s3-spoolss: _spoolss_OpenPrinterEx needs to wipe out policy handle upon failure.
[tprouty/samba.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 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677
678 static void notify_one_value(struct spoolss_notify_msg *msg,
679                              SPOOL_NOTIFY_INFO_DATA *data,
680                              TALLOC_CTX *mem_ctx)
681 {
682         data->notify_data.value[0] = msg->notify.value[0];
683         data->notify_data.value[1] = 0;
684 }
685
686 static void notify_string(struct spoolss_notify_msg *msg,
687                           SPOOL_NOTIFY_INFO_DATA *data,
688                           TALLOC_CTX *mem_ctx)
689 {
690         UNISTR2 unistr;
691
692         /* The length of the message includes the trailing \0 */
693
694         init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695
696         data->notify_data.data.length = msg->len * 2;
697         data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
698
699         if (!data->notify_data.data.string) {
700                 data->notify_data.data.length = 0;
701                 return;
702         }
703
704         memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 }
706
707 static void notify_system_time(struct spoolss_notify_msg *msg,
708                                SPOOL_NOTIFY_INFO_DATA *data,
709                                TALLOC_CTX *mem_ctx)
710 {
711         SYSTEMTIME systime;
712         prs_struct ps;
713
714         if (msg->len != sizeof(time_t)) {
715                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
716                           msg->len));
717                 return;
718         }
719
720         if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
721                 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
722                 return;
723         }
724
725         if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
726                 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
727                 prs_mem_free(&ps);
728                 return;
729         }
730
731         if (!spoolss_io_system_time("", &ps, 0, &systime)) {
732                 prs_mem_free(&ps);
733                 return;
734         }
735
736         data->notify_data.data.length = prs_offset(&ps);
737         if (prs_offset(&ps)) {
738                 data->notify_data.data.string = (uint16 *)
739                         TALLOC(mem_ctx, prs_offset(&ps));
740                 if (!data->notify_data.data.string) {
741                         prs_mem_free(&ps);
742                         return;
743                 }
744                 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
745         } else {
746                 data->notify_data.data.string = NULL;
747         }
748
749         prs_mem_free(&ps);
750 }
751
752 struct notify2_message_table {
753         const char *name;
754         void (*fn)(struct spoolss_notify_msg *msg,
755                    SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 };
757
758 static struct notify2_message_table printer_notify_table[] = {
759         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
760         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
761         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
762         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
763         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
764         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
765         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
766         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
767         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
768         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
769         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
770         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
771         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
772         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
773         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
774         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
775         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
776         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
777         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 };
779
780 static struct notify2_message_table job_notify_table[] = {
781         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
782         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
783         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
784         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
785         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
786         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
787         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
788         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
789         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
790         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
791         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
792         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
793         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
794         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
795         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
796         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
797         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
798         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
799         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
800         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
801         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
802         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
803         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
804         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
805 };
806
807
808 /***********************************************************************
809  Allocate talloc context for container object
810  **********************************************************************/
811
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 {
814         if ( !ctr )
815                 return;
816
817         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
818
819         return;
820 }
821
822 /***********************************************************************
823  release all allocated memory and zero out structure
824  **********************************************************************/
825
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 {
828         if ( !ctr )
829                 return;
830
831         if ( ctr->ctx )
832                 talloc_destroy(ctr->ctx);
833
834         ZERO_STRUCTP(ctr);
835
836         return;
837 }
838
839 /***********************************************************************
840  **********************************************************************/
841
842 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
843 {
844         if ( !ctr )
845                 return NULL;
846
847         return ctr->ctx;
848 }
849
850 /***********************************************************************
851  **********************************************************************/
852
853 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
854 {
855         if ( !ctr || !ctr->msg_groups )
856                 return NULL;
857
858         if ( idx >= ctr->num_groups )
859                 return NULL;
860
861         return &ctr->msg_groups[idx];
862
863 }
864
865 /***********************************************************************
866  How many groups of change messages do we have ?
867  **********************************************************************/
868
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 {
871         if ( !ctr )
872                 return 0;
873
874         return ctr->num_groups;
875 }
876
877 /***********************************************************************
878  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879  **********************************************************************/
880
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
882 {
883         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
884         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
885         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
886         int                             i, new_slot;
887
888         if ( !ctr || !msg )
889                 return 0;
890
891         /* loop over all groups looking for a matching printer name */
892
893         for ( i=0; i<ctr->num_groups; i++ ) {
894                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895                         break;
896         }
897
898         /* add a new group? */
899
900         if ( i == ctr->num_groups ) {
901                 ctr->num_groups++;
902
903                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
904                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905                         return 0;
906                 }
907                 ctr->msg_groups = groups;
908
909                 /* clear the new entry and set the printer name */
910
911                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
912                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913         }
914
915         /* add the change messages; 'i' is the correct index now regardless */
916
917         msg_grp = &ctr->msg_groups[i];
918
919         msg_grp->num_msgs++;
920
921         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
922                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923                 return 0;
924         }
925         msg_grp->msgs = msg_list;
926
927         new_slot = msg_grp->num_msgs-1;
928         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
929
930         /* need to allocate own copy of data */
931
932         if ( msg->len != 0 )
933                 msg_grp->msgs[new_slot].notify.data = (char *)
934                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
935
936         return ctr->num_groups;
937 }
938
939 /***********************************************************************
940  Send a change notication message on all handles which have a call
941  back registered
942  **********************************************************************/
943
944 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
945 {
946         Printer_entry            *p;
947         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
948         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
949         SPOOLSS_NOTIFY_MSG       *messages;
950         int                      sending_msg_count;
951
952         if ( !msg_group ) {
953                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954                 return;
955         }
956
957         messages = msg_group->msgs;
958
959         if ( !messages ) {
960                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961                 return;
962         }
963
964         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
965
966         /* loop over all printers */
967
968         for (p = printers_list; p; p = p->next) {
969                 SPOOL_NOTIFY_INFO_DATA *data;
970                 uint32  data_len = 0;
971                 uint32  id;
972                 int     i;
973
974                 /* Is there notification on this handle? */
975
976                 if ( !p->notify.client_connected )
977                         continue;
978
979                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
980
981                 /* For this printer?  Print servers always receive
982                    notifications. */
983
984                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
985                     ( !strequal(msg_group->printername, p->sharename) ) )
986                         continue;
987
988                 DEBUG(10,("Our printer\n"));
989
990                 /* allocate the max entries possible */
991
992                 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
993                 if (!data) {
994                         return;
995                 }
996
997                 ZERO_STRUCTP(data);
998
999                 /* build the array of change notifications */
1000
1001                 sending_msg_count = 0;
1002
1003                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1004                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1005
1006                         /* Are we monitoring this event? */
1007
1008                         if (!is_monitoring_event(p, msg->type, msg->field))
1009                                 continue;
1010
1011                         sending_msg_count++;
1012
1013
1014                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1015                                 msg->type, msg->field, p->sharename));
1016
1017                         /*
1018                          * if the is a printer notification handle and not a job notification
1019                          * type, then set the id to 0.  Other wise just use what was specified
1020                          * in the message.
1021                          *
1022                          * When registering change notification on a print server handle
1023                          * we always need to send back the id (snum) matching the printer
1024                          * for which the change took place.  For change notify registered
1025                          * on a printer handle, this does not matter and the id should be 0.
1026                          *
1027                          * --jerry
1028                          */
1029
1030                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1031                                 id = 0;
1032                         else
1033                                 id = msg->id;
1034
1035
1036                         /* Convert unix jobid to smb jobid */
1037
1038                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1039                                 id = sysjob_to_jobid(msg->id);
1040
1041                                 if (id == -1) {
1042                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1043                                         goto done;
1044                                 }
1045                         }
1046
1047                         construct_info_data( &data[data_len], msg->type, msg->field, id );
1048
1049                         switch(msg->type) {
1050                         case PRINTER_NOTIFY_TYPE:
1051                                 if ( printer_notify_table[msg->field].fn )
1052                                         printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1053                                 break;
1054
1055                         case JOB_NOTIFY_TYPE:
1056                                 if ( job_notify_table[msg->field].fn )
1057                                         job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1058                                 break;
1059
1060                         default:
1061                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1062                                 goto done;
1063                         }
1064
1065                         data_len++;
1066                 }
1067
1068                 if ( sending_msg_count ) {
1069                         rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1070                                         data_len, data, p->notify.change, 0 );
1071                 }
1072         }
1073
1074 done:
1075         DEBUG(8,("send_notify2_changes: Exit...\n"));
1076         return;
1077 }
1078
1079 /***********************************************************************
1080  **********************************************************************/
1081
1082 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 {
1084
1085         uint32 tv_sec, tv_usec;
1086         size_t offset = 0;
1087
1088         /* Unpack message */
1089
1090         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1091                              msg->printer);
1092
1093         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1094                                 &tv_sec, &tv_usec,
1095                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1096
1097         if (msg->len == 0)
1098                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1099                            &msg->notify.value[0], &msg->notify.value[1]);
1100         else
1101                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1102                            &msg->len, &msg->notify.data);
1103
1104         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1105                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1106
1107         tv->tv_sec = tv_sec;
1108         tv->tv_usec = tv_usec;
1109
1110         if (msg->len == 0)
1111                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1112                           msg->notify.value[1]));
1113         else
1114                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1115
1116         return True;
1117 }
1118
1119 /********************************************************************
1120  Receive a notify2 message list
1121  ********************************************************************/
1122
1123 static void receive_notify2_message_list(struct messaging_context *msg,
1124                                          void *private_data,
1125                                          uint32_t msg_type,
1126                                          struct server_id server_id,
1127                                          DATA_BLOB *data)
1128 {
1129         size_t                  msg_count, i;
1130         char                    *buf = (char *)data->data;
1131         char                    *msg_ptr;
1132         size_t                  msg_len;
1133         SPOOLSS_NOTIFY_MSG      notify;
1134         SPOOLSS_NOTIFY_MSG_CTR  messages;
1135         int                     num_groups;
1136
1137         if (data->length < 4) {
1138                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1139                 return;
1140         }
1141
1142         msg_count = IVAL(buf, 0);
1143         msg_ptr = buf + 4;
1144
1145         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1146
1147         if (msg_count == 0) {
1148                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1149                 return;
1150         }
1151
1152         /* initialize the container */
1153
1154         ZERO_STRUCT( messages );
1155         notify_msg_ctr_init( &messages );
1156
1157         /*
1158          * build message groups for each printer identified
1159          * in a change_notify msg.  Remember that a PCN message
1160          * includes the handle returned for the srv_spoolss_replyopenprinter()
1161          * call.  Therefore messages are grouped according to printer handle.
1162          */
1163
1164         for ( i=0; i<msg_count; i++ ) {
1165                 struct timeval msg_tv;
1166
1167                 if (msg_ptr + 4 - buf > data->length) {
1168                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1169                         return;
1170                 }
1171
1172                 msg_len = IVAL(msg_ptr,0);
1173                 msg_ptr += 4;
1174
1175                 if (msg_ptr + msg_len - buf > data->length) {
1176                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1177                         return;
1178                 }
1179
1180                 /* unpack messages */
1181
1182                 ZERO_STRUCT( notify );
1183                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1184                 msg_ptr += msg_len;
1185
1186                 /* add to correct list in container */
1187
1188                 notify_msg_ctr_addmsg( &messages, &notify );
1189
1190                 /* free memory that might have been allocated by notify2_unpack_msg() */
1191
1192                 if ( notify.len != 0 )
1193                         SAFE_FREE( notify.notify.data );
1194         }
1195
1196         /* process each group of messages */
1197
1198         num_groups = notify_msg_ctr_numgroups( &messages );
1199         for ( i=0; i<num_groups; i++ )
1200                 send_notify2_changes( &messages, i );
1201
1202
1203         /* cleanup */
1204
1205         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1206
1207         notify_msg_ctr_destroy( &messages );
1208
1209         return;
1210 }
1211
1212 /********************************************************************
1213  Send a message to ourself about new driver being installed
1214  so we can upgrade the information for each printer bound to this
1215  driver
1216  ********************************************************************/
1217
1218 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1219 {
1220         int len = strlen(drivername);
1221
1222         if (!len)
1223                 return False;
1224
1225         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1226                 drivername));
1227
1228         messaging_send_buf(smbd_messaging_context(), procid_self(),
1229                            MSG_PRINTER_DRVUPGRADE,
1230                            (uint8 *)drivername, len+1);
1231
1232         return True;
1233 }
1234
1235 /**********************************************************************
1236  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1237  over all printers, upgrading ones as necessary
1238  **********************************************************************/
1239
1240 void do_drv_upgrade_printer(struct messaging_context *msg,
1241                             void *private_data,
1242                             uint32_t msg_type,
1243                             struct server_id server_id,
1244                             DATA_BLOB *data)
1245 {
1246         fstring drivername;
1247         int snum;
1248         int n_services = lp_numservices();
1249         size_t len;
1250
1251         len = MIN(data->length,sizeof(drivername)-1);
1252         strncpy(drivername, (const char *)data->data, len);
1253
1254         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1255
1256         /* Iterate the printer list */
1257
1258         for (snum=0; snum<n_services; snum++)
1259         {
1260                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1261                 {
1262                         WERROR result;
1263                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1264
1265                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1266                         if (!W_ERROR_IS_OK(result))
1267                                 continue;
1268
1269                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1270                         {
1271                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1272
1273                                 /* all we care about currently is the change_id */
1274
1275                                 result = mod_a_printer(printer, 2);
1276                                 if (!W_ERROR_IS_OK(result)) {
1277                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1278                                                 win_errstr(result)));
1279                                 }
1280                         }
1281
1282                         free_a_printer(&printer, 2);
1283                 }
1284         }
1285
1286         /* all done */
1287 }
1288
1289 /********************************************************************
1290  Update the cache for all printq's with a registered client
1291  connection
1292  ********************************************************************/
1293
1294 void update_monitored_printq_cache( void )
1295 {
1296         Printer_entry *printer = printers_list;
1297         int snum;
1298
1299         /* loop through all printers and update the cache where
1300            client_connected == True */
1301         while ( printer )
1302         {
1303                 if ( (printer->printer_type == SPLHND_PRINTER)
1304                         && printer->notify.client_connected )
1305                 {
1306                         snum = print_queue_snum(printer->sharename);
1307                         print_queue_status( snum, NULL, NULL );
1308                 }
1309
1310                 printer = printer->next;
1311         }
1312
1313         return;
1314 }
1315 /********************************************************************
1316  Send a message to ourself about new driver being installed
1317  so we can upgrade the information for each printer bound to this
1318  driver
1319  ********************************************************************/
1320
1321 static bool srv_spoolss_reset_printerdata(char* drivername)
1322 {
1323         int len = strlen(drivername);
1324
1325         if (!len)
1326                 return False;
1327
1328         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1329                 drivername));
1330
1331         messaging_send_buf(smbd_messaging_context(), procid_self(),
1332                            MSG_PRINTERDATA_INIT_RESET,
1333                            (uint8 *)drivername, len+1);
1334
1335         return True;
1336 }
1337
1338 /**********************************************************************
1339  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1340  over all printers, resetting printer data as neessary
1341  **********************************************************************/
1342
1343 void reset_all_printerdata(struct messaging_context *msg,
1344                            void *private_data,
1345                            uint32_t msg_type,
1346                            struct server_id server_id,
1347                            DATA_BLOB *data)
1348 {
1349         fstring drivername;
1350         int snum;
1351         int n_services = lp_numservices();
1352         size_t len;
1353
1354         len = MIN( data->length, sizeof(drivername)-1 );
1355         strncpy( drivername, (const char *)data->data, len );
1356
1357         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1358
1359         /* Iterate the printer list */
1360
1361         for ( snum=0; snum<n_services; snum++ )
1362         {
1363                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1364                 {
1365                         WERROR result;
1366                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1367
1368                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1369                         if ( !W_ERROR_IS_OK(result) )
1370                                 continue;
1371
1372                         /*
1373                          * if the printer is bound to the driver,
1374                          * then reset to the new driver initdata
1375                          */
1376
1377                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1378                         {
1379                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1380
1381                                 if ( !set_driver_init(printer, 2) ) {
1382                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1383                                                 printer->info_2->printername, printer->info_2->drivername));
1384                                 }
1385
1386                                 result = mod_a_printer( printer, 2 );
1387                                 if ( !W_ERROR_IS_OK(result) ) {
1388                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1389                                                 get_dos_error_msg(result)));
1390                                 }
1391                         }
1392
1393                         free_a_printer( &printer, 2 );
1394                 }
1395         }
1396
1397         /* all done */
1398
1399         return;
1400 }
1401
1402 /****************************************************************
1403  _spoolss_OpenPrinter
1404 ****************************************************************/
1405
1406 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1407                             struct spoolss_OpenPrinter *r)
1408 {
1409         struct spoolss_OpenPrinterEx e;
1410         WERROR werr;
1411
1412         ZERO_STRUCT(e.in.userlevel);
1413
1414         e.in.printername        = r->in.printername;
1415         e.in.datatype           = r->in.datatype;
1416         e.in.devmode_ctr        = r->in.devmode_ctr;
1417         e.in.access_mask        = r->in.access_mask;
1418         e.in.level              = 0;
1419
1420         e.out.handle            = r->out.handle;
1421
1422         werr = _spoolss_OpenPrinterEx(p, &e);
1423
1424         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1425                 /* OpenPrinterEx returns this for a bad
1426                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1427                  * instead.
1428                  */
1429                 werr = WERR_INVALID_PRINTER_NAME;
1430         }
1431
1432         return werr;
1433 }
1434
1435 /********************************************************************
1436  FIXME: temporary convert_devicemode_new function
1437  ********************************************************************/
1438
1439 static bool convert_devicemode_new(const char *printername,
1440                                    struct spoolss_DeviceMode *devmode,
1441                                    NT_DEVICEMODE **pp_nt_devmode)
1442 {
1443         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1444
1445         /*
1446          * Ensure nt_devmode is a valid pointer
1447          * as we will be overwriting it.
1448          */
1449
1450         if (nt_devmode == NULL) {
1451                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1452                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1453                         return false;
1454         }
1455
1456         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1457         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1458
1459         nt_devmode->specversion         = devmode->specversion;
1460         nt_devmode->driverversion       = devmode->driverversion;
1461         nt_devmode->size                = devmode->size;
1462         nt_devmode->fields              = devmode->fields;
1463         nt_devmode->orientation         = devmode->orientation;
1464         nt_devmode->papersize           = devmode->papersize;
1465         nt_devmode->paperlength         = devmode->paperlength;
1466         nt_devmode->paperwidth          = devmode->paperwidth;
1467         nt_devmode->scale               = devmode->scale;
1468         nt_devmode->copies              = devmode->copies;
1469         nt_devmode->defaultsource       = devmode->defaultsource;
1470         nt_devmode->printquality        = devmode->printquality;
1471         nt_devmode->color               = devmode->color;
1472         nt_devmode->duplex              = devmode->duplex;
1473         nt_devmode->yresolution         = devmode->yresolution;
1474         nt_devmode->ttoption            = devmode->ttoption;
1475         nt_devmode->collate             = devmode->collate;
1476
1477         nt_devmode->logpixels           = devmode->logpixels;
1478         nt_devmode->bitsperpel          = devmode->bitsperpel;
1479         nt_devmode->pelswidth           = devmode->pelswidth;
1480         nt_devmode->pelsheight          = devmode->pelsheight;
1481         nt_devmode->displayflags        = devmode->displayflags;
1482         nt_devmode->displayfrequency    = devmode->displayfrequency;
1483         nt_devmode->icmmethod           = devmode->icmmethod;
1484         nt_devmode->icmintent           = devmode->icmintent;
1485         nt_devmode->mediatype           = devmode->mediatype;
1486         nt_devmode->dithertype          = devmode->dithertype;
1487         nt_devmode->reserved1           = devmode->reserved1;
1488         nt_devmode->reserved2           = devmode->reserved2;
1489         nt_devmode->panningwidth        = devmode->panningwidth;
1490         nt_devmode->panningheight       = devmode->panningheight;
1491
1492         /*
1493          * Only change private and driverextra if the incoming devmode
1494          * has a new one. JRA.
1495          */
1496
1497         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1498                 SAFE_FREE(nt_devmode->nt_dev_private);
1499                 nt_devmode->driverextra = devmode->__driverextra_length;
1500                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1501                         return false;
1502                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1503         }
1504
1505         *pp_nt_devmode = nt_devmode;
1506
1507         return true;
1508 }
1509
1510 /****************************************************************
1511  _spoolss_OpenPrinterEx
1512 ****************************************************************/
1513
1514 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1515                               struct spoolss_OpenPrinterEx *r)
1516 {
1517         POLICY_HND              *handle = r->out.handle;
1518         char *name = CONST_DISCARD(char *, r->in.printername);
1519         int snum;
1520         Printer_entry *Printer=NULL;
1521
1522         if (!name) {
1523                 return WERR_INVALID_PARAM;
1524         }
1525
1526         /* some sanity check because you can open a printer or a print server */
1527         /* aka: \\server\printer or \\server */
1528
1529         DEBUGADD(3,("checking name: %s\n",name));
1530
1531         if (!open_printer_hnd(p, handle, name, 0)) {
1532                 ZERO_STRUCTP(r->out.handle);
1533                 return WERR_INVALID_PARAM;
1534         }
1535
1536         Printer=find_printer_index_by_hnd(p, handle);
1537         if ( !Printer ) {
1538                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1539                         "handle we created for printer %s\n", name ));
1540                 close_printer_handle(p,handle);
1541                 ZERO_STRUCTP(r->out.handle);
1542                 return WERR_INVALID_PARAM;
1543         }
1544
1545         /*
1546          * First case: the user is opening the print server:
1547          *
1548          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1549          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1550          *
1551          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1552          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1553          * or if the user is listed in the smb.conf printer admin parameter.
1554          *
1555          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1556          * client view printer folder, but does not show the MSAPW.
1557          *
1558          * Note: this test needs code to check access rights here too. Jeremy
1559          * could you look at this?
1560          *
1561          * Second case: the user is opening a printer:
1562          * NT doesn't let us connect to a printer if the connecting user
1563          * doesn't have print permission.
1564          *
1565          * Third case: user is opening a Port Monitor
1566          * access checks same as opening a handle to the print server.
1567          */
1568
1569         switch (Printer->printer_type )
1570         {
1571         case SPLHND_SERVER:
1572         case SPLHND_PORTMON_TCP:
1573         case SPLHND_PORTMON_LOCAL:
1574                 /* Printserver handles use global struct... */
1575
1576                 snum = -1;
1577
1578                 /* Map standard access rights to object specific access rights */
1579
1580                 se_map_standard(&r->in.access_mask,
1581                                 &printserver_std_mapping);
1582
1583                 /* Deny any object specific bits that don't apply to print
1584                    servers (i.e printer and job specific bits) */
1585
1586                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1587
1588                 if (r->in.access_mask &
1589                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1590                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1591                         close_printer_handle(p, handle);
1592                         ZERO_STRUCTP(r->out.handle);
1593                         return WERR_ACCESS_DENIED;
1594                 }
1595
1596                 /* Allow admin access */
1597
1598                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1599                 {
1600                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1601
1602                         if (!lp_ms_add_printer_wizard()) {
1603                                 close_printer_handle(p, handle);
1604                                 ZERO_STRUCTP(r->out.handle);
1605                                 return WERR_ACCESS_DENIED;
1606                         }
1607
1608                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1609                            and not a printer admin, then fail */
1610
1611                         if ((p->server_info->utok.uid != 0) &&
1612                             !user_has_privileges(p->server_info->ptok,
1613                                                  &se_printop ) &&
1614                             !token_contains_name_in_list(
1615                                     uidtoname(p->server_info->utok.uid),
1616                                     NULL, NULL,
1617                                     p->server_info->ptok,
1618                                     lp_printer_admin(snum))) {
1619                                 close_printer_handle(p, handle);
1620                                 ZERO_STRUCTP(r->out.handle);
1621                                 return WERR_ACCESS_DENIED;
1622                         }
1623
1624                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1625                 }
1626                 else
1627                 {
1628                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1629                 }
1630
1631                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1632                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1633
1634                 /* We fall through to return WERR_OK */
1635                 break;
1636
1637         case SPLHND_PRINTER:
1638                 /* NT doesn't let us connect to a printer if the connecting user
1639                    doesn't have print permission.  */
1640
1641                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1642                         close_printer_handle(p, handle);
1643                         ZERO_STRUCTP(r->out.handle);
1644                         return WERR_BADFID;
1645                 }
1646
1647                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1648
1649                 /* map an empty access mask to the minimum access mask */
1650                 if (r->in.access_mask == 0x0)
1651                         r->in.access_mask = PRINTER_ACCESS_USE;
1652
1653                 /*
1654                  * If we are not serving the printer driver for this printer,
1655                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1656                  * will keep NT clients happy  --jerry
1657                  */
1658
1659                 if (lp_use_client_driver(snum)
1660                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1661                 {
1662                         r->in.access_mask = PRINTER_ACCESS_USE;
1663                 }
1664
1665                 /* check smb.conf parameters and the the sec_desc */
1666
1667                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1668                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1669                         ZERO_STRUCTP(r->out.handle);
1670                         return WERR_ACCESS_DENIED;
1671                 }
1672
1673                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1674                                    p->server_info->ptok, snum) ||
1675                     !print_access_check(p->server_info, snum,
1676                                         r->in.access_mask)) {
1677                         DEBUG(3, ("access DENIED for printer open\n"));
1678                         close_printer_handle(p, handle);
1679                         ZERO_STRUCTP(r->out.handle);
1680                         return WERR_ACCESS_DENIED;
1681                 }
1682
1683                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1684                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1685                         close_printer_handle(p, handle);
1686                         ZERO_STRUCTP(r->out.handle);
1687                         return WERR_ACCESS_DENIED;
1688                 }
1689
1690                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1691                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1692                 else
1693                         r->in.access_mask = PRINTER_ACCESS_USE;
1694
1695                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1696                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1697
1698                 break;
1699
1700         default:
1701                 /* sanity check to prevent programmer error */
1702                 ZERO_STRUCTP(r->out.handle);
1703                 return WERR_BADFID;
1704         }
1705
1706         Printer->access_granted = r->in.access_mask;
1707
1708         /*
1709          * If the client sent a devmode in the OpenPrinter() call, then
1710          * save it here in case we get a job submission on this handle
1711          */
1712
1713          if ( (Printer->printer_type != SPLHND_SERVER)
1714                 && r->in.devmode_ctr.devmode )
1715          {
1716                 convert_devicemode_new(Printer->sharename,
1717                                        r->in.devmode_ctr.devmode,
1718                                        &Printer->nt_devmode);
1719          }
1720
1721 #if 0   /* JERRY -- I'm doubtful this is really effective */
1722         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1723            optimization in Windows 2000 clients  --jerry */
1724
1725         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1726                 && (RA_WIN2K == get_remote_arch()) )
1727         {
1728                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1729                 sys_usleep( 500000 );
1730         }
1731 #endif
1732
1733         return WERR_OK;
1734 }
1735
1736 /****************************************************************************
1737 ****************************************************************************/
1738
1739 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1740                                               NT_PRINTER_INFO_LEVEL_2 *d)
1741 {
1742         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1743
1744         if (!r || !d) {
1745                 return false;
1746         }
1747
1748         d->attributes           = r->attributes;
1749         d->priority             = r->priority;
1750         d->default_priority     = r->defaultpriority;
1751         d->starttime            = r->starttime;
1752         d->untiltime            = r->untiltime;
1753         d->status               = r->status;
1754         d->cjobs                = r->cjobs;
1755
1756         fstrcpy(d->servername,  r->servername);
1757         fstrcpy(d->printername, r->printername);
1758         fstrcpy(d->sharename,   r->sharename);
1759         fstrcpy(d->portname,    r->portname);
1760         fstrcpy(d->drivername,  r->drivername);
1761         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1762         fstrcpy(d->location,    r->location);
1763         fstrcpy(d->sepfile,     r->sepfile);
1764         fstrcpy(d->printprocessor, r->printprocessor);
1765         fstrcpy(d->datatype,    r->datatype);
1766         fstrcpy(d->parameters,  r->parameters);
1767
1768         return true;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1775                                      NT_PRINTER_INFO_LEVEL *printer)
1776 {
1777         bool ret;
1778
1779         switch (info_ctr->level) {
1780         case 2:
1781                 /* allocate memory if needed.  Messy because
1782                    convert_printer_info is used to update an existing
1783                    printer or build a new one */
1784
1785                 if (!printer->info_2) {
1786                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1787                         if (!printer->info_2) {
1788                                 DEBUG(0,("convert_printer_info_new: "
1789                                         "talloc() failed!\n"));
1790                                 return false;
1791                         }
1792                 }
1793
1794                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1795                                                         printer->info_2);
1796                 printer->info_2->setuptime = time(NULL);
1797                 return ret;
1798         }
1799
1800         return false;
1801 }
1802
1803 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1804                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1805 {
1806         bool result = True;
1807
1808         switch (level) {
1809                 case 3:
1810                         printer->info_3=NULL;
1811                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1812                                 result = False;
1813                         break;
1814                 case 6:
1815                         printer->info_6=NULL;
1816                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1817                                 result = False;
1818                         break;
1819                 default:
1820                         break;
1821         }
1822
1823         return result;
1824 }
1825
1826 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1827                                 NT_DEVICEMODE **pp_nt_devmode)
1828 {
1829         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1830
1831         /*
1832          * Ensure nt_devmode is a valid pointer
1833          * as we will be overwriting it.
1834          */
1835
1836         if (nt_devmode == NULL) {
1837                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1838                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1839                         return False;
1840         }
1841
1842         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1843         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1844
1845         nt_devmode->specversion=devmode->specversion;
1846         nt_devmode->driverversion=devmode->driverversion;
1847         nt_devmode->size=devmode->size;
1848         nt_devmode->fields=devmode->fields;
1849         nt_devmode->orientation=devmode->orientation;
1850         nt_devmode->papersize=devmode->papersize;
1851         nt_devmode->paperlength=devmode->paperlength;
1852         nt_devmode->paperwidth=devmode->paperwidth;
1853         nt_devmode->scale=devmode->scale;
1854         nt_devmode->copies=devmode->copies;
1855         nt_devmode->defaultsource=devmode->defaultsource;
1856         nt_devmode->printquality=devmode->printquality;
1857         nt_devmode->color=devmode->color;
1858         nt_devmode->duplex=devmode->duplex;
1859         nt_devmode->yresolution=devmode->yresolution;
1860         nt_devmode->ttoption=devmode->ttoption;
1861         nt_devmode->collate=devmode->collate;
1862
1863         nt_devmode->logpixels=devmode->logpixels;
1864         nt_devmode->bitsperpel=devmode->bitsperpel;
1865         nt_devmode->pelswidth=devmode->pelswidth;
1866         nt_devmode->pelsheight=devmode->pelsheight;
1867         nt_devmode->displayflags=devmode->displayflags;
1868         nt_devmode->displayfrequency=devmode->displayfrequency;
1869         nt_devmode->icmmethod=devmode->icmmethod;
1870         nt_devmode->icmintent=devmode->icmintent;
1871         nt_devmode->mediatype=devmode->mediatype;
1872         nt_devmode->dithertype=devmode->dithertype;
1873         nt_devmode->reserved1=devmode->reserved1;
1874         nt_devmode->reserved2=devmode->reserved2;
1875         nt_devmode->panningwidth=devmode->panningwidth;
1876         nt_devmode->panningheight=devmode->panningheight;
1877
1878         /*
1879          * Only change private and driverextra if the incoming devmode
1880          * has a new one. JRA.
1881          */
1882
1883         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1884                 SAFE_FREE(nt_devmode->nt_dev_private);
1885                 nt_devmode->driverextra=devmode->driverextra;
1886                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1887                         return False;
1888                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1889         }
1890
1891         *pp_nt_devmode = nt_devmode;
1892
1893         return True;
1894 }
1895
1896 /********************************************************************
1897  * _spoolss_enddocprinter_internal.
1898  ********************************************************************/
1899
1900 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1901 {
1902         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1903         int snum;
1904
1905         if (!Printer) {
1906                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1907                 return WERR_BADFID;
1908         }
1909
1910         if (!get_printer_snum(p, handle, &snum, NULL))
1911                 return WERR_BADFID;
1912
1913         Printer->document_started=False;
1914         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1915         /* error codes unhandled so far ... */
1916
1917         return WERR_OK;
1918 }
1919
1920 /****************************************************************
1921  _spoolss_ClosePrinter
1922 ****************************************************************/
1923
1924 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1925                              struct spoolss_ClosePrinter *r)
1926 {
1927         POLICY_HND *handle = r->in.handle;
1928
1929         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1930
1931         if (Printer && Printer->document_started)
1932                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1933
1934         if (!close_printer_handle(p, handle))
1935                 return WERR_BADFID;
1936
1937         /* clear the returned printer handle.  Observed behavior
1938            from Win2k server.  Don't think this really matters.
1939            Previous code just copied the value of the closed
1940            handle.    --jerry */
1941
1942         ZERO_STRUCTP(r->out.handle);
1943
1944         return WERR_OK;
1945 }
1946
1947 /****************************************************************
1948  _spoolss_DeletePrinter
1949 ****************************************************************/
1950
1951 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1952                               struct spoolss_DeletePrinter *r)
1953 {
1954         POLICY_HND *handle = r->in.handle;
1955         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1956         WERROR result;
1957
1958         if (Printer && Printer->document_started)
1959                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1960
1961         result = delete_printer_handle(p, handle);
1962
1963         update_c_setprinter(False);
1964
1965         return result;
1966 }
1967
1968 /*******************************************************************
1969  * static function to lookup the version id corresponding to an
1970  * long architecture string
1971  ******************************************************************/
1972
1973 static int get_version_id (char * arch)
1974 {
1975         int i;
1976         struct table_node archi_table[]= {
1977
1978                 {"Windows 4.0",          "WIN40",       0 },
1979                 {"Windows NT x86",       "W32X86",      2 },
1980                 {"Windows NT R4000",     "W32MIPS",     2 },
1981                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1982                 {"Windows NT PowerPC",   "W32PPC",      2 },
1983                 {"Windows IA64",         "IA64",        3 },
1984                 {"Windows x64",          "x64",         3 },
1985                 {NULL,                   "",            -1 }
1986         };
1987
1988         for (i=0; archi_table[i].long_archi != NULL; i++)
1989         {
1990                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1991                         return (archi_table[i].version);
1992         }
1993
1994         return -1;
1995 }
1996
1997 /****************************************************************
1998  _spoolss_DeletePrinterDriver
1999 ****************************************************************/
2000
2001 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2002                                     struct spoolss_DeletePrinterDriver *r)
2003 {
2004         char *driver;
2005         char *arch;
2006         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2007         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2008         int                             version;
2009         WERROR                          status;
2010         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2011         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2012
2013         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2014            and not a printer admin, then fail */
2015
2016         if ( (p->server_info->utok.uid != 0)
2017                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2018                 && !token_contains_name_in_list(
2019                         uidtoname(p->server_info->utok.uid), NULL,
2020                         NULL, p->server_info->ptok,
2021                         lp_printer_admin(-1)) )
2022         {
2023                 return WERR_ACCESS_DENIED;
2024         }
2025
2026         driver = CONST_DISCARD(char *, r->in.driver);
2027         arch   = CONST_DISCARD(char *, r->in.architecture);
2028
2029         /* check that we have a valid driver name first */
2030
2031         if ((version=get_version_id(arch)) == -1)
2032                 return WERR_INVALID_ENVIRONMENT;
2033
2034         ZERO_STRUCT(info);
2035         ZERO_STRUCT(info_win2k);
2036
2037         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2038         {
2039                 /* try for Win2k driver if "Windows NT x86" */
2040
2041                 if ( version == 2 ) {
2042                         version = 3;
2043                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2044                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2045                                 goto done;
2046                         }
2047                 }
2048                 /* otherwise it was a failure */
2049                 else {
2050                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2051                         goto done;
2052                 }
2053
2054         }
2055
2056         if (printer_driver_in_use(info.info_3)) {
2057                 status = WERR_PRINTER_DRIVER_IN_USE;
2058                 goto done;
2059         }
2060
2061         if ( version == 2 )
2062         {
2063                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2064                 {
2065                         /* if we get to here, we now have 2 driver info structures to remove */
2066                         /* remove the Win2k driver first*/
2067
2068                         status_win2k = delete_printer_driver(
2069                                 p, info_win2k.info_3, 3, False );
2070                         free_a_printer_driver( info_win2k, 3 );
2071
2072                         /* this should not have failed---if it did, report to client */
2073                         if ( !W_ERROR_IS_OK(status_win2k) )
2074                         {
2075                                 status = status_win2k;
2076                                 goto done;
2077                         }
2078                 }
2079         }
2080
2081         status = delete_printer_driver(p, info.info_3, version, False);
2082
2083         /* if at least one of the deletes succeeded return OK */
2084
2085         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2086                 status = WERR_OK;
2087
2088 done:
2089         free_a_printer_driver( info, 3 );
2090
2091         return status;
2092 }
2093
2094 /****************************************************************
2095  _spoolss_DeletePrinterDriverEx
2096 ****************************************************************/
2097
2098 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2099                                       struct spoolss_DeletePrinterDriverEx *r)
2100 {
2101         char *driver;
2102         char *arch;
2103         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2104         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2105         int                             version;
2106         uint32_t                        flags = r->in.delete_flags;
2107         bool                            delete_files;
2108         WERROR                          status;
2109         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2110         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2111
2112         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2113            and not a printer admin, then fail */
2114
2115         if ( (p->server_info->utok.uid != 0)
2116                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2117                 && !token_contains_name_in_list(
2118                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2119                         p->server_info->ptok, lp_printer_admin(-1)) )
2120         {
2121                 return WERR_ACCESS_DENIED;
2122         }
2123
2124         driver = CONST_DISCARD(char *, r->in.driver);
2125         arch   = CONST_DISCARD(char *, r->in.architecture);
2126
2127         /* check that we have a valid driver name first */
2128         if ((version=get_version_id(arch)) == -1) {
2129                 /* this is what NT returns */
2130                 return WERR_INVALID_ENVIRONMENT;
2131         }
2132
2133         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2134                 version = r->in.version;
2135
2136         ZERO_STRUCT(info);
2137         ZERO_STRUCT(info_win2k);
2138
2139         status = get_a_printer_driver(&info, 3, driver, arch, version);
2140
2141         if ( !W_ERROR_IS_OK(status) )
2142         {
2143                 /*
2144                  * if the client asked for a specific version,
2145                  * or this is something other than Windows NT x86,
2146                  * then we've failed
2147                  */
2148
2149                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2150                         goto done;
2151
2152                 /* try for Win2k driver if "Windows NT x86" */
2153
2154                 version = 3;
2155                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2156                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2157                         goto done;
2158                 }
2159         }
2160
2161         if ( printer_driver_in_use(info.info_3) ) {
2162                 status = WERR_PRINTER_DRIVER_IN_USE;
2163                 goto done;
2164         }
2165
2166         /*
2167          * we have a couple of cases to consider.
2168          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2169          *     then the delete should fail if **any** files overlap with
2170          *     other drivers
2171          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2172          *     non-overlapping files
2173          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2174          *     is set, the do not delete any files
2175          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2176          */
2177
2178         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2179
2180         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2181
2182         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183                 /* no idea of the correct error here */
2184                 status = WERR_ACCESS_DENIED;
2185                 goto done;
2186         }
2187
2188
2189         /* also check for W32X86/3 if necessary; maybe we already have? */
2190
2191         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2192                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2193                 {
2194
2195                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2196                                 /* no idea of the correct error here */
2197                                 free_a_printer_driver( info_win2k, 3 );
2198                                 status = WERR_ACCESS_DENIED;
2199                                 goto done;
2200                         }
2201
2202                         /* if we get to here, we now have 2 driver info structures to remove */
2203                         /* remove the Win2k driver first*/
2204
2205                         status_win2k = delete_printer_driver(
2206                                 p, info_win2k.info_3, 3, delete_files);
2207                         free_a_printer_driver( info_win2k, 3 );
2208
2209                         /* this should not have failed---if it did, report to client */
2210
2211                         if ( !W_ERROR_IS_OK(status_win2k) )
2212                                 goto done;
2213                 }
2214         }
2215
2216         status = delete_printer_driver(p, info.info_3, version, delete_files);
2217
2218         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2219                 status = WERR_OK;
2220 done:
2221         free_a_printer_driver( info, 3 );
2222
2223         return status;
2224 }
2225
2226
2227 /****************************************************************************
2228  Internal routine for retreiving printerdata
2229  ***************************************************************************/
2230
2231 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2232                                   const char *key, const char *value, uint32 *type, uint8 **data,
2233                                   uint32 *needed, uint32 in_size  )
2234 {
2235         REGISTRY_VALUE          *val;
2236         uint32                  size;
2237         int                     data_len;
2238
2239         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2240                 return WERR_BADFILE;
2241
2242         *type = regval_type( val );
2243
2244         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2245
2246         size = regval_size( val );
2247
2248         /* copy the min(in_size, len) */
2249
2250         if ( in_size ) {
2251                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2252
2253                 /* special case for 0 length values */
2254                 if ( data_len ) {
2255                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2256                                 return WERR_NOMEM;
2257                 }
2258                 else {
2259                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2260                                 return WERR_NOMEM;
2261                 }
2262         }
2263         else
2264                 *data = NULL;
2265
2266         *needed = size;
2267
2268         DEBUG(5,("get_printer_dataex: copy done\n"));
2269
2270         return WERR_OK;
2271 }
2272
2273 /****************************************************************************
2274  Internal routine for removing printerdata
2275  ***************************************************************************/
2276
2277 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2278 {
2279         return delete_printer_data( printer->info_2, key, value );
2280 }
2281
2282 /****************************************************************************
2283  Internal routine for storing printerdata
2284  ***************************************************************************/
2285
2286 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2287                                   uint32 type, uint8 *data, int real_len  )
2288 {
2289         /* the registry objects enforce uniqueness based on value name */
2290
2291         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2292 }
2293
2294 /********************************************************************
2295  GetPrinterData on a printer server Handle.
2296 ********************************************************************/
2297
2298 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2299 {
2300         int i;
2301
2302         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2303
2304         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2305                 *type = REG_DWORD;
2306                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2307                         return WERR_NOMEM;
2308                 SIVAL(*data, 0, 0x00);
2309                 *needed = 0x4;
2310                 return WERR_OK;
2311         }
2312
2313         if (!StrCaseCmp(value, "BeepEnabled")) {
2314                 *type = REG_DWORD;
2315                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2316                         return WERR_NOMEM;
2317                 SIVAL(*data, 0, 0x00);
2318                 *needed = 0x4;
2319                 return WERR_OK;
2320         }
2321
2322         if (!StrCaseCmp(value, "EventLog")) {
2323                 *type = REG_DWORD;
2324                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2325                         return WERR_NOMEM;
2326                 /* formally was 0x1b */
2327                 SIVAL(*data, 0, 0x0);
2328                 *needed = 0x4;
2329                 return WERR_OK;
2330         }
2331
2332         if (!StrCaseCmp(value, "NetPopup")) {
2333                 *type = REG_DWORD;
2334                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2335                         return WERR_NOMEM;
2336                 SIVAL(*data, 0, 0x00);
2337                 *needed = 0x4;
2338                 return WERR_OK;
2339         }
2340
2341         if (!StrCaseCmp(value, "MajorVersion")) {
2342                 *type = REG_DWORD;
2343                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2344                         return WERR_NOMEM;
2345
2346                 /* Windows NT 4.0 seems to not allow uploading of drivers
2347                    to a server that reports 0x3 as the MajorVersion.
2348                    need to investigate more how Win2k gets around this .
2349                    -- jerry */
2350
2351                 if ( RA_WINNT == get_remote_arch() )
2352                         SIVAL(*data, 0, 2);
2353                 else
2354                         SIVAL(*data, 0, 3);
2355
2356                 *needed = 0x4;
2357                 return WERR_OK;
2358         }
2359
2360         if (!StrCaseCmp(value, "MinorVersion")) {
2361                 *type = REG_DWORD;
2362                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2363                         return WERR_NOMEM;
2364                 SIVAL(*data, 0, 0);
2365                 *needed = 0x4;
2366                 return WERR_OK;
2367         }
2368
2369         /* REG_BINARY
2370          *  uint32 size          = 0x114
2371          *  uint32 major         = 5
2372          *  uint32 minor         = [0|1]
2373          *  uint32 build         = [2195|2600]
2374          *  extra unicode string = e.g. "Service Pack 3"
2375          */
2376         if (!StrCaseCmp(value, "OSVersion")) {
2377                 *type = REG_BINARY;
2378                 *needed = 0x114;
2379
2380                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2381                         return WERR_NOMEM;
2382
2383                 SIVAL(*data, 0, *needed);       /* size */
2384                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2385                 SIVAL(*data, 8, 0);
2386                 SIVAL(*data, 12, 2195);         /* build */
2387
2388                 /* leave extra string empty */
2389
2390                 return WERR_OK;
2391         }
2392
2393
2394         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2395                 const char *string="C:\\PRINTERS";
2396                 *type = REG_SZ;
2397                 *needed = 2*(strlen(string)+1);
2398                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2399                         return WERR_NOMEM;
2400                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2401
2402                 /* it's done by hand ready to go on the wire */
2403                 for (i=0; i<strlen(string); i++) {
2404                         (*data)[2*i]=string[i];
2405                         (*data)[2*i+1]='\0';
2406                 }
2407                 return WERR_OK;
2408         }
2409
2410         if (!StrCaseCmp(value, "Architecture")) {
2411                 const char *string="Windows NT x86";
2412                 *type = REG_SZ;
2413                 *needed = 2*(strlen(string)+1);
2414                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2415                         return WERR_NOMEM;
2416                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2417                 for (i=0; i<strlen(string); i++) {
2418                         (*data)[2*i]=string[i];
2419                         (*data)[2*i+1]='\0';
2420                 }
2421                 return WERR_OK;
2422         }
2423
2424         if (!StrCaseCmp(value, "DsPresent")) {
2425                 *type = REG_DWORD;
2426                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2427                         return WERR_NOMEM;
2428
2429                 /* only show the publish check box if we are a
2430                    memeber of a AD domain */
2431
2432                 if ( lp_security() == SEC_ADS )
2433                         SIVAL(*data, 0, 0x01);
2434                 else
2435                         SIVAL(*data, 0, 0x00);
2436
2437                 *needed = 0x4;
2438                 return WERR_OK;
2439         }
2440
2441         if (!StrCaseCmp(value, "DNSMachineName")) {
2442                 const char *hostname = get_mydnsfullname();
2443
2444                 if (!hostname)
2445                         return WERR_BADFILE;
2446                 *type = REG_SZ;
2447                 *needed = 2*(strlen(hostname)+1);
2448                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2449                         return WERR_NOMEM;
2450                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2451                 for (i=0; i<strlen(hostname); i++) {
2452                         (*data)[2*i]=hostname[i];
2453                         (*data)[2*i+1]='\0';
2454                 }
2455                 return WERR_OK;
2456         }
2457
2458
2459         return WERR_BADFILE;
2460 }
2461
2462 /********************************************************************
2463  * spoolss_getprinterdata
2464  ********************************************************************/
2465
2466 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2467 {
2468         POLICY_HND      *handle = &q_u->handle;
2469         UNISTR2         *valuename = &q_u->valuename;
2470         uint32          in_size = q_u->size;
2471         uint32          *type = &r_u->type;
2472         uint32          *out_size = &r_u->size;
2473         uint8           **data = &r_u->data;
2474         uint32          *needed = &r_u->needed;
2475         WERROR          status;
2476         fstring         value;
2477         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2478         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2479         int             snum = 0;
2480
2481         /*
2482          * Reminder: when it's a string, the length is in BYTES
2483          * even if UNICODE is negociated.
2484          *
2485          * JFM, 4/19/1999
2486          */
2487
2488         *out_size = in_size;
2489
2490         /* in case of problem, return some default values */
2491
2492         *needed = 0;
2493         *type   = 0;
2494
2495         DEBUG(4,("_spoolss_getprinterdata\n"));
2496
2497         if ( !Printer ) {
2498                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2499                 status = WERR_BADFID;
2500                 goto done;
2501         }
2502
2503         unistr2_to_ascii(value, valuename, sizeof(value));
2504
2505         if ( Printer->printer_type == SPLHND_SERVER )
2506                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2507         else
2508         {
2509                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2510                         status = WERR_BADFID;
2511                         goto done;
2512                 }
2513
2514                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2515                 if ( !W_ERROR_IS_OK(status) )
2516                         goto done;
2517
2518                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2519
2520                 if ( strequal(value, "ChangeId") ) {
2521                         *type = REG_DWORD;
2522                         *needed = sizeof(uint32);
2523                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2524                                 status = WERR_NOMEM;
2525                                 goto done;
2526                         }
2527                         SIVAL( *data, 0, printer->info_2->changeid );
2528                         status = WERR_OK;
2529                 }
2530                 else
2531                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2532         }
2533
2534         if (*needed > *out_size)
2535                 status = WERR_MORE_DATA;
2536
2537 done:
2538         if ( !W_ERROR_IS_OK(status) )
2539         {
2540                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2541
2542                 /* reply this param doesn't exist */
2543
2544                 if ( *out_size ) {
2545                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2546                                 if ( printer )
2547                                         free_a_printer( &printer, 2 );
2548                                 return WERR_NOMEM;
2549                         }
2550                 } else {
2551                         *data = NULL;
2552                 }
2553         }
2554
2555         /* cleanup & exit */
2556
2557         if ( printer )
2558                 free_a_printer( &printer, 2 );
2559
2560         return status;
2561 }
2562
2563 /*********************************************************
2564  Connect to the client machine.
2565 **********************************************************/
2566
2567 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2568                         struct sockaddr_storage *client_ss, const char *remote_machine)
2569 {
2570         NTSTATUS ret;
2571         struct cli_state *the_cli;
2572         struct sockaddr_storage rm_addr;
2573
2574         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2575                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2576                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2577                         return False;
2578                 }
2579
2580                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2581                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2582                         return False;
2583                 }
2584         } else {
2585                 char addr[INET6_ADDRSTRLEN];
2586                 rm_addr = *client_ss;
2587                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2588                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2589                         addr));
2590         }
2591
2592         /* setup the connection */
2593
2594         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2595                 &rm_addr, 0, "IPC$", "IPC",
2596                 "", /* username */
2597                 "", /* domain */
2598                 "", /* password */
2599                 0, lp_client_signing(), NULL );
2600
2601         if ( !NT_STATUS_IS_OK( ret ) ) {
2602                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2603                         remote_machine ));
2604                 return False;
2605         }
2606
2607         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2608                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2609                 cli_shutdown(the_cli);
2610                 return False;
2611         }
2612
2613         /*
2614          * Ok - we have an anonymous connection to the IPC$ share.
2615          * Now start the NT Domain stuff :-).
2616          */
2617
2618         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2619         if (!NT_STATUS_IS_OK(ret)) {
2620                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2621                         remote_machine, nt_errstr(ret)));
2622                 cli_shutdown(the_cli);
2623                 return False;
2624         }
2625
2626         return True;
2627 }
2628
2629 /***************************************************************************
2630  Connect to the client.
2631 ****************************************************************************/
2632
2633 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2634                                         uint32 localprinter, uint32 type,
2635                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2636 {
2637         WERROR result;
2638         NTSTATUS status;
2639
2640         /*
2641          * If it's the first connection, contact the client
2642          * and connect to the IPC$ share anonymously
2643          */
2644         if (smb_connections==0) {
2645                 fstring unix_printer;
2646
2647                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2648
2649                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2650                         return False;
2651
2652                 messaging_register(smbd_messaging_context(), NULL,
2653                                    MSG_PRINTER_NOTIFY2,
2654                                    receive_notify2_message_list);
2655                 /* Tell the connections db we're now interested in printer
2656                  * notify messages. */
2657                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2658         }
2659
2660         /*
2661          * Tell the specific printing tdb we want messages for this printer
2662          * by registering our PID.
2663          */
2664
2665         if (!print_notify_register_pid(snum))
2666                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2667
2668         smb_connections++;
2669
2670         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2671                                                  printer,
2672                                                  localprinter,
2673                                                  type,
2674                                                  0,
2675                                                  NULL,
2676                                                  handle,
2677                                                  &result);
2678         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2679                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2680                         win_errstr(result)));
2681
2682         return (W_ERROR_IS_OK(result));
2683 }
2684
2685 /********************************************************************
2686  * _spoolss_rffpcnex
2687  * ReplyFindFirstPrinterChangeNotifyEx
2688  *
2689  * before replying OK: status=0 a rpc call is made to the workstation
2690  * asking ReplyOpenPrinter
2691  *
2692  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2693  * called from api_spoolss_rffpcnex
2694  ********************************************************************/
2695
2696 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2697 {
2698         POLICY_HND *handle = &q_u->handle;
2699         uint32 flags = q_u->flags;
2700         uint32 options = q_u->options;
2701         UNISTR2 *localmachine = &q_u->localmachine;
2702         uint32 printerlocal = q_u->printerlocal;
2703         int snum = -1;
2704         SPOOL_NOTIFY_OPTION *option = q_u->option;
2705         struct sockaddr_storage client_ss;
2706
2707         /* store the notify value in the printer struct */
2708
2709         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2710
2711         if (!Printer) {
2712                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2713                 return WERR_BADFID;
2714         }
2715
2716         Printer->notify.flags=flags;
2717         Printer->notify.options=options;
2718         Printer->notify.printerlocal=printerlocal;
2719
2720         if (Printer->notify.option)
2721                 free_spool_notify_option(&Printer->notify.option);
2722
2723         Printer->notify.option=dup_spool_notify_option(option);
2724
2725         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2726                        sizeof(Printer->notify.localmachine));
2727
2728         /* Connect to the client machine and send a ReplyOpenPrinter */
2729
2730         if ( Printer->printer_type == SPLHND_SERVER)
2731                 snum = -1;
2732         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2733                         !get_printer_snum(p, handle, &snum, NULL) )
2734                 return WERR_BADFID;
2735
2736         if (!interpret_string_addr(&client_ss, p->client_address,
2737                                    AI_NUMERICHOST)) {
2738                 return WERR_SERVER_UNAVAILABLE;
2739         }
2740
2741         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2742                                         Printer->notify.printerlocal, 1,
2743                                         &Printer->notify.client_hnd, &client_ss))
2744                 return WERR_SERVER_UNAVAILABLE;
2745
2746         Printer->notify.client_connected=True;
2747
2748         return WERR_OK;
2749 }
2750
2751 /*******************************************************************
2752  * fill a notify_info_data with the servername
2753  ********************************************************************/
2754
2755 void spoolss_notify_server_name(int snum,
2756                                        SPOOL_NOTIFY_INFO_DATA *data,
2757                                        print_queue_struct *queue,
2758                                        NT_PRINTER_INFO_LEVEL *printer,
2759                                        TALLOC_CTX *mem_ctx)
2760 {
2761         smb_ucs2_t *temp = NULL;
2762         uint32 len;
2763
2764         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2765         if (len == (uint32)-1) {
2766                 len = 0;
2767         }
2768
2769         data->notify_data.data.length = len;
2770         if (len) {
2771                 data->notify_data.data.string = (uint16 *)temp;
2772         } else {
2773                 data->notify_data.data.string = NULL;
2774         }
2775 }
2776
2777 /*******************************************************************
2778  * fill a notify_info_data with the printername (not including the servername).
2779  ********************************************************************/
2780
2781 void spoolss_notify_printer_name(int snum,
2782                                         SPOOL_NOTIFY_INFO_DATA *data,
2783                                         print_queue_struct *queue,
2784                                         NT_PRINTER_INFO_LEVEL *printer,
2785                                         TALLOC_CTX *mem_ctx)
2786 {
2787         smb_ucs2_t *temp = NULL;
2788         uint32 len;
2789
2790         /* the notify name should not contain the \\server\ part */
2791         char *p = strrchr(printer->info_2->printername, '\\');
2792
2793         if (!p) {
2794                 p = printer->info_2->printername;
2795         } else {
2796                 p++;
2797         }
2798
2799         len = rpcstr_push_talloc(mem_ctx, &temp, p);
2800         if (len == (uint32)-1) {
2801                 len = 0;
2802         }
2803
2804         data->notify_data.data.length = len;
2805         if (len) {
2806                 data->notify_data.data.string = (uint16 *)temp;
2807         } else {
2808                 data->notify_data.data.string = NULL;
2809         }
2810 }
2811
2812 /*******************************************************************
2813  * fill a notify_info_data with the servicename
2814  ********************************************************************/
2815
2816 void spoolss_notify_share_name(int snum,
2817                                       SPOOL_NOTIFY_INFO_DATA *data,
2818                                       print_queue_struct *queue,
2819                                       NT_PRINTER_INFO_LEVEL *printer,
2820                                       TALLOC_CTX *mem_ctx)
2821 {
2822         smb_ucs2_t *temp = NULL;
2823         uint32 len;
2824
2825         len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2826         if (len == (uint32)-1) {
2827                 len = 0;
2828         }
2829
2830         data->notify_data.data.length = len;
2831         if (len) {
2832                 data->notify_data.data.string = (uint16 *)temp;
2833         } else {
2834                 data->notify_data.data.string = NULL;
2835         }
2836
2837 }
2838
2839 /*******************************************************************
2840  * fill a notify_info_data with the port name
2841  ********************************************************************/
2842
2843 void spoolss_notify_port_name(int snum,
2844                                      SPOOL_NOTIFY_INFO_DATA *data,
2845                                      print_queue_struct *queue,
2846                                      NT_PRINTER_INFO_LEVEL *printer,
2847                                      TALLOC_CTX *mem_ctx)
2848 {
2849         smb_ucs2_t *temp = NULL;
2850         uint32 len;
2851
2852         /* even if it's strange, that's consistant in all the code */
2853
2854         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2855         if (len == (uint32)-1) {
2856                 len = 0;
2857         }
2858
2859         data->notify_data.data.length = len;
2860         if (len) {
2861                 data->notify_data.data.string = (uint16 *)temp;
2862         } else {
2863                 data->notify_data.data.string = NULL;
2864         }
2865 }
2866
2867 /*******************************************************************
2868  * fill a notify_info_data with the printername
2869  * but it doesn't exist, have to see what to do
2870  ********************************************************************/
2871
2872 void spoolss_notify_driver_name(int snum,
2873                                        SPOOL_NOTIFY_INFO_DATA *data,
2874                                        print_queue_struct *queue,
2875                                        NT_PRINTER_INFO_LEVEL *printer,
2876                                        TALLOC_CTX *mem_ctx)
2877 {
2878         smb_ucs2_t *temp = NULL;
2879         uint32 len;
2880
2881         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2882         if (len == (uint32)-1) {
2883                 len = 0;
2884         }
2885
2886         data->notify_data.data.length = len;
2887         if (len) {
2888                 data->notify_data.data.string = (uint16 *)temp;
2889         } else {
2890                 data->notify_data.data.string = NULL;
2891         }
2892 }
2893
2894 /*******************************************************************
2895  * fill a notify_info_data with the comment
2896  ********************************************************************/
2897
2898 void spoolss_notify_comment(int snum,
2899                                    SPOOL_NOTIFY_INFO_DATA *data,
2900                                    print_queue_struct *queue,
2901                                    NT_PRINTER_INFO_LEVEL *printer,
2902                                    TALLOC_CTX *mem_ctx)
2903 {
2904         smb_ucs2_t *temp = NULL;
2905         uint32 len;
2906
2907         if (*printer->info_2->comment == '\0')
2908                 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2909         else
2910                 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2911
2912         if (len == (uint32)-1) {
2913                 len = 0;
2914         }
2915         data->notify_data.data.length = len;
2916         if (len) {
2917                 data->notify_data.data.string = (uint16 *)temp;
2918         } else {
2919                 data->notify_data.data.string = NULL;
2920         }
2921 }
2922
2923 /*******************************************************************
2924  * fill a notify_info_data with the comment
2925  * location = "Room 1, floor 2, building 3"
2926  ********************************************************************/
2927
2928 void spoolss_notify_location(int snum,
2929                                     SPOOL_NOTIFY_INFO_DATA *data,
2930                                     print_queue_struct *queue,
2931                                     NT_PRINTER_INFO_LEVEL *printer,
2932                                     TALLOC_CTX *mem_ctx)
2933 {
2934         smb_ucs2_t *temp = NULL;
2935         uint32 len;
2936
2937         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2938         if (len == (uint32)-1) {
2939                 len = 0;
2940         }
2941
2942         data->notify_data.data.length = len;
2943         if (len) {
2944                 data->notify_data.data.string = (uint16 *)temp;
2945         } else {
2946                 data->notify_data.data.string = NULL;
2947         }
2948 }
2949
2950 /*******************************************************************
2951  * fill a notify_info_data with the device mode
2952  * jfm:xxxx don't to it for know but that's a real problem !!!
2953  ********************************************************************/
2954
2955 static void spoolss_notify_devmode(int snum,
2956                                    SPOOL_NOTIFY_INFO_DATA *data,
2957                                    print_queue_struct *queue,
2958                                    NT_PRINTER_INFO_LEVEL *printer,
2959                                    TALLOC_CTX *mem_ctx)
2960 {
2961         /* for a dummy implementation we have to zero the fields */
2962         data->notify_data.data.length = 0;
2963         data->notify_data.data.string = NULL;
2964 }
2965
2966 /*******************************************************************
2967  * fill a notify_info_data with the separator file name
2968  ********************************************************************/
2969
2970 void spoolss_notify_sepfile(int snum,
2971                                    SPOOL_NOTIFY_INFO_DATA *data,
2972                                    print_queue_struct *queue,
2973                                    NT_PRINTER_INFO_LEVEL *printer,
2974                                    TALLOC_CTX *mem_ctx)
2975 {
2976         smb_ucs2_t *temp = NULL;
2977         uint32 len;
2978
2979         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2980         if (len == (uint32)-1) {
2981                 len = 0;
2982         }
2983
2984         data->notify_data.data.length = len;
2985         if (len) {
2986                 data->notify_data.data.string = (uint16 *)temp;
2987         } else {
2988                 data->notify_data.data.string = NULL;
2989         }
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the print processor
2994  * jfm:xxxx return always winprint to indicate we don't do anything to it
2995  ********************************************************************/
2996
2997 void spoolss_notify_print_processor(int snum,
2998                                            SPOOL_NOTIFY_INFO_DATA *data,
2999                                            print_queue_struct *queue,
3000                                            NT_PRINTER_INFO_LEVEL *printer,
3001                                            TALLOC_CTX *mem_ctx)
3002 {
3003         smb_ucs2_t *temp = NULL;
3004         uint32 len;
3005
3006         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
3007         if (len == (uint32)-1) {
3008                 len = 0;
3009         }
3010
3011         data->notify_data.data.length = len;
3012         if (len) {
3013                 data->notify_data.data.string = (uint16 *)temp;
3014         } else {
3015                 data->notify_data.data.string = NULL;
3016         }
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the print processor options
3021  * jfm:xxxx send an empty string
3022  ********************************************************************/
3023
3024 void spoolss_notify_parameters(int snum,
3025                                       SPOOL_NOTIFY_INFO_DATA *data,
3026                                       print_queue_struct *queue,
3027                                       NT_PRINTER_INFO_LEVEL *printer,
3028                                       TALLOC_CTX *mem_ctx)
3029 {
3030         smb_ucs2_t *temp = NULL;
3031         uint32 len;
3032
3033         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3034         if (len == (uint32)-1) {
3035                 len = 0;
3036         }
3037
3038         data->notify_data.data.length = len;
3039         if (len) {
3040                 data->notify_data.data.string = (uint16 *)temp;
3041         } else {
3042                 data->notify_data.data.string = NULL;
3043         }
3044 }
3045
3046 /*******************************************************************
3047  * fill a notify_info_data with the data type
3048  * jfm:xxxx always send RAW as data type
3049  ********************************************************************/
3050
3051 void spoolss_notify_datatype(int snum,
3052                                     SPOOL_NOTIFY_INFO_DATA *data,
3053                                     print_queue_struct *queue,
3054                                     NT_PRINTER_INFO_LEVEL *printer,
3055                                     TALLOC_CTX *mem_ctx)
3056 {
3057         smb_ucs2_t *temp = NULL;
3058         uint32 len;
3059
3060         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3061         if (len == (uint32)-1) {
3062                 len = 0;
3063         }
3064
3065         data->notify_data.data.length = len;
3066         if (len) {
3067                 data->notify_data.data.string = (uint16 *)temp;
3068         } else {
3069                 data->notify_data.data.string = NULL;
3070         }
3071 }
3072
3073 /*******************************************************************
3074  * fill a notify_info_data with the security descriptor
3075  * jfm:xxxx send an null pointer to say no security desc
3076  * have to implement security before !
3077  ********************************************************************/
3078
3079 static void spoolss_notify_security_desc(int snum,
3080                                          SPOOL_NOTIFY_INFO_DATA *data,
3081                                          print_queue_struct *queue,
3082                                          NT_PRINTER_INFO_LEVEL *printer,
3083                                          TALLOC_CTX *mem_ctx)
3084 {
3085         data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3086         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3087 }
3088
3089 /*******************************************************************
3090  * fill a notify_info_data with the attributes
3091  * jfm:xxxx a samba printer is always shared
3092  ********************************************************************/
3093
3094 void spoolss_notify_attributes(int snum,
3095                                       SPOOL_NOTIFY_INFO_DATA *data,
3096                                       print_queue_struct *queue,
3097                                       NT_PRINTER_INFO_LEVEL *printer,
3098                                       TALLOC_CTX *mem_ctx)
3099 {
3100         data->notify_data.value[0] = printer->info_2->attributes;
3101         data->notify_data.value[1] = 0;
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with the priority
3106  ********************************************************************/
3107
3108 static void spoolss_notify_priority(int snum,
3109                                     SPOOL_NOTIFY_INFO_DATA *data,
3110                                     print_queue_struct *queue,
3111                                     NT_PRINTER_INFO_LEVEL *printer,
3112                                     TALLOC_CTX *mem_ctx)
3113 {
3114         data->notify_data.value[0] = printer->info_2->priority;
3115         data->notify_data.value[1] = 0;
3116 }
3117
3118 /*******************************************************************
3119  * fill a notify_info_data with the default priority
3120  ********************************************************************/
3121
3122 static void spoolss_notify_default_priority(int snum,
3123                                             SPOOL_NOTIFY_INFO_DATA *data,
3124                                             print_queue_struct *queue,
3125                                             NT_PRINTER_INFO_LEVEL *printer,
3126                                             TALLOC_CTX *mem_ctx)
3127 {
3128         data->notify_data.value[0] = printer->info_2->default_priority;
3129         data->notify_data.value[1] = 0;
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with the start time
3134  ********************************************************************/
3135
3136 static void spoolss_notify_start_time(int snum,
3137                                       SPOOL_NOTIFY_INFO_DATA *data,
3138                                       print_queue_struct *queue,
3139                                       NT_PRINTER_INFO_LEVEL *printer,
3140                                       TALLOC_CTX *mem_ctx)
3141 {
3142         data->notify_data.value[0] = printer->info_2->starttime;
3143         data->notify_data.value[1] = 0;
3144 }
3145
3146 /*******************************************************************
3147  * fill a notify_info_data with the until time
3148  ********************************************************************/
3149
3150 static void spoolss_notify_until_time(int snum,
3151                                       SPOOL_NOTIFY_INFO_DATA *data,
3152                                       print_queue_struct *queue,
3153                                       NT_PRINTER_INFO_LEVEL *printer,
3154                                       TALLOC_CTX *mem_ctx)
3155 {
3156         data->notify_data.value[0] = printer->info_2->untiltime;
3157         data->notify_data.value[1] = 0;
3158 }
3159
3160 /*******************************************************************
3161  * fill a notify_info_data with the status
3162  ********************************************************************/
3163
3164 static void spoolss_notify_status(int snum,
3165                                   SPOOL_NOTIFY_INFO_DATA *data,
3166                                   print_queue_struct *queue,
3167                                   NT_PRINTER_INFO_LEVEL *printer,
3168                                   TALLOC_CTX *mem_ctx)
3169 {
3170         print_status_struct status;
3171
3172         print_queue_length(snum, &status);
3173         data->notify_data.value[0]=(uint32) status.status;
3174         data->notify_data.value[1] = 0;
3175 }
3176
3177 /*******************************************************************
3178  * fill a notify_info_data with the number of jobs queued
3179  ********************************************************************/
3180
3181 void spoolss_notify_cjobs(int snum,
3182                                  SPOOL_NOTIFY_INFO_DATA *data,
3183                                  print_queue_struct *queue,
3184                                  NT_PRINTER_INFO_LEVEL *printer,
3185                                  TALLOC_CTX *mem_ctx)
3186 {
3187         data->notify_data.value[0] = print_queue_length(snum, NULL);
3188         data->notify_data.value[1] = 0;
3189 }
3190
3191 /*******************************************************************
3192  * fill a notify_info_data with the average ppm
3193  ********************************************************************/
3194
3195 static void spoolss_notify_average_ppm(int snum,
3196                                        SPOOL_NOTIFY_INFO_DATA *data,
3197                                        print_queue_struct *queue,
3198                                        NT_PRINTER_INFO_LEVEL *printer,
3199                                        TALLOC_CTX *mem_ctx)
3200 {
3201         /* always respond 8 pages per minutes */
3202         /* a little hard ! */
3203         data->notify_data.value[0] = printer->info_2->averageppm;
3204         data->notify_data.value[1] = 0;
3205 }
3206
3207 /*******************************************************************
3208  * fill a notify_info_data with username
3209  ********************************************************************/
3210
3211 static void spoolss_notify_username(int snum,
3212                                     SPOOL_NOTIFY_INFO_DATA *data,
3213                                     print_queue_struct *queue,
3214                                     NT_PRINTER_INFO_LEVEL *printer,
3215                                     TALLOC_CTX *mem_ctx)
3216 {
3217         smb_ucs2_t *temp = NULL;
3218         uint32 len;
3219
3220         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3221         if (len == (uint32)-1) {
3222                 len = 0;
3223         }
3224
3225         data->notify_data.data.length = len;
3226         if (len) {
3227                 data->notify_data.data.string = (uint16 *)temp;
3228         } else {
3229                 data->notify_data.data.string = NULL;
3230         }
3231 }
3232
3233 /*******************************************************************
3234  * fill a notify_info_data with job status
3235  ********************************************************************/
3236
3237 static void spoolss_notify_job_status(int snum,
3238                                       SPOOL_NOTIFY_INFO_DATA *data,
3239                                       print_queue_struct *queue,
3240                                       NT_PRINTER_INFO_LEVEL *printer,
3241                                       TALLOC_CTX *mem_ctx)
3242 {
3243         data->notify_data.value[0]=nt_printj_status(queue->status);
3244         data->notify_data.value[1] = 0;
3245 }
3246
3247 /*******************************************************************
3248  * fill a notify_info_data with job name
3249  ********************************************************************/
3250
3251 static void spoolss_notify_job_name(int snum,
3252                                     SPOOL_NOTIFY_INFO_DATA *data,
3253                                     print_queue_struct *queue,
3254                                     NT_PRINTER_INFO_LEVEL *printer,
3255                                     TALLOC_CTX *mem_ctx)
3256 {
3257         smb_ucs2_t *temp = NULL;
3258         uint32 len;
3259
3260         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3261         if (len == (uint32)-1) {
3262                 len = 0;
3263         }
3264
3265         data->notify_data.data.length = len;
3266         if (len) {
3267                 data->notify_data.data.string = (uint16 *)temp;
3268         } else {
3269                 data->notify_data.data.string = NULL;
3270         }
3271 }
3272
3273 /*******************************************************************
3274  * fill a notify_info_data with job status
3275  ********************************************************************/
3276
3277 static void spoolss_notify_job_status_string(int snum,
3278                                              SPOOL_NOTIFY_INFO_DATA *data,
3279                                              print_queue_struct *queue,
3280                                              NT_PRINTER_INFO_LEVEL *printer,
3281                                              TALLOC_CTX *mem_ctx)
3282 {
3283         /*
3284          * Now we're returning job status codes we just return a "" here. JRA.
3285          */
3286
3287         const char *p = "";
3288         smb_ucs2_t *temp = NULL;
3289         uint32 len;
3290
3291 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3292         p = "unknown";
3293
3294         switch (queue->status) {
3295         case LPQ_QUEUED:
3296                 p = "Queued";
3297                 break;
3298         case LPQ_PAUSED:
3299                 p = "";    /* NT provides the paused string */
3300                 break;
3301         case LPQ_SPOOLING:
3302                 p = "Spooling";
3303                 break;
3304         case LPQ_PRINTING:
3305                 p = "Printing";
3306                 break;
3307         }
3308 #endif /* NO LONGER NEEDED. */
3309
3310         len = rpcstr_push_talloc(mem_ctx, &temp, p);
3311         if (len == (uint32)-1) {
3312                 len = 0;
3313         }
3314
3315         data->notify_data.data.length = len;
3316         if (len) {
3317                 data->notify_data.data.string = (uint16 *)temp;
3318         } else {
3319                 data->notify_data.data.string = NULL;
3320         }
3321 }
3322
3323 /*******************************************************************
3324  * fill a notify_info_data with job time
3325  ********************************************************************/
3326
3327 static void spoolss_notify_job_time(int snum,
3328                                     SPOOL_NOTIFY_INFO_DATA *data,
3329                                     print_queue_struct *queue,
3330                                     NT_PRINTER_INFO_LEVEL *printer,
3331                                     TALLOC_CTX *mem_ctx)
3332 {
3333         data->notify_data.value[0]=0x0;
3334         data->notify_data.value[1]=0;
3335 }
3336
3337 /*******************************************************************
3338  * fill a notify_info_data with job size
3339  ********************************************************************/
3340
3341 static void spoolss_notify_job_size(int snum,
3342                                     SPOOL_NOTIFY_INFO_DATA *data,
3343                                     print_queue_struct *queue,
3344                                     NT_PRINTER_INFO_LEVEL *printer,
3345                                     TALLOC_CTX *mem_ctx)
3346 {
3347         data->notify_data.value[0]=queue->size;
3348         data->notify_data.value[1]=0;
3349 }
3350
3351 /*******************************************************************
3352  * fill a notify_info_data with page info
3353  ********************************************************************/
3354 static void spoolss_notify_total_pages(int snum,
3355                                 SPOOL_NOTIFY_INFO_DATA *data,
3356                                 print_queue_struct *queue,
3357                                 NT_PRINTER_INFO_LEVEL *printer,
3358                                 TALLOC_CTX *mem_ctx)
3359 {
3360         data->notify_data.value[0]=queue->page_count;
3361         data->notify_data.value[1]=0;
3362 }
3363
3364 /*******************************************************************
3365  * fill a notify_info_data with pages printed info.
3366  ********************************************************************/
3367 static void spoolss_notify_pages_printed(int snum,
3368                                 SPOOL_NOTIFY_INFO_DATA *data,
3369                                 print_queue_struct *queue,
3370                                 NT_PRINTER_INFO_LEVEL *printer,
3371                                 TALLOC_CTX *mem_ctx)
3372 {
3373         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
3374         data->notify_data.value[1]=0;
3375 }
3376
3377 /*******************************************************************
3378  Fill a notify_info_data with job position.
3379  ********************************************************************/
3380
3381 static void spoolss_notify_job_position(int snum,
3382                                         SPOOL_NOTIFY_INFO_DATA *data,
3383                                         print_queue_struct *queue,
3384                                         NT_PRINTER_INFO_LEVEL *printer,
3385                                         TALLOC_CTX *mem_ctx)
3386 {
3387         data->notify_data.value[0]=queue->job;
3388         data->notify_data.value[1]=0;
3389 }
3390
3391 /*******************************************************************
3392  Fill a notify_info_data with submitted time.
3393  ********************************************************************/
3394
3395 static void spoolss_notify_submitted_time(int snum,
3396                                           SPOOL_NOTIFY_INFO_DATA *data,
3397                                           print_queue_struct *queue,
3398                                           NT_PRINTER_INFO_LEVEL *printer,
3399                                           TALLOC_CTX *mem_ctx)
3400 {
3401         struct tm *t;
3402         uint32 len;
3403         SYSTEMTIME st;
3404         char *p;
3405
3406         t=gmtime(&queue->time);
3407
3408         len = sizeof(SYSTEMTIME);
3409
3410         data->notify_data.data.length = len;
3411         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3412
3413         if (!data->notify_data.data.string) {
3414                 data->notify_data.data.length = 0;
3415                 return;
3416         }
3417
3418         make_systemtime(&st, t);
3419
3420         /*
3421          * Systemtime must be linearized as a set of UINT16's.
3422          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3423          */
3424
3425         p = (char *)data->notify_data.data.string;
3426         SSVAL(p, 0, st.year);
3427         SSVAL(p, 2, st.month);
3428         SSVAL(p, 4, st.dayofweek);
3429         SSVAL(p, 6, st.day);
3430         SSVAL(p, 8, st.hour);
3431         SSVAL(p, 10, st.minute);
3432         SSVAL(p, 12, st.second);
3433         SSVAL(p, 14, st.milliseconds);
3434 }
3435
3436 struct s_notify_info_data_table
3437 {
3438         uint16 type;
3439         uint16 field;
3440         const char *name;
3441         uint32 size;
3442         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3443                     print_queue_struct *queue,
3444                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3445 };
3446
3447 /* A table describing the various print notification constants and
3448    whether the notification data is a pointer to a variable sized
3449    buffer, a one value uint32 or a two value uint32. */
3450
3451 static const struct s_notify_info_data_table notify_info_data_table[] =
3452 {
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_STRING,   spoolss_notify_print_processor },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_STRING,   spoolss_notify_parameters },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_STRING,   spoolss_notify_datatype },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC,   spoolss_notify_security_desc },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_ONE_VALUE, spoolss_notify_priority },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
3479 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
3480 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
3481 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
3482 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
3483 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
3484 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
3485 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
3486 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
3487 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
3488 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
3489 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3490 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
3491 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
3492 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
3493 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
3494 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3495 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
3496 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3497 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3498 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3499 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3500 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3501 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3502 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3503 };
3504
3505 /*******************************************************************
3506  Return the size of info_data structure.
3507 ********************************************************************/
3508
3509 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3510 {
3511         int i=0;
3512
3513         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3514                 if ( (notify_info_data_table[i].type == type)
3515                         && (notify_info_data_table[i].field == field) ) {
3516                         switch(notify_info_data_table[i].size) {
3517                                 case NOTIFY_ONE_VALUE:
3518                                 case NOTIFY_TWO_VALUE:
3519                                         return 1;
3520                                 case NOTIFY_STRING:
3521                                         return 2;
3522
3523                                 /* The only pointer notify data I have seen on
3524                                    the wire is the submitted time and this has
3525                                    the notify size set to 4. -tpot */
3526
3527                                 case NOTIFY_POINTER:
3528                                         return 4;
3529
3530                                 case NOTIFY_SECDESC:
3531                                         return 5;
3532                         }
3533                 }
3534         }
3535
3536         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3537
3538         return 0;
3539 }
3540
3541 /*******************************************************************
3542  Return the type of notify_info_data.
3543 ********************************************************************/
3544
3545 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3546 {
3547         uint32 i=0;
3548
3549         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3550                 if (notify_info_data_table[i].type == type &&
3551                     notify_info_data_table[i].field == field)
3552                         return notify_info_data_table[i].size;
3553         }
3554
3555         return 0;
3556 }
3557
3558 /****************************************************************************
3559 ****************************************************************************/
3560
3561 static bool search_notify(uint16 type, uint16 field, int *value)
3562 {
3563         int i;
3564
3565         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3566                 if (notify_info_data_table[i].type == type &&
3567                     notify_info_data_table[i].field == field &&
3568                     notify_info_data_table[i].fn != NULL) {
3569                         *value = i;
3570                         return True;
3571                 }
3572         }
3573
3574         return False;
3575 }
3576
3577 /****************************************************************************
3578 ****************************************************************************/
3579
3580 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3581 {
3582         info_data->type     = type;
3583         info_data->field    = field;
3584         info_data->reserved = 0;
3585
3586         info_data->size     = size_of_notify_info_data(type, field);
3587         info_data->enc_type = type_of_notify_info_data(type, field);
3588
3589         info_data->id = id;
3590 }
3591
3592 /*******************************************************************
3593  *
3594  * fill a notify_info struct with info asked
3595  *
3596  ********************************************************************/
3597
3598 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3599                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3600                                           *option_type, uint32 id,
3601                                           TALLOC_CTX *mem_ctx)
3602 {
3603         int field_num,j;
3604         uint16 type;
3605         uint16 field;
3606
3607         SPOOL_NOTIFY_INFO_DATA *current_data;
3608         NT_PRINTER_INFO_LEVEL *printer = NULL;
3609         print_queue_struct *queue=NULL;
3610
3611         type=option_type->type;
3612
3613         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3614                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3615                 option_type->count, lp_servicename(snum)));
3616
3617         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3618                 return False;
3619
3620         for(field_num=0; field_num<option_type->count; field_num++) {
3621                 field = option_type->fields[field_num];
3622
3623                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3624
3625                 if (!search_notify(type, field, &j) )
3626                         continue;
3627
3628                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3629                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3630                         free_a_printer(&printer, 2);
3631                         return False;
3632                 }
3633
3634                 current_data = &info->data[info->count];
3635
3636                 construct_info_data(current_data, type, field, id);
3637
3638                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3639                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3640
3641                 notify_info_data_table[j].fn(snum, current_data, queue,
3642                                              printer, mem_ctx);
3643
3644                 info->count++;
3645         }
3646
3647         free_a_printer(&printer, 2);
3648         return True;
3649 }
3650
3651 /*******************************************************************
3652  *
3653  * fill a notify_info struct with info asked
3654  *
3655  ********************************************************************/
3656
3657 static bool construct_notify_jobs_info(print_queue_struct *queue,
3658                                        SPOOL_NOTIFY_INFO *info,
3659                                        NT_PRINTER_INFO_LEVEL *printer,
3660                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3661                                        *option_type, uint32 id,
3662                                        TALLOC_CTX *mem_ctx)
3663 {
3664         int field_num,j;
3665         uint16 type;
3666         uint16 field;
3667
3668         SPOOL_NOTIFY_INFO_DATA *current_data;
3669
3670         DEBUG(4,("construct_notify_jobs_info\n"));
3671
3672         type = option_type->type;
3673
3674         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3675                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3676                 option_type->count));
3677
3678         for(field_num=0; field_num<option_type->count; field_num++) {
3679                 field = option_type->fields[field_num];
3680
3681                 if (!search_notify(type, field, &j) )
3682                         continue;
3683
3684                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3685                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3686                         return False;
3687                 }
3688
3689                 current_data=&(info->data[info->count]);
3690
3691                 construct_info_data(current_data, type, field, id);
3692                 notify_info_data_table[j].fn(snum, current_data, queue,
3693                                              printer, mem_ctx);
3694                 info->count++;
3695         }
3696
3697         return True;
3698 }
3699
3700 /*
3701  * JFM: The enumeration is not that simple, it's even non obvious.
3702  *
3703  * let's take an example: I want to monitor the PRINTER SERVER for
3704  * the printer's name and the number of jobs currently queued.
3705  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3706  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3707  *
3708  * I have 3 printers on the back of my server.
3709  *
3710  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3711  * structures.
3712  *   Number     Data                    Id
3713  *      1       printer 1 name          1
3714  *      2       printer 1 cjob          1
3715  *      3       printer 2 name          2
3716  *      4       printer 2 cjob          2
3717  *      5       printer 3 name          3
3718  *      6       printer 3 name          3
3719  *
3720  * that's the print server case, the printer case is even worse.
3721  */
3722
3723 /*******************************************************************
3724  *
3725  * enumerate all printers on the printserver
3726  * fill a notify_info struct with info asked
3727  *
3728  ********************************************************************/
3729
3730 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3731                                       SPOOL_NOTIFY_INFO *info,
3732                                       TALLOC_CTX *mem_ctx)
3733 {
3734         int snum;
3735         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3736         int n_services=lp_numservices();
3737         int i;
3738         SPOOL_NOTIFY_OPTION *option;
3739         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3740
3741         DEBUG(4,("printserver_notify_info\n"));
3742
3743         if (!Printer)
3744                 return WERR_BADFID;
3745
3746         option=Printer->notify.option;
3747         info->version=2;
3748         info->data=NULL;
3749         info->count=0;
3750
3751         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752            sending a ffpcn() request first */
3753
3754         if ( !option )
3755                 return WERR_BADFID;
3756
3757         for (i=0; i<option->count; i++) {
3758                 option_type=&(option->ctr.type[i]);
3759
3760                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3761                         continue;
3762
3763                 for (snum=0; snum<n_services; snum++)
3764                 {
3765                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3766                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3767                 }
3768         }
3769
3770 #if 0
3771         /*
3772          * Debugging information, don't delete.
3773          */
3774
3775         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3776         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3777         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3778
3779         for (i=0; i<info->count; i++) {
3780                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3781                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3782                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3783         }
3784 #endif
3785
3786         return WERR_OK;
3787 }
3788
3789 /*******************************************************************
3790  *
3791  * fill a notify_info struct with info asked
3792  *
3793  ********************************************************************/
3794
3795 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3796                                   TALLOC_CTX *mem_ctx)
3797 {
3798         int snum;
3799         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3800         int i;
3801         uint32 id;
3802         SPOOL_NOTIFY_OPTION *option;
3803         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3804         int count,j;
3805         print_queue_struct *queue=NULL;
3806         print_status_struct status;
3807
3808         DEBUG(4,("printer_notify_info\n"));
3809
3810         if (!Printer)
3811                 return WERR_BADFID;
3812
3813         option=Printer->notify.option;
3814         id = 0x0;
3815         info->version=2;
3816         info->data=NULL;
3817         info->count=0;
3818
3819         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3820            sending a ffpcn() request first */
3821
3822         if ( !option )
3823                 return WERR_BADFID;
3824
3825         get_printer_snum(p, hnd, &snum, NULL);
3826
3827         for (i=0; i<option->count; i++) {
3828                 option_type=&option->ctr.type[i];
3829
3830                 switch ( option_type->type ) {
3831                 case PRINTER_NOTIFY_TYPE:
3832                         if(construct_notify_printer_info(Printer, info, snum,
3833                                                          option_type, id,
3834                                                          mem_ctx))
3835                                 id--;
3836                         break;
3837
3838                 case JOB_NOTIFY_TYPE: {
3839                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3840
3841                         count = print_queue_status(snum, &queue, &status);
3842
3843                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3844                                 goto done;
3845
3846                         for (j=0; j<count; j++) {
3847                                 construct_notify_jobs_info(&queue[j], info,
3848                                                            printer, snum,
3849                                                            option_type,
3850                                                            queue[j].job,
3851                                                            mem_ctx);
3852                         }
3853
3854                         free_a_printer(&printer, 2);
3855
3856                 done:
3857                         SAFE_FREE(queue);
3858                         break;
3859                 }
3860                 }
3861         }
3862
3863         /*
3864          * Debugging information, don't delete.
3865          */
3866         /*
3867         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3868         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3869         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3870
3871         for (i=0; i<info->count; i++) {
3872                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3873                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3874                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3875         }
3876         */
3877         return WERR_OK;
3878 }
3879
3880 /********************************************************************
3881  * spoolss_rfnpcnex
3882  ********************************************************************/
3883
3884 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3885 {
3886         POLICY_HND *handle = &q_u->handle;
3887         SPOOL_NOTIFY_INFO *info = &r_u->info;
3888
3889         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3890         WERROR result = WERR_BADFID;
3891
3892         /* we always have a NOTIFY_INFO struct */
3893         r_u->info_ptr=0x1;
3894
3895         if (!Printer) {
3896                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3897                          OUR_HANDLE(handle)));
3898                 goto done;
3899         }
3900
3901         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3902
3903         /*
3904          *      We are now using the change value, and
3905          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3906          *      I don't have a global notification system, I'm sending back all the
3907          *      informations even when _NOTHING_ has changed.
3908          */
3909
3910         /* We need to keep track of the change value to send back in
3911            RRPCN replies otherwise our updates are ignored. */
3912
3913         Printer->notify.fnpcn = True;
3914
3915         if (Printer->notify.client_connected) {
3916                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3917                 Printer->notify.change = q_u->change;
3918         }
3919
3920         /* just ignore the SPOOL_NOTIFY_OPTION */
3921
3922         switch (Printer->printer_type) {
3923                 case SPLHND_SERVER:
3924                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3925                         break;
3926
3927                 case SPLHND_PRINTER:
3928                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3929                         break;
3930         }
3931
3932         Printer->notify.fnpcn = False;
3933
3934 done:
3935         return result;
3936 }
3937
3938 /********************************************************************
3939  * construct_printer_info_0
3940  * fill a printer_info_0 struct
3941  ********************************************************************/
3942
3943 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3944 {
3945         char *chaine = NULL;
3946         int count;
3947         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3948         counter_printer_0 *session_counter;
3949         uint32 global_counter;
3950         struct tm *t;
3951         time_t setuptime;
3952         print_status_struct status;
3953         TALLOC_CTX *ctx = talloc_tos();
3954
3955         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3956                 return False;
3957
3958         init_unistr(&printer->printername, ntprinter->info_2->printername);
3959
3960         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3961         if (!chaine) {
3962                 free_a_printer(&ntprinter,2);
3963                 return false;
3964         }
3965
3966         count = print_queue_length(snum, &status);
3967
3968         /* check if we already have a counter for this printer */
3969         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3970                 if (session_counter->snum == snum)
3971                         break;
3972         }
3973
3974         init_unistr(&printer->servername, chaine);
3975
3976         /* it's the first time, add it to the list */
3977         if (session_counter==NULL) {
3978                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3979                         free_a_printer(&ntprinter, 2);
3980                         return False;
3981                 }
3982                 ZERO_STRUCTP(session_counter);
3983                 session_counter->snum=snum;
3984                 session_counter->counter=0;
3985                 DLIST_ADD(counter_list, session_counter);
3986         }
3987
3988         /* increment it */
3989         session_counter->counter++;
3990
3991         /* JFM:
3992          * the global_counter should be stored in a TDB as it's common to all the clients
3993          * and should be zeroed on samba startup
3994          */
3995         global_counter=session_counter->counter;
3996         printer->cjobs = count;
3997         printer->total_jobs = 0;
3998         printer->total_bytes = 0;
3999
4000         setuptime = (time_t)ntprinter->info_2->setuptime;
4001         t=gmtime(&setuptime);
4002
4003         printer->year = t->tm_year+1900;
4004         printer->month = t->tm_mon+1;
4005         printer->dayofweek = t->tm_wday;
4006         printer->day = t->tm_mday;
4007         printer->hour = t->tm_hour;
4008         printer->minute = t->tm_min;
4009         printer->second = t->tm_sec;
4010         printer->milliseconds = 0;
4011
4012         printer->global_counter = global_counter;
4013         printer->total_pages = 0;
4014
4015         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4016         printer->major_version = 0x0005;        /* NT 5 */
4017         printer->build_version = 0x0893;        /* build 2195 */
4018
4019         printer->unknown7 = 0x1;
4020         printer->unknown8 = 0x0;
4021         printer->unknown9 = 0x0;
4022         printer->session_counter = session_counter->counter;
4023         printer->unknown11 = 0x0;
4024         printer->printer_errors = 0x0;          /* number of print failure */
4025         printer->unknown13 = 0x0;
4026         printer->unknown14 = 0x1;
4027         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
4028         printer->unknown16 =  0x0;
4029         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4030         printer->unknown18 =  0x0;
4031         printer->status = nt_printq_status(status.status);
4032         printer->unknown20 =  0x0;
4033         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4034         printer->unknown22 = 0x0;
4035         printer->unknown23 = 0x6;               /* 6  ???*/
4036         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4037         printer->unknown25 = 0;
4038         printer->unknown26 = 0;
4039         printer->unknown27 = 0;
4040         printer->unknown28 = 0;
4041         printer->unknown29 = 0;
4042
4043         free_a_printer(&ntprinter,2);
4044         return (True);
4045 }
4046
4047 /********************************************************************
4048  * construct_printer_info_1
4049  * fill a printer_info_1 struct
4050  ********************************************************************/
4051 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4052 {
4053         char *chaine = NULL;
4054         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4055         TALLOC_CTX *ctx = talloc_tos();
4056
4057         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4058                 return false;
4059
4060         printer->flags=flags;
4061
4062         if (*ntprinter->info_2->comment == '\0') {
4063                 init_unistr(&printer->comment, lp_comment(snum));
4064                 chaine = talloc_asprintf(ctx,
4065                                 "%s,%s,%s", ntprinter->info_2->printername,
4066                                 ntprinter->info_2->drivername, lp_comment(snum));
4067         }
4068         else {
4069                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4070                 chaine = talloc_asprintf(ctx,
4071                                 "%s,%s,%s", ntprinter->info_2->printername,
4072                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4073         }
4074
4075         if (!chaine) {
4076                 free_a_printer(&ntprinter,2);
4077                 return false;
4078         }
4079
4080         init_unistr(&printer->description, chaine);
4081         init_unistr(&printer->name, ntprinter->info_2->printername);
4082
4083         free_a_printer(&ntprinter,2);
4084
4085         return True;
4086 }
4087
4088 /****************************************************************************
4089  Free a DEVMODE struct.
4090 ****************************************************************************/
4091
4092 static void free_dev_mode(DEVICEMODE *dev)
4093 {
4094         if (dev == NULL)
4095                 return;
4096
4097         SAFE_FREE(dev->dev_private);
4098         SAFE_FREE(dev);
4099 }
4100
4101
4102 /****************************************************************************
4103  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4104  should be valid upon entry
4105 ****************************************************************************/
4106
4107 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4108 {
4109         if ( !devmode || !ntdevmode )
4110                 return False;
4111
4112         init_unistr(&devmode->devicename, ntdevmode->devicename);
4113
4114         init_unistr(&devmode->formname, ntdevmode->formname);
4115
4116         devmode->specversion      = ntdevmode->specversion;
4117         devmode->driverversion    = ntdevmode->driverversion;
4118         devmode->size             = ntdevmode->size;
4119         devmode->driverextra      = ntdevmode->driverextra;
4120         devmode->fields           = ntdevmode->fields;
4121
4122         devmode->orientation      = ntdevmode->orientation;
4123         devmode->papersize        = ntdevmode->papersize;
4124         devmode->paperlength      = ntdevmode->paperlength;
4125         devmode->paperwidth       = ntdevmode->paperwidth;
4126         devmode->scale            = ntdevmode->scale;
4127         devmode->copies           = ntdevmode->copies;
4128         devmode->defaultsource    = ntdevmode->defaultsource;
4129         devmode->printquality     = ntdevmode->printquality;
4130         devmode->color            = ntdevmode->color;
4131         devmode->duplex           = ntdevmode->duplex;
4132         devmode->yresolution      = ntdevmode->yresolution;
4133         devmode->ttoption         = ntdevmode->ttoption;
4134         devmode->collate          = ntdevmode->collate;
4135         devmode->icmmethod        = ntdevmode->icmmethod;
4136         devmode->icmintent        = ntdevmode->icmintent;
4137         devmode->mediatype        = ntdevmode->mediatype;
4138         devmode->dithertype       = ntdevmode->dithertype;
4139
4140         if (ntdevmode->nt_dev_private != NULL) {
4141                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4142                         return False;
4143         }
4144
4145         return True;
4146 }
4147
4148 /****************************************************************************
4149  Create a DEVMODE struct. Returns malloced memory.
4150 ****************************************************************************/
4151
4152 DEVICEMODE *construct_dev_mode(const char *servicename)
4153 {
4154         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4155         DEVICEMODE              *devmode = NULL;
4156
4157         DEBUG(7,("construct_dev_mode\n"));
4158
4159         DEBUGADD(8,("getting printer characteristics\n"));
4160
4161         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4162                 return NULL;
4163
4164         if ( !printer->info_2->devmode ) {
4165                 DEBUG(5, ("BONG! There was no device mode!\n"));
4166                 goto done;
4167         }
4168
4169         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4170                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4171                 goto done;
4172         }
4173
4174         ZERO_STRUCTP(devmode);
4175
4176         DEBUGADD(8,("loading DEVICEMODE\n"));
4177
4178         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4179                 free_dev_mode( devmode );
4180                 devmode = NULL;
4181         }
4182
4183 done:
4184         free_a_printer(&printer,2);
4185
4186         return devmode;
4187 }
4188
4189 /********************************************************************
4190  * construct_printer_info_2
4191  * fill a printer_info_2 struct
4192  ********************************************************************/
4193
4194 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4195 {
4196         int count;
4197         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4198
4199         print_status_struct status;
4200
4201         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4202                 return False;
4203
4204         count = print_queue_length(snum, &status);
4205
4206         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4207         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4208         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4209         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4210         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4211
4212         if (*ntprinter->info_2->comment == '\0')
4213                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4214         else
4215                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4216
4217         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4218         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4219         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4220         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4221         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4222
4223         printer->attributes = ntprinter->info_2->attributes;
4224
4225         printer->priority = ntprinter->info_2->priority;                                /* priority */
4226         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4227         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4228         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4229         printer->status = nt_printq_status(status.status);                      /* status */
4230         printer->cjobs = count;                                                 /* jobs */
4231         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4232
4233         if ( !(printer->devmode = construct_dev_mode(
4234                        lp_const_servicename(snum))) )
4235                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4236
4237         printer->secdesc = NULL;
4238
4239         if ( ntprinter->info_2->secdesc_buf
4240                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4241         {
4242                 /* don't use talloc_steal() here unless you do a deep steal of all
4243                    the SEC_DESC members */
4244
4245                 printer->secdesc = dup_sec_desc( talloc_tos(),
4246                         ntprinter->info_2->secdesc_buf->sd );
4247         }
4248
4249         free_a_printer(&ntprinter, 2);
4250
4251         return True;
4252 }
4253
4254 /********************************************************************
4255  * construct_printer_info_3
4256  * fill a printer_info_3 struct
4257  ********************************************************************/
4258
4259 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4260 {
4261         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4262         PRINTER_INFO_3 *printer = NULL;
4263
4264         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4265                 return False;
4266
4267         *pp_printer = NULL;
4268         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4269                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4270                 free_a_printer(&ntprinter, 2);
4271                 return False;
4272         }
4273
4274         ZERO_STRUCTP(printer);
4275
4276         /* These are the components of the SD we are returning. */
4277
4278         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4279                 /* don't use talloc_steal() here unless you do a deep steal of all
4280                    the SEC_DESC members */
4281
4282                 printer->secdesc = dup_sec_desc( talloc_tos(),
4283                         ntprinter->info_2->secdesc_buf->sd );
4284         }
4285
4286         free_a_printer(&ntprinter, 2);
4287
4288         *pp_printer = printer;
4289         return True;
4290 }
4291
4292 /********************************************************************
4293  * construct_printer_info_4
4294  * fill a printer_info_4 struct
4295  ********************************************************************/
4296
4297 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4298 {
4299         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4300
4301         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4302                 return False;
4303
4304         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4305         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4306         printer->attributes = ntprinter->info_2->attributes;
4307
4308         free_a_printer(&ntprinter, 2);
4309         return True;
4310 }
4311
4312 /********************************************************************
4313  * construct_printer_info_5
4314  * fill a printer_info_5 struct
4315  ********************************************************************/
4316
4317 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4318 {
4319         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320
4321         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4322                 return False;
4323
4324         init_unistr(&printer->printername, ntprinter->info_2->printername);
4325         init_unistr(&printer->portname, ntprinter->info_2->portname);
4326         printer->attributes = ntprinter->info_2->attributes;
4327
4328         /* these two are not used by NT+ according to MSDN */
4329
4330         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4331         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4332
4333         free_a_printer(&ntprinter, 2);
4334
4335         return True;
4336 }
4337
4338 /********************************************************************
4339  * construct_printer_info_6
4340  * fill a printer_info_6 struct
4341  ********************************************************************/
4342
4343 static bool construct_printer_info_6(Printer_entry *print_hnd,
4344                                      PRINTER_INFO_6 *printer,
4345                                      int snum)
4346 {
4347         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4348         int count;
4349         print_status_struct status;
4350
4351         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4352                                          lp_const_servicename(snum))))
4353                 return False;
4354
4355         count = print_queue_length(snum, &status);
4356
4357         printer->status = nt_printq_status(status.status);
4358
4359         free_a_printer(&ntprinter, 2);
4360
4361         return True;
4362 }
4363
4364 /********************************************************************
4365  * construct_printer_info_7
4366  * fill a printer_info_7 struct
4367  ********************************************************************/
4368
4369 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4370 {
4371         char *guid_str = NULL;
4372         struct GUID guid;
4373
4374         if (is_printer_published(print_hnd, snum, &guid)) {
4375                 if (asprintf(&guid_str, "{%s}",
4376                              GUID_string(talloc_tos(), &guid)) == -1) {
4377                         return false;
4378                 }
4379                 strupper_m(guid_str);
4380                 init_unistr(&printer->guid, guid_str);
4381                 SAFE_FREE(guid_str);
4382                 printer->action = SPOOL_DS_PUBLISH;
4383         } else {
4384                 init_unistr(&printer->guid, "");
4385                 printer->action = SPOOL_DS_UNPUBLISH;
4386         }
4387
4388         return True;
4389 }
4390
4391 /********************************************************************
4392  Spoolss_enumprinters.
4393 ********************************************************************/
4394
4395 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4396 {
4397         int snum;
4398         int i;
4399         int n_services=lp_numservices();
4400         PRINTER_INFO_1 *printers=NULL;
4401         PRINTER_INFO_1 current_prt;
4402         WERROR result = WERR_OK;
4403
4404         DEBUG(4,("enum_all_printers_info_1\n"));
4405
4406         for (snum=0; snum<n_services; snum++) {
4407                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4408                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4409
4410                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4411                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4412                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4413                                         *returned=0;
4414                                         return WERR_NOMEM;
4415                                 }
4416                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4417
4418                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4419                                 (*returned)++;
4420                         }
4421                 }
4422         }
4423
4424         /* check the required size. */
4425         for (i=0; i<*returned; i++)
4426                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4427
4428         if (*needed > offered) {
4429                 result = WERR_INSUFFICIENT_BUFFER;
4430                 goto out;
4431         }
4432
4433         if (!rpcbuf_alloc_size(buffer, *needed)) {
4434                 result = WERR_NOMEM;
4435                 goto out;
4436         }
4437
4438         /* fill the buffer with the structures */
4439         for (i=0; i<*returned; i++)
4440                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4441
4442 out:
4443         /* clear memory */
4444
4445         SAFE_FREE(printers);
4446
4447         if ( !W_ERROR_IS_OK(result) )
4448                 *returned = 0;
4449
4450         return result;
4451 }
4452
4453 /********************************************************************
4454  enum_all_printers_info_1_local.
4455 *********************************************************************/
4456
4457 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4458 {
4459         DEBUG(4,("enum_all_printers_info_1_local\n"));
4460
4461         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4462 }
4463
4464 /********************************************************************
4465  enum_all_printers_info_1_name.
4466 *********************************************************************/
4467
4468 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4469 {
4470         char *s = name;
4471
4472         DEBUG(4,("enum_all_printers_info_1_name\n"));
4473
4474         if ((name[0] == '\\') && (name[1] == '\\'))
4475                 s = name + 2;
4476
4477         if (is_myname_or_ipaddr(s)) {
4478                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4479         }
4480         else
4481                 return WERR_INVALID_NAME;
4482 }
4483
4484 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4485 /********************************************************************
4486  enum_all_printers_info_1_remote.
4487 *********************************************************************/
4488
4489 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4490 {
4491         PRINTER_INFO_1 *printer;
4492         fstring printername;
4493         fstring desc;
4494         fstring comment;
4495         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4496         WERROR result = WERR_OK;
4497
4498         /* JFM: currently it's more a place holder than anything else.
4499          * In the spooler world there is a notion of server registration.
4500          * the print servers are registered on the PDC (in the same domain)
4501          *
4502          * We should have a TDB here. The registration is done thru an
4503          * undocumented RPC call.
4504          */
4505
4506         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4507                 return WERR_NOMEM;
4508
4509         *returned=1;
4510
4511         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4512         slprintf(desc, sizeof(desc)-1,"%s", name);
4513         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4514
4515         init_unistr(&printer->description, desc);
4516         init_unistr(&printer->name, printername);
4517         init_unistr(&printer->comment, comment);
4518         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4519
4520         /* check the required size. */
4521         *needed += spoolss_size_printer_info_1(printer);
4522
4523         if (*needed > offered) {
4524                 result = WERR_INSUFFICIENT_BUFFER;
4525                 goto out;
4526         }
4527
4528         if (!rpcbuf_alloc_size(buffer, *needed)) {
4529                 result = WERR_NOMEM;
4530                 goto out;
4531         }
4532
4533         /* fill the buffer with the structures */
4534         smb_io_printer_info_1("", buffer, printer, 0);
4535
4536 out:
4537         /* clear memory */
4538         SAFE_FREE(printer);
4539
4540         if ( !W_ERROR_IS_OK(result) )
4541                 *returned = 0;
4542
4543         return result;
4544 }
4545
4546 #endif
4547
4548 /********************************************************************
4549  enum_all_printers_info_1_network.
4550 *********************************************************************/
4551
4552 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4553 {
4554         char *s = name;
4555
4556         DEBUG(4,("enum_all_printers_info_1_network\n"));
4557
4558         /* If we respond to a enum_printers level 1 on our name with flags
4559            set to PRINTER_ENUM_REMOTE with a list of printers then these
4560            printers incorrectly appear in the APW browse list.
4561            Specifically the printers for the server appear at the workgroup
4562            level where all the other servers in the domain are
4563            listed. Windows responds to this call with a
4564            WERR_CAN_NOT_COMPLETE so we should do the same. */
4565
4566         if (name[0] == '\\' && name[1] == '\\')
4567                  s = name + 2;
4568
4569         if (is_myname_or_ipaddr(s))
4570                  return WERR_CAN_NOT_COMPLETE;
4571
4572         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4573 }
4574
4575 /********************************************************************
4576  * api_spoolss_enumprinters
4577  *
4578  * called from api_spoolss_enumprinters (see this to understand)
4579  ********************************************************************/
4580
4581 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4582 {
4583         int snum;
4584         int i;
4585         int n_services=lp_numservices();
4586         PRINTER_INFO_2 *printers=NULL;
4587         PRINTER_INFO_2 current_prt;
4588         WERROR result = WERR_OK;
4589
4590         *returned = 0;
4591
4592         for (snum=0; snum<n_services; snum++) {
4593                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4594                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4595
4596                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4597                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4598                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4599                                         *returned = 0;
4600                                         return WERR_NOMEM;
4601                                 }
4602
4603                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4604
4605                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4606
4607                                 (*returned)++;
4608                         }
4609                 }
4610         }
4611
4612         /* check the required size. */
4613         for (i=0; i<*returned; i++)
4614                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4615
4616         if (*needed > offered) {
4617                 result = WERR_INSUFFICIENT_BUFFER;
4618                 goto out;
4619         }
4620
4621         if (!rpcbuf_alloc_size(buffer, *needed)) {
4622                 result = WERR_NOMEM;
4623                 goto out;
4624         }
4625
4626         /* fill the buffer with the structures */
4627         for (i=0; i<*returned; i++)
4628                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4629
4630 out:
4631         /* clear memory */
4632
4633         for (i=0; i<*returned; i++)
4634                 free_devmode(printers[i].devmode);
4635
4636         SAFE_FREE(printers);
4637
4638         if ( !W_ERROR_IS_OK(result) )
4639                 *returned = 0;
4640
4641         return result;
4642 }
4643
4644 /********************************************************************
4645  * handle enumeration of printers at level 1
4646  ********************************************************************/
4647
4648 static WERROR enumprinters_level1( uint32 flags, fstring name,
4649                                  RPC_BUFFER *buffer, uint32 offered,
4650                                  uint32 *needed, uint32 *returned)
4651 {
4652         /* Not all the flags are equals */
4653
4654         if (flags & PRINTER_ENUM_LOCAL)
4655                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4656
4657         if (flags & PRINTER_ENUM_NAME)
4658                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4659
4660 #if 0   /* JERRY - disabled for now */
4661         if (flags & PRINTER_ENUM_REMOTE)
4662                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4663 #endif
4664
4665         if (flags & PRINTER_ENUM_NETWORK)
4666                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4667
4668         return WERR_OK; /* NT4sp5 does that */
4669 }
4670
4671 /********************************************************************
4672  * handle enumeration of printers at level 2
4673  ********************************************************************/
4674
4675 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4676                                  RPC_BUFFER *buffer, uint32 offered,
4677                                  uint32 *needed, uint32 *returned)
4678 {
4679         if (flags & PRINTER_ENUM_LOCAL) {
4680                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4681         }
4682
4683         if (flags & PRINTER_ENUM_NAME) {
4684                 if (is_myname_or_ipaddr(canon_servername(servername)))
4685                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4686                 else
4687                         return WERR_INVALID_NAME;
4688         }
4689
4690         if (flags & PRINTER_ENUM_REMOTE)
4691                 return WERR_UNKNOWN_LEVEL;
4692
4693         return WERR_OK;
4694 }
4695
4696 /********************************************************************
4697  * handle enumeration of printers at level 5
4698  ********************************************************************/
4699
4700 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4701                                  RPC_BUFFER *buffer, uint32 offered,
4702                                  uint32 *needed, uint32 *returned)
4703 {
4704 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4705         return WERR_OK;
4706 }
4707
4708 /********************************************************************
4709  * api_spoolss_enumprinters
4710  *
4711  * called from api_spoolss_enumprinters (see this to understand)
4712  ********************************************************************/
4713
4714 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4715 {
4716         uint32 flags = q_u->flags;
4717         UNISTR2 *servername = &q_u->servername;
4718         uint32 level = q_u->level;
4719         RPC_BUFFER *buffer = NULL;
4720         uint32 offered = q_u->offered;
4721         uint32 *needed = &r_u->needed;
4722         uint32 *returned = &r_u->returned;
4723
4724         fstring name;
4725
4726         /* that's an [in out] buffer */
4727
4728         if (!q_u->buffer && (offered!=0)) {
4729                 return WERR_INVALID_PARAM;
4730         }
4731
4732         if (offered > MAX_RPC_DATA_SIZE) {
4733                 return WERR_INVALID_PARAM;
4734         }
4735
4736         rpcbuf_move(q_u->buffer, &r_u->buffer);
4737         buffer = r_u->buffer;
4738
4739         DEBUG(4,("_spoolss_enumprinters\n"));
4740
4741         *needed=0;
4742         *returned=0;
4743
4744         /*
4745          * Level 1:
4746          *          flags==PRINTER_ENUM_NAME
4747          *           if name=="" then enumerates all printers
4748          *           if name!="" then enumerate the printer
4749          *          flags==PRINTER_ENUM_REMOTE
4750          *          name is NULL, enumerate printers
4751          * Level 2: name!="" enumerates printers, name can't be NULL
4752          * Level 3: doesn't exist
4753          * Level 4: does a local registry lookup
4754          * Level 5: same as Level 2
4755          */
4756
4757         unistr2_to_ascii(name, servername, sizeof(name));
4758         strupper_m(name);
4759
4760         switch (level) {
4761         case 1:
4762                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4763         case 2:
4764                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4765         case 5:
4766                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4767         case 3:
4768         case 4:
4769                 break;
4770         }
4771         return WERR_UNKNOWN_LEVEL;
4772 }
4773
4774 /****************************************************************************
4775 ****************************************************************************/
4776
4777 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4778 {
4779         PRINTER_INFO_0 *printer=NULL;
4780         WERROR result = WERR_OK;
4781
4782         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4783                 return WERR_NOMEM;
4784
4785         construct_printer_info_0(print_hnd, printer, snum);
4786
4787         /* check the required size. */
4788         *needed += spoolss_size_printer_info_0(printer);
4789
4790         if (*needed > offered) {
4791                 result = WERR_INSUFFICIENT_BUFFER;
4792                 goto out;
4793         }
4794
4795         if (!rpcbuf_alloc_size(buffer, *needed)) {
4796                 result = WERR_NOMEM;
4797                 goto out;
4798         }
4799
4800         /* fill the buffer with the structures */
4801         smb_io_printer_info_0("", buffer, printer, 0);
4802
4803 out:
4804         /* clear memory */
4805
4806         SAFE_FREE(printer);
4807
4808         return result;
4809 }
4810
4811 /****************************************************************************
4812 ****************************************************************************/
4813
4814 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4815 {
4816         PRINTER_INFO_1 *printer=NULL;
4817         WERROR result = WERR_OK;
4818
4819         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4820                 return WERR_NOMEM;
4821
4822         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4823
4824         /* check the required size. */
4825         *needed += spoolss_size_printer_info_1(printer);
4826
4827         if (*needed > offered) {
4828                 result = WERR_INSUFFICIENT_BUFFER;
4829                 goto out;
4830         }
4831
4832         if (!rpcbuf_alloc_size(buffer, *needed)) {
4833                 result = WERR_NOMEM;
4834                 goto out;
4835         }
4836
4837         /* fill the buffer with the structures */
4838         smb_io_printer_info_1("", buffer, printer, 0);
4839
4840 out:
4841         /* clear memory */
4842         SAFE_FREE(printer);
4843
4844         return result;
4845 }
4846
4847 /****************************************************************************
4848 ****************************************************************************/
4849
4850 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4851 {
4852         PRINTER_INFO_2 *printer=NULL;
4853         WERROR result = WERR_OK;
4854
4855         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4856                 return WERR_NOMEM;
4857
4858         construct_printer_info_2(print_hnd, printer, snum);
4859
4860         /* check the required size. */
4861         *needed += spoolss_size_printer_info_2(printer);
4862
4863         if (*needed > offered) {
4864                 result = WERR_INSUFFICIENT_BUFFER;
4865                 goto out;
4866         }
4867
4868         if (!rpcbuf_alloc_size(buffer, *needed)) {
4869                 result = WERR_NOMEM;
4870                 goto out;
4871         }
4872
4873         /* fill the buffer with the structures */
4874         if (!smb_io_printer_info_2("", buffer, printer, 0))
4875                 result = WERR_NOMEM;
4876
4877 out:
4878         /* clear memory */
4879         free_printer_info_2(printer);
4880
4881         return result;
4882 }
4883
4884 /****************************************************************************
4885 ****************************************************************************/
4886
4887 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4888 {
4889         PRINTER_INFO_3 *printer=NULL;
4890         WERROR result = WERR_OK;
4891
4892         if (!construct_printer_info_3(print_hnd, &printer, snum))
4893                 return WERR_NOMEM;
4894
4895         /* check the required size. */
4896         *needed += spoolss_size_printer_info_3(printer);
4897
4898         if (*needed > offered) {
4899                 result = WERR_INSUFFICIENT_BUFFER;
4900                 goto out;
4901         }
4902
4903         if (!rpcbuf_alloc_size(buffer, *needed)) {
4904                 result = WERR_NOMEM;
4905                 goto out;
4906         }
4907
4908         /* fill the buffer with the structures */
4909         smb_io_printer_info_3("", buffer, printer, 0);
4910
4911 out:
4912         /* clear memory */
4913         free_printer_info_3(printer);
4914
4915         return result;
4916 }
4917
4918 /****************************************************************************
4919 ****************************************************************************/
4920
4921 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4922 {
4923         PRINTER_INFO_4 *printer=NULL;
4924         WERROR result = WERR_OK;
4925
4926         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4927                 return WERR_NOMEM;
4928
4929         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4930                 SAFE_FREE(printer);
4931                 return WERR_NOMEM;
4932         }
4933
4934         /* check the required size. */
4935         *needed += spoolss_size_printer_info_4(printer);
4936
4937         if (*needed > offered) {
4938                 result = WERR_INSUFFICIENT_BUFFER;
4939                 goto out;
4940         }
4941
4942         if (!rpcbuf_alloc_size(buffer, *needed)) {
4943                 result = WERR_NOMEM;
4944                 goto out;
4945         }
4946
4947         /* fill the buffer with the structures */
4948         smb_io_printer_info_4("", buffer, printer, 0);
4949
4950 out:
4951         /* clear memory */
4952         free_printer_info_4(printer);
4953
4954         return result;
4955 }
4956
4957 /****************************************************************************
4958 ****************************************************************************/
4959
4960 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4961 {
4962         PRINTER_INFO_5 *printer=NULL;
4963         WERROR result = WERR_OK;
4964
4965         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4966                 return WERR_NOMEM;
4967
4968         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4969                 free_printer_info_5(printer);
4970                 return WERR_NOMEM;
4971         }
4972
4973         /* check the required size. */
4974         *needed += spoolss_size_printer_info_5(printer);
4975
4976         if (*needed > offered) {
4977                 result = WERR_INSUFFICIENT_BUFFER;
4978                 goto out;
4979         }
4980
4981         if (!rpcbuf_alloc_size(buffer, *needed)) {
4982                 result = WERR_NOMEM;
4983                 goto out;
4984         }
4985
4986         /* fill the buffer with the structures */
4987         smb_io_printer_info_5("", buffer, printer, 0);
4988
4989 out:
4990         /* clear memory */
4991         free_printer_info_5(printer);
4992
4993         return result;
4994 }
4995
4996 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4997                                  int snum,
4998                                  RPC_BUFFER *buffer, uint32 offered,
4999                                  uint32 *needed)
5000 {
5001         PRINTER_INFO_6 *printer;
5002         WERROR result = WERR_OK;
5003
5004         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5005                 return WERR_NOMEM;
5006         }
5007
5008         if (!construct_printer_info_6(print_hnd, printer, snum)) {
5009                 free_printer_info_6(printer);
5010                 return WERR_NOMEM;
5011         }
5012
5013         /* check the required size. */
5014         *needed += spoolss_size_printer_info_6(printer);
5015
5016         if (*needed > offered) {
5017                 result = WERR_INSUFFICIENT_BUFFER;
5018                 goto out;
5019         }
5020
5021         if (!rpcbuf_alloc_size(buffer, *needed)) {
5022                 result = WERR_NOMEM;
5023                 goto out;
5024         }
5025
5026         /* fill the buffer with the structures */
5027         smb_io_printer_info_6("", buffer, printer, 0);
5028
5029 out:
5030         /* clear memory */
5031         free_printer_info_6(printer);
5032
5033         return result;
5034 }
5035
5036 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5037 {
5038         PRINTER_INFO_7 *printer=NULL;
5039         WERROR result = WERR_OK;
5040
5041         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5042                 return WERR_NOMEM;
5043
5044         if (!construct_printer_info_7(print_hnd, printer, snum)) {
5045                 result = WERR_NOMEM;
5046                 goto out;
5047         }
5048
5049         /* check the required size. */
5050         *needed += spoolss_size_printer_info_7(printer);
5051
5052         if (*needed > offered) {
5053                 result = WERR_INSUFFICIENT_BUFFER;
5054                 goto out;
5055         }
5056
5057         if (!rpcbuf_alloc_size(buffer, *needed)) {
5058                 result = WERR_NOMEM;
5059                 goto out;
5060
5061         }
5062
5063         /* fill the buffer with the structures */
5064         smb_io_printer_info_7("", buffer, printer, 0);
5065
5066 out:
5067         /* clear memory */
5068         free_printer_info_7(printer);
5069
5070         return result;
5071 }
5072
5073 /****************************************************************************
5074 ****************************************************************************/
5075
5076 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5077 {
5078         POLICY_HND *handle = &q_u->handle;
5079         uint32 level = q_u->level;
5080         RPC_BUFFER *buffer = NULL;
5081         uint32 offered = q_u->offered;
5082         uint32 *needed = &r_u->needed;
5083         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5084
5085         int snum;
5086
5087         /* that's an [in out] buffer */
5088
5089         if (!q_u->buffer && (offered!=0)) {
5090                 return WERR_INVALID_PARAM;
5091         }
5092
5093         if (offered > MAX_RPC_DATA_SIZE) {
5094                 return WERR_INVALID_PARAM;
5095         }
5096
5097         rpcbuf_move(q_u->buffer, &r_u->buffer);
5098         buffer = r_u->buffer;
5099
5100         *needed=0;
5101
5102         if (!get_printer_snum(p, handle, &snum, NULL))
5103                 return WERR_BADFID;
5104
5105         switch (level) {
5106         case 0:
5107                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5108         case 1:
5109                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5110         case 2:
5111                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5112         case 3:
5113                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5114         case 4:
5115                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5116         case 5:
5117                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5118         case 6:
5119                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5120         case 7:
5121                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5122         }
5123         return WERR_UNKNOWN_LEVEL;
5124 }
5125
5126 /********************************************************************
5127  * fill a DRIVER_INFO_1 struct
5128  ********************************************************************/
5129
5130 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5131 {
5132         init_unistr( &info->name, driver.info_3->name);
5133 }
5134
5135 /********************************************************************
5136  * construct_printer_driver_info_1
5137  ********************************************************************/
5138
5139 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5140 {
5141         NT_PRINTER_INFO_LEVEL *printer = NULL;
5142         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5143
5144         ZERO_STRUCT(driver);
5145
5146         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5147                 return WERR_INVALID_PRINTER_NAME;
5148
5149         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5150                 free_a_printer(&printer, 2);
5151                 return WERR_UNKNOWN_PRINTER_DRIVER;
5152         }
5153
5154         fill_printer_driver_info_1(info, driver, servername, architecture);
5155
5156         free_a_printer(&printer,2);
5157
5158         return WERR_OK;
5159 }
5160
5161 /********************************************************************
5162  * construct_printer_driver_info_2
5163  * fill a printer_info_2 struct
5164  ********************************************************************/
5165
5166 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5167 {
5168         TALLOC_CTX *ctx = talloc_tos();
5169         char *temp = NULL;
5170         const char *cservername = canon_servername(servername);
5171
5172         info->version=driver.info_3->cversion;
5173
5174         init_unistr( &info->name, driver.info_3->name );
5175         init_unistr( &info->architecture, driver.info_3->environment );
5176
5177         if (strlen(driver.info_3->driverpath)) {
5178                 temp = talloc_asprintf(ctx,
5179                                 "\\\\%s%s",
5180                                 cservername,
5181                                 driver.info_3->driverpath);
5182                 init_unistr( &info->driverpath, temp );
5183         } else {
5184                 init_unistr( &info->driverpath, "" );
5185         }
5186
5187         TALLOC_FREE(temp);
5188         if (strlen(driver.info_3->datafile)) {
5189                 temp = talloc_asprintf(ctx,
5190                                 "\\\\%s%s",
5191                                 cservername,
5192                                 driver.info_3->datafile);
5193                 init_unistr( &info->datafile, temp );
5194         } else
5195                 init_unistr( &info->datafile, "" );
5196
5197         TALLOC_FREE(temp);
5198         if (strlen(driver.info_3->configfile)) {
5199                 temp = talloc_asprintf(ctx,
5200                                 "\\\\%s%s",
5201                                 cservername,
5202                                 driver.info_3->configfile);
5203                 init_unistr( &info->configfile, temp );
5204         } else
5205                 init_unistr( &info->configfile, "" );
5206 }
5207
5208 /********************************************************************
5209  * construct_printer_driver_info_2
5210  * fill a printer_info_2 struct
5211  ********************************************************************/
5212
5213 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5214 {
5215         NT_PRINTER_INFO_LEVEL *printer = NULL;
5216         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5217
5218         ZERO_STRUCT(printer);
5219         ZERO_STRUCT(driver);
5220
5221         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5222                 return WERR_INVALID_PRINTER_NAME;
5223
5224         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5225                 free_a_printer(&printer, 2);
5226                 return WERR_UNKNOWN_PRINTER_DRIVER;
5227         }
5228
5229         fill_printer_driver_info_2(info, driver, servername);
5230
5231         free_a_printer(&printer,2);
5232
5233         return WERR_OK;
5234 }
5235
5236 /********************************************************************
5237  * copy a strings array and convert to UNICODE
5238  *
5239  * convert an array of ascii string to a UNICODE string
5240  ********************************************************************/
5241
5242 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5243 {
5244         int i=0;
5245         int j=0;
5246         const char *v;
5247         char *line = NULL;
5248         TALLOC_CTX *ctx = talloc_tos();
5249
5250         DEBUG(6,("init_unistr_array\n"));
5251         *uni_array=NULL;
5252
5253         while (true) {
5254                 if ( !char_array ) {
5255                         v = "";
5256                 } else {
5257                         v = char_array[i];
5258                         if (!v)
5259                                 v = ""; /* hack to handle null lists */
5260                 }
5261
5262                 /* hack to allow this to be used in places other than when generating
5263                    the list of dependent files */
5264
5265                 TALLOC_FREE(line);
5266                 if ( servername ) {
5267                         line = talloc_asprintf(ctx,
5268                                         "\\\\%s%s",
5269                                         canon_servername(servername),
5270                                         v);
5271                 } else {
5272                         line = talloc_strdup(ctx, v);
5273                 }
5274
5275                 if (!line) {
5276                         SAFE_FREE(*uni_array);
5277                         return 0;
5278                 }
5279                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5280
5281                 /* add one extra unit16 for the second terminating NULL */
5282
5283                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5284                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5285                         return 0;
5286                 }
5287
5288                 if ( !strlen(v) )
5289                         break;
5290
5291                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5292                 i++;
5293         }
5294
5295         if (*uni_array) {
5296                 /* special case for ""; we need to add both NULL's here */
5297                 if (!j)
5298                         (*uni_array)[j++]=0x0000;
5299                 (*uni_array)[j]=0x0000;
5300         }
5301
5302         DEBUGADD(6,("last one:done\n"));
5303
5304         /* return size of array in uint16's */
5305
5306         return j+1;
5307 }
5308
5309 /********************************************************************
5310  * construct_printer_info_3
5311  * fill a printer_info_3 struct
5312  ********************************************************************/
5313
5314 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5315 {
5316         char *temp = NULL;
5317         TALLOC_CTX *ctx = talloc_tos();
5318         const char *cservername = canon_servername(servername);
5319
5320         ZERO_STRUCTP(info);
5321
5322         info->version=driver.info_3->cversion;
5323
5324         init_unistr( &info->name, driver.info_3->name );
5325         init_unistr( &info->architecture, driver.info_3->environment );
5326
5327         if (strlen(driver.info_3->driverpath)) {
5328                 temp = talloc_asprintf(ctx,
5329                                 "\\\\%s%s",
5330                                 cservername,
5331                                 driver.info_3->driverpath);
5332                 init_unistr( &info->driverpath, temp );
5333         } else
5334                 init_unistr( &info->driverpath, "" );
5335
5336         TALLOC_FREE(temp);
5337         if (strlen(driver.info_3->datafile)) {
5338                 temp = talloc_asprintf(ctx,
5339                                 "\\\\%s%s",
5340                                 cservername,
5341                                 driver.info_3->datafile);
5342                 init_unistr( &info->datafile, temp );
5343         } else
5344                 init_unistr( &info->datafile, "" );
5345
5346         TALLOC_FREE(temp);
5347         if (strlen(driver.info_3->configfile)) {
5348                 temp = talloc_asprintf(ctx,
5349                                 "\\\\%s%s",
5350                                 cservername,
5351                                 driver.info_3->configfile);
5352                 init_unistr( &info->configfile, temp );
5353         } else
5354                 init_unistr( &info->configfile, "" );
5355
5356         TALLOC_FREE(temp);
5357         if (strlen(driver.info_3->helpfile)) {
5358                 temp = talloc_asprintf(ctx,
5359                                 "\\\\%s%s",
5360                                 cservername,
5361                                 driver.info_3->helpfile);
5362                 init_unistr( &info->helpfile, temp );
5363         } else
5364                 init_unistr( &info->helpfile, "" );
5365
5366         TALLOC_FREE(temp);
5367         init_unistr( &info->monitorname, driver.info_3->monitorname );
5368         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5369
5370         info->dependentfiles=NULL;
5371         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5372 }
5373
5374 /********************************************************************
5375  * construct_printer_info_3
5376  * fill a printer_info_3 struct
5377  ********************************************************************/
5378
5379 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5380 {
5381         NT_PRINTER_INFO_LEVEL *printer = NULL;
5382         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5383         WERROR status;
5384         ZERO_STRUCT(driver);
5385
5386         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5387         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5388         if (!W_ERROR_IS_OK(status))
5389                 return WERR_INVALID_PRINTER_NAME;
5390
5391         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5392         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5393
5394 #if 0   /* JERRY */
5395
5396         /*
5397          * I put this code in during testing.  Helpful when commenting out the
5398          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5399          * as win2k always queries the driver using an infor level of 6.
5400          * I've left it in (but ifdef'd out) because I'll probably
5401          * use it in experimentation again in the future.   --jerry 22/01/2002
5402          */
5403
5404         if (!W_ERROR_IS_OK(status)) {
5405                 /*
5406                  * Is this a W2k client ?
5407                  */
5408                 if (version == 3) {
5409                         /* Yes - try again with a WinNT driver. */
5410                         version = 2;
5411                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5412                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5413                 }
5414 #endif
5415
5416                 if (!W_ERROR_IS_OK(status)) {
5417                         free_a_printer(&printer,2);
5418                         return WERR_UNKNOWN_PRINTER_DRIVER;
5419                 }
5420
5421 #if 0   /* JERRY */
5422         }
5423 #endif
5424
5425
5426         fill_printer_driver_info_3(info, driver, servername);
5427
5428         free_a_printer(&printer,2);
5429
5430         return WERR_OK;
5431 }
5432
5433 /********************************************************************
5434  * construct_printer_info_6
5435  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5436  ********************************************************************/
5437
5438 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5439 {
5440         char *temp = NULL;
5441         fstring nullstr;
5442         TALLOC_CTX *ctx = talloc_tos();
5443         const char *cservername = canon_servername(servername);
5444
5445         ZERO_STRUCTP(info);
5446         memset(&nullstr, '\0', sizeof(fstring));
5447
5448         info->version=driver.info_3->cversion;
5449
5450         init_unistr( &info->name, driver.info_3->name );
5451         init_unistr( &info->architecture, driver.info_3->environment );
5452
5453         if (strlen(driver.info_3->driverpath)) {
5454                 temp = talloc_asprintf(ctx,
5455                                 "\\\\%s%s",
5456                                 cservername,
5457                                 driver.info_3->driverpath);
5458                 init_unistr( &info->driverpath, temp );
5459         } else
5460                 init_unistr( &info->driverpath, "" );
5461
5462         TALLOC_FREE(temp);
5463         if (strlen(driver.info_3->datafile)) {
5464                 temp = talloc_asprintf(ctx,
5465                                 "\\\\%s%s",
5466                                 cservername,
5467                                 driver.info_3->datafile);
5468                 init_unistr( &info->datafile, temp );
5469         } else
5470                 init_unistr( &info->datafile, "" );
5471
5472         TALLOC_FREE(temp);
5473         if (strlen(driver.info_3->configfile)) {
5474                 temp = talloc_asprintf(ctx,
5475                                 "\\\\%s%s",
5476                                 cservername,
5477                                 driver.info_3->configfile);
5478                 init_unistr( &info->configfile, temp );
5479         } else
5480                 init_unistr( &info->configfile, "" );
5481
5482         TALLOC_FREE(temp);
5483         if (strlen(driver.info_3->helpfile)) {
5484                 temp = talloc_asprintf(ctx,
5485                                 "\\\\%s%s",
5486                                 cservername,
5487                                 driver.info_3->helpfile);
5488                 init_unistr( &info->helpfile, temp );
5489         } else
5490                 init_unistr( &info->helpfile, "" );
5491
5492         TALLOC_FREE(temp);
5493         init_unistr( &info->monitorname, driver.info_3->monitorname );
5494         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5495
5496         info->dependentfiles = NULL;
5497         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5498
5499         info->previousdrivernames=NULL;
5500         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5501
5502         info->driver_date=0;
5503
5504         info->padding=0;
5505         info->driver_version_low=0;
5506         info->driver_version_high=0;
5507
5508         init_unistr( &info->mfgname, "");
5509         init_unistr( &info->oem_url, "");
5510         init_unistr( &info->hardware_id, "");
5511         init_unistr( &info->provider, "");
5512 }
5513
5514 /********************************************************************
5515  * construct_printer_info_6
5516  * fill a printer_info_6 struct
5517  ********************************************************************/
5518
5519 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5520               const char *servername, fstring architecture, uint32 version)
5521 {
5522         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5523         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5524         WERROR                          status;
5525
5526         ZERO_STRUCT(driver);
5527
5528         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5529
5530         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5531
5532         if (!W_ERROR_IS_OK(status))
5533                 return WERR_INVALID_PRINTER_NAME;
5534
5535         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5536
5537         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5538
5539         if (!W_ERROR_IS_OK(status))
5540         {
5541                 /*
5542                  * Is this a W2k client ?
5543                  */
5544
5545                 if (version < 3) {
5546                         free_a_printer(&printer,2);
5547                         return WERR_UNKNOWN_PRINTER_DRIVER;
5548                 }
5549
5550                 /* Yes - try again with a WinNT driver. */
5551                 version = 2;
5552                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5553                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5554                 if (!W_ERROR_IS_OK(status)) {
5555                         free_a_printer(&printer,2);
5556                         return WERR_UNKNOWN_PRINTER_DRIVER;
5557                 }
5558         }
5559
5560         fill_printer_driver_info_6(info, driver, servername);
5561
5562         free_a_printer(&printer,2);
5563         free_a_printer_driver(driver, 3);
5564
5565         return WERR_OK;
5566 }
5567
5568 /****************************************************************************
5569 ****************************************************************************/
5570
5571 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5572 {
5573         SAFE_FREE(info->dependentfiles);
5574 }
5575
5576 /****************************************************************************
5577 ****************************************************************************/
5578
5579 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5580 {
5581         SAFE_FREE(info->dependentfiles);
5582 }
5583
5584 /****************************************************************************
5585 ****************************************************************************/
5586
5587 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5588 {
5589         DRIVER_INFO_1 *info=NULL;
5590         WERROR result;
5591
5592         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5593                 return WERR_NOMEM;
5594
5595         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5596         if (!W_ERROR_IS_OK(result))
5597                 goto out;
5598
5599         /* check the required size. */
5600         *needed += spoolss_size_printer_driver_info_1(info);
5601
5602         if (*needed > offered) {
5603                 result = WERR_INSUFFICIENT_BUFFER;
5604                 goto out;
5605         }
5606
5607         if (!rpcbuf_alloc_size(buffer, *needed)) {
5608                 result = WERR_NOMEM;
5609                 goto out;
5610         }
5611
5612         /* fill the buffer with the structures */
5613         smb_io_printer_driver_info_1("", buffer, info, 0);
5614
5615 out:
5616         /* clear memory */
5617         SAFE_FREE(info);
5618
5619         return result;
5620 }
5621
5622 /****************************************************************************
5623 ****************************************************************************/
5624
5625 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5626 {
5627         DRIVER_INFO_2 *info=NULL;
5628         WERROR result;
5629
5630         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5631                 return WERR_NOMEM;
5632
5633         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5634         if (!W_ERROR_IS_OK(result))
5635                 goto out;
5636
5637         /* check the required size. */
5638         *needed += spoolss_size_printer_driver_info_2(info);
5639
5640         if (*needed > offered) {
5641                 result = WERR_INSUFFICIENT_BUFFER;
5642                 goto out;
5643         }
5644
5645         if (!rpcbuf_alloc_size(buffer, *needed)) {
5646                 result = WERR_NOMEM;
5647                 goto out;
5648         }
5649
5650         /* fill the buffer with the structures */
5651         smb_io_printer_driver_info_2("", buffer, info, 0);
5652
5653 out:
5654         /* clear memory */
5655         SAFE_FREE(info);
5656
5657         return result;
5658 }
5659
5660 /****************************************************************************
5661 ****************************************************************************/
5662
5663 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5664 {
5665         DRIVER_INFO_3 info;
5666         WERROR result;
5667
5668         ZERO_STRUCT(info);
5669
5670         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5671         if (!W_ERROR_IS_OK(result))
5672                 goto out;
5673
5674         /* check the required size. */
5675         *needed += spoolss_size_printer_driver_info_3(&info);
5676
5677         if (*needed > offered) {
5678                 result = WERR_INSUFFICIENT_BUFFER;
5679                 goto out;
5680         }
5681
5682         if (!rpcbuf_alloc_size(buffer, *needed)) {
5683                 result = WERR_NOMEM;
5684                 goto out;
5685         }
5686
5687         /* fill the buffer with the structures */
5688         smb_io_printer_driver_info_3("", buffer, &info, 0);
5689
5690 out:
5691         free_printer_driver_info_3(&info);
5692
5693         return result;
5694 }
5695
5696 /****************************************************************************
5697 ****************************************************************************/
5698
5699 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5700 {
5701         DRIVER_INFO_6 info;
5702         WERROR result;
5703
5704         ZERO_STRUCT(info);
5705
5706         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5707         if (!W_ERROR_IS_OK(result))
5708                 goto out;
5709
5710         /* check the required size. */
5711         *needed += spoolss_size_printer_driver_info_6(&info);
5712
5713         if (*needed > offered) {
5714                 result = WERR_INSUFFICIENT_BUFFER;
5715                 goto out;
5716         }
5717
5718         if (!rpcbuf_alloc_size(buffer, *needed)) {
5719                 result = WERR_NOMEM;
5720                 goto out;
5721         }
5722
5723         /* fill the buffer with the structures */
5724         smb_io_printer_driver_info_6("", buffer, &info, 0);
5725
5726 out:
5727         free_printer_driver_info_6(&info);
5728
5729         return result;
5730 }
5731
5732 /****************************************************************************
5733 ****************************************************************************/
5734
5735 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5736 {
5737         POLICY_HND *handle = &q_u->handle;
5738         UNISTR2 *uni_arch = &q_u->architecture;
5739         uint32 level = q_u->level;
5740         uint32 clientmajorversion = q_u->clientmajorversion;
5741         RPC_BUFFER *buffer = NULL;
5742         uint32 offered = q_u->offered;
5743         uint32 *needed = &r_u->needed;
5744         uint32 *servermajorversion = &r_u->servermajorversion;
5745         uint32 *serverminorversion = &r_u->serverminorversion;
5746         Printer_entry *printer;
5747
5748         fstring servername;
5749         fstring architecture;
5750         int snum;
5751
5752         /* that's an [in out] buffer */
5753
5754         if (!q_u->buffer && (offered!=0)) {
5755                 return WERR_INVALID_PARAM;
5756         }
5757
5758         if (offered > MAX_RPC_DATA_SIZE) {
5759                 return WERR_INVALID_PARAM;
5760         }
5761
5762         rpcbuf_move(q_u->buffer, &r_u->buffer);
5763         buffer = r_u->buffer;
5764
5765         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5766
5767         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5768                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5769                 return WERR_INVALID_PRINTER_NAME;
5770         }
5771
5772         *needed = 0;
5773         *servermajorversion = 0;
5774         *serverminorversion = 0;
5775
5776         fstrcpy(servername, get_server_name( printer ));
5777         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5778
5779         if (!get_printer_snum(p, handle, &snum, NULL))
5780                 return WERR_BADFID;
5781
5782         switch (level) {
5783         case 1:
5784                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5785         case 2:
5786                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5787         case 3:
5788                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5789         case 6:
5790                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5791 #if 0   /* JERRY */
5792         case 101:
5793                 /* apparently this call is the equivalent of
5794                    EnumPrinterDataEx() for the DsDriver key */
5795                 break;
5796 #endif
5797         }
5798
5799         return WERR_UNKNOWN_LEVEL;
5800 }
5801
5802
5803 /****************************************************************
5804  _spoolss_StartPagePrinter
5805 ****************************************************************/
5806
5807 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5808                                  struct spoolss_StartPagePrinter *r)
5809 {
5810         POLICY_HND *handle = r->in.handle;
5811
5812         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5813
5814         if (!Printer) {
5815                 DEBUG(3,("_spoolss_StartPagePrinter: "
5816                         "Error in startpageprinter printer handle\n"));
5817                 return WERR_BADFID;
5818         }
5819
5820         Printer->page_started=True;
5821         return WERR_OK;
5822 }
5823
5824 /****************************************************************
5825  _spoolss_EndPagePrinter
5826 ****************************************************************/
5827
5828 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5829                                struct spoolss_EndPagePrinter *r)
5830 {
5831         POLICY_HND *handle = r->in.handle;
5832         int snum;
5833
5834         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5835
5836         if (!Printer) {
5837                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5838                         OUR_HANDLE(handle)));
5839                 return WERR_BADFID;
5840         }
5841
5842         if (!get_printer_snum(p, handle, &snum, NULL))
5843                 return WERR_BADFID;
5844
5845         Printer->page_started=False;
5846         print_job_endpage(snum, Printer->jobid);
5847
5848         return WERR_OK;
5849 }
5850
5851 /****************************************************************
5852  _spoolss_StartDocPrinter
5853 ****************************************************************/
5854
5855 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5856                                 struct spoolss_StartDocPrinter *r)
5857 {
5858         POLICY_HND *handle = r->in.handle;
5859         uint32_t *jobid = r->out.job_id;
5860         struct spoolss_DocumentInfo1 *info_1;
5861         int snum;
5862         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5863
5864         if (!Printer) {
5865                 DEBUG(2,("_spoolss_StartDocPrinter: "
5866                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5867                 return WERR_BADFID;
5868         }
5869
5870         if (r->in.level != 1) {
5871                 return WERR_UNKNOWN_LEVEL;
5872         }
5873
5874         info_1 = r->in.info.info1;
5875
5876         /*
5877          * a nice thing with NT is it doesn't listen to what you tell it.
5878          * when asked to send _only_ RAW datas, it tries to send datas
5879          * in EMF format.
5880          *
5881          * So I add checks like in NT Server ...
5882          */
5883
5884         if (info_1->datatype) {
5885                 if (strcmp(info_1->datatype, "RAW") != 0) {
5886                         (*jobid)=0;
5887                         return WERR_INVALID_DATATYPE;
5888                 }
5889         }
5890
5891         /* get the share number of the printer */
5892         if (!get_printer_snum(p, handle, &snum, NULL)) {
5893                 return WERR_BADFID;
5894         }
5895
5896         Printer->jobid = print_job_start(p->server_info, snum,
5897                                          CONST_DISCARD(char *,info_1->document_name),
5898                                          Printer->nt_devmode);
5899
5900         /* An error occured in print_job_start() so return an appropriate
5901            NT error code. */
5902
5903         if (Printer->jobid == -1) {
5904                 return map_werror_from_unix(errno);
5905         }
5906
5907         Printer->document_started=True;
5908         (*jobid) = Printer->jobid;
5909
5910         return WERR_OK;
5911 }
5912
5913 /****************************************************************
5914  _spoolss_EndDocPrinter
5915 ****************************************************************/
5916
5917 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5918                               struct spoolss_EndDocPrinter *r)
5919 {
5920         POLICY_HND *handle = r->in.handle;
5921
5922         return _spoolss_enddocprinter_internal(p, handle);
5923 }
5924
5925 /****************************************************************
5926  _spoolss_WritePrinter
5927 ****************************************************************/
5928
5929 WERROR _spoolss_WritePrinter(pipes_struct *p,
5930                              struct spoolss_WritePrinter *r)
5931 {
5932         POLICY_HND *handle = r->in.handle;
5933         uint32 buffer_size = r->in._data_size;
5934         uint8 *buffer = r->in.data.data;
5935         uint32 *buffer_written = &r->in._data_size;
5936         int snum;
5937         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5938
5939         if (!Printer) {
5940                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5941                         OUR_HANDLE(handle)));
5942                 *r->out.num_written = r->in._data_size;
5943                 return WERR_BADFID;
5944         }
5945
5946         if (!get_printer_snum(p, handle, &snum, NULL))
5947                 return WERR_BADFID;
5948
5949         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5950                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5951         if (*buffer_written == (uint32)-1) {
5952                 *r->out.num_written = 0;
5953                 if (errno == ENOSPC)
5954                         return WERR_NO_SPOOL_SPACE;
5955                 else
5956                         return WERR_ACCESS_DENIED;
5957         }
5958
5959         *r->out.num_written = r->in._data_size;
5960
5961         return WERR_OK;
5962 }
5963
5964 /********************************************************************
5965  * api_spoolss_getprinter
5966  * called from the spoolss dispatcher
5967  *
5968  ********************************************************************/
5969
5970 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5971                               pipes_struct *p)
5972 {
5973         int snum;
5974         WERROR errcode = WERR_BADFUNC;
5975         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5976
5977         if (!Printer) {
5978                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5979                 return WERR_BADFID;
5980         }
5981
5982         if (!get_printer_snum(p, handle, &snum, NULL))
5983                 return WERR_BADFID;
5984
5985         switch (command) {
5986         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5987                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5988                         errcode = WERR_OK;
5989                 }
5990                 break;
5991         case SPOOLSS_PRINTER_CONTROL_RESUME:
5992         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5993                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5994                         errcode = WERR_OK;
5995                 }
5996                 break;
5997         case SPOOLSS_PRINTER_CONTROL_PURGE:
5998                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5999                         errcode = WERR_OK;
6000                 }
6001                 break;
6002         default:
6003                 return WERR_UNKNOWN_LEVEL;
6004         }
6005
6006         return errcode;
6007 }
6008
6009
6010 /****************************************************************
6011  _spoolss_AbortPrinter
6012  * From MSDN: "Deletes printer's spool file if printer is configured
6013  * for spooling"
6014 ****************************************************************/
6015
6016 WERROR _spoolss_AbortPrinter(pipes_struct *p,
6017                              struct spoolss_AbortPrinter *r)
6018 {
6019         POLICY_HND      *handle = r->in.handle;
6020         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
6021         int             snum;
6022         WERROR          errcode = WERR_OK;
6023
6024         if (!Printer) {
6025                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6026                         OUR_HANDLE(handle)));
6027                 return WERR_BADFID;
6028         }
6029
6030         if (!get_printer_snum(p, handle, &snum, NULL))
6031                 return WERR_BADFID;
6032
6033         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6034
6035         return errcode;
6036 }
6037
6038 /********************************************************************
6039  * called by spoolss_api_setprinter
6040  * when updating a printer description
6041  ********************************************************************/
6042
6043 static WERROR update_printer_sec(POLICY_HND *handle,
6044                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6045 {
6046         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6047         WERROR result;
6048         int snum;
6049
6050         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6051
6052         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6053                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6054                          OUR_HANDLE(handle)));
6055
6056                 result = WERR_BADFID;
6057                 goto done;
6058         }
6059
6060         if (!secdesc_ctr) {
6061                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6062                 result = WERR_INVALID_PARAM;
6063                 goto done;
6064         }
6065
6066         /* Check the user has permissions to change the security
6067            descriptor.  By experimentation with two NT machines, the user
6068            requires Full Access to the printer to change security
6069            information. */
6070
6071         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6072                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6073                 result = WERR_ACCESS_DENIED;
6074                 goto done;
6075         }
6076
6077         /* NT seems to like setting the security descriptor even though
6078            nothing may have actually changed. */
6079
6080         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6081                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6082                 result = WERR_BADFID;
6083                 goto done;
6084         }
6085
6086         if (DEBUGLEVEL >= 10) {
6087                 SEC_ACL *the_acl;
6088                 int i;
6089
6090                 the_acl = old_secdesc_ctr->sd->dacl;
6091                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6092                            PRINTERNAME(snum), the_acl->num_aces));
6093
6094                 for (i = 0; i < the_acl->num_aces; i++) {
6095                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6096                                            &the_acl->aces[i].trustee),
6097                                   the_acl->aces[i].access_mask));
6098                 }
6099
6100                 the_acl = secdesc_ctr->sd->dacl;
6101
6102                 if (the_acl) {
6103                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6104                                    PRINTERNAME(snum), the_acl->num_aces));
6105
6106                         for (i = 0; i < the_acl->num_aces; i++) {
6107                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6108                                                    &the_acl->aces[i].trustee),
6109                                            the_acl->aces[i].access_mask));
6110                         }
6111                 } else {
6112                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6113                 }
6114         }
6115
6116         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6117         if (!new_secdesc_ctr) {
6118                 result = WERR_NOMEM;
6119                 goto done;
6120         }
6121
6122         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6123                 result = WERR_OK;
6124                 goto done;
6125         }
6126
6127         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6128
6129  done:
6130
6131         return result;
6132 }
6133
6134 /********************************************************************
6135  Canonicalize printer info from a client
6136
6137  ATTN: It does not matter what we set the servername to hear
6138  since we do the necessary work in get_a_printer() to set it to
6139  the correct value based on what the client sent in the
6140  _spoolss_open_printer_ex().
6141  ********************************************************************/
6142
6143 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6144 {
6145         fstring printername;
6146         const char *p;
6147
6148         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6149                 "portname=%s drivername=%s comment=%s location=%s\n",
6150                 info->servername, info->printername, info->sharename,
6151                 info->portname, info->drivername, info->comment, info->location));
6152
6153         /* we force some elements to "correct" values */
6154         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6155         fstrcpy(info->sharename, lp_servicename(snum));
6156
6157         /* check to see if we allow printername != sharename */
6158
6159         if ( lp_force_printername(snum) ) {
6160                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6161                         global_myname(), info->sharename );
6162         } else {
6163
6164                 /* make sure printername is in \\server\printername format */
6165
6166                 fstrcpy( printername, info->printername );
6167                 p = printername;
6168                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6169                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6170                                 p++;
6171                 }
6172
6173                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6174                          global_myname(), p );
6175         }
6176
6177         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6178         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6179
6180
6181
6182         return True;
6183 }
6184
6185 /****************************************************************************
6186 ****************************************************************************/
6187
6188 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6189 {
6190         char *cmd = lp_addport_cmd();
6191         char *command = NULL;
6192         int ret;
6193         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6194         bool is_print_op = False;
6195
6196         if ( !*cmd ) {
6197                 return WERR_ACCESS_DENIED;
6198         }
6199
6200         command = talloc_asprintf(ctx,
6201                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6202         if (!command) {
6203                 return WERR_NOMEM;
6204         }
6205
6206         if ( token )
6207                 is_print_op = user_has_privileges( token, &se_printop );
6208
6209         DEBUG(10,("Running [%s]\n", command));
6210
6211         /********* BEGIN SePrintOperatorPrivilege **********/
6212
6213         if ( is_print_op )
6214                 become_root();
6215
6216         ret = smbrun(command, NULL);
6217
6218         if ( is_print_op )
6219                 unbecome_root();
6220
6221         /********* END SePrintOperatorPrivilege **********/
6222
6223         DEBUGADD(10,("returned [%d]\n", ret));
6224
6225         TALLOC_FREE(command);
6226
6227         if ( ret != 0 ) {
6228                 return WERR_ACCESS_DENIED;
6229         }
6230
6231         return WERR_OK;
6232 }
6233
6234 /****************************************************************************
6235 ****************************************************************************/
6236
6237 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6238 {
6239         char *cmd = lp_addprinter_cmd();
6240         char **qlines;
6241         char *command = NULL;
6242         int numlines;
6243         int ret;
6244         int fd;
6245         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6246         bool is_print_op = False;
6247         char *remote_machine = talloc_strdup(ctx, "%m");
6248
6249         if (!remote_machine) {
6250                 return false;
6251         }
6252         remote_machine = talloc_sub_basic(ctx,
6253                                 current_user_info.smb_name,
6254                                 current_user_info.domain,
6255                                 remote_machine);
6256         if (!remote_machine) {
6257                 return false;
6258         }
6259
6260         command = talloc_asprintf(ctx,
6261                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6262                         cmd, printer->info_2->printername, printer->info_2->sharename,
6263                         printer->info_2->portname, printer->info_2->drivername,
6264                         printer->info_2->location, printer->info_2->comment, remote_machine);
6265         if (!command) {
6266                 return false;
6267         }
6268
6269         if ( token )
6270                 is_print_op = user_has_privileges( token, &se_printop );
6271
6272         DEBUG(10,("Running [%s]\n", command));
6273
6274         /********* BEGIN SePrintOperatorPrivilege **********/
6275
6276         if ( is_print_op )
6277                 become_root();
6278
6279         if ( (ret = smbrun(command, &fd)) == 0 ) {
6280                 /* Tell everyone we updated smb.conf. */
6281                 message_send_all(smbd_messaging_context(),
6282                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6283         }
6284
6285         if ( is_print_op )
6286                 unbecome_root();
6287
6288         /********* END SePrintOperatorPrivilege **********/
6289
6290         DEBUGADD(10,("returned [%d]\n", ret));
6291
6292         TALLOC_FREE(command);
6293         TALLOC_FREE(remote_machine);
6294
6295         if ( ret != 0 ) {
6296                 if (fd != -1)
6297                         close(fd);
6298                 return False;
6299         }
6300
6301         /* reload our services immediately */
6302         reload_services( False );
6303
6304         numlines = 0;
6305         /* Get lines and convert them back to dos-codepage */
6306         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6307         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6308         close(fd);
6309
6310         /* Set the portname to what the script says the portname should be. */
6311         /* but don't require anything to be return from the script exit a good error code */
6312
6313         if (numlines) {
6314                 /* Set the portname to what the script says the portname should be. */
6315                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6316                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6317         }
6318
6319         TALLOC_FREE(qlines);
6320         return True;
6321 }
6322
6323
6324 /********************************************************************
6325  * Called by spoolss_api_setprinter
6326  * when updating a printer description.
6327  ********************************************************************/
6328
6329 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6330                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6331                              struct spoolss_DeviceMode *devmode)
6332 {
6333         int snum;
6334         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6335         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6336         WERROR result;
6337         UNISTR2 buffer;
6338         fstring asc_buffer;
6339
6340         DEBUG(8,("update_printer\n"));
6341
6342         result = WERR_OK;
6343
6344         if (!Printer) {
6345                 result = WERR_BADFID;
6346                 goto done;
6347         }
6348
6349         if (!get_printer_snum(p, handle, &snum, NULL)) {
6350                 result = WERR_BADFID;
6351                 goto done;
6352         }
6353
6354         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6355             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6356                 result = WERR_BADFID;
6357                 goto done;
6358         }
6359
6360         DEBUGADD(8,("Converting info_2 struct\n"));
6361
6362         /*
6363          * convert_printer_info converts the incoming
6364          * info from the client and overwrites the info
6365          * just read from the tdb in the pointer 'printer'.
6366          */
6367
6368         if (!convert_printer_info_new(info_ctr, printer)) {
6369                 result =  WERR_NOMEM;
6370                 goto done;
6371         }
6372
6373         if (devmode) {
6374                 /* we have a valid devmode
6375                    convert it and link it*/
6376
6377                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6378                 if (!convert_devicemode_new(printer->info_2->printername,
6379                                             devmode,
6380                                             &printer->info_2->devmode)) {
6381                         result =  WERR_NOMEM;
6382                         goto done;
6383                 }
6384         }
6385
6386         /* Do sanity check on the requested changes for Samba */
6387
6388         if (!check_printer_ok(printer->info_2, snum)) {
6389                 result = WERR_INVALID_PARAM;
6390                 goto done;
6391         }
6392
6393         /* FIXME!!! If the driver has changed we really should verify that
6394            it is installed before doing much else   --jerry */
6395
6396         /* Check calling user has permission to update printer description */
6397
6398         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6399                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6400                 result = WERR_ACCESS_DENIED;
6401                 goto done;
6402         }
6403
6404         /* Call addprinter hook */
6405         /* Check changes to see if this is really needed */
6406
6407         if ( *lp_addprinter_cmd()
6408                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6409                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6410                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6411                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6412         {
6413                 /* add_printer_hook() will call reload_services() */
6414
6415                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6416                                        printer) ) {
6417                         result = WERR_ACCESS_DENIED;
6418                         goto done;
6419                 }
6420         }
6421
6422         /*
6423          * When a *new* driver is bound to a printer, the drivername is used to
6424          * lookup previously saved driver initialization info, which is then
6425          * bound to the printer, simulating what happens in the Windows arch.
6426          */
6427         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6428         {
6429                 if (!set_driver_init(printer, 2))
6430                 {
6431                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6432                                 printer->info_2->drivername));
6433                 }
6434
6435                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6436                         printer->info_2->drivername));
6437
6438                 notify_printer_driver(snum, printer->info_2->drivername);
6439         }
6440
6441         /*
6442          * flag which changes actually occured.  This is a small subset of
6443          * all the possible changes.  We also have to update things in the
6444          * DsSpooler key.
6445          */
6446
6447         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6448                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6449                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6450                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451
6452                 notify_printer_comment(snum, printer->info_2->comment);
6453         }
6454
6455         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6456                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6457                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6458                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6459
6460                 notify_printer_sharename(snum, printer->info_2->sharename);
6461         }
6462
6463         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6464                 char *pname;
6465
6466                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6467                         pname++;
6468                 else
6469                         pname = printer->info_2->printername;
6470
6471
6472                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6473                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6474                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475
6476                 notify_printer_printername( snum, pname );
6477         }
6478
6479         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6480                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6481                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6482                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6483
6484                 notify_printer_port(snum, printer->info_2->portname);
6485         }
6486
6487         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6488                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6489                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6490                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6491
6492                 notify_printer_location(snum, printer->info_2->location);
6493         }
6494
6495         /* here we need to update some more DsSpooler keys */
6496         /* uNCName, serverName, shortServerName */
6497
6498         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6499         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6500                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6501         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6502                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6503
6504         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6505                  global_myname(), printer->info_2->sharename );
6506         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6507         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6508                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6509
6510         /* Update printer info */
6511         result = mod_a_printer(printer, 2);
6512
6513 done:
6514         free_a_printer(&printer, 2);
6515         free_a_printer(&old_printer, 2);
6516
6517
6518         return result;
6519 }
6520
6521 /****************************************************************************
6522 ****************************************************************************/
6523 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6524                                            struct spoolss_SetPrinterInfo7 *info7)
6525 {
6526 #ifdef HAVE_ADS
6527         int snum;
6528         Printer_entry *Printer;
6529
6530         if ( lp_security() != SEC_ADS ) {
6531                 return WERR_UNKNOWN_LEVEL;
6532         }
6533
6534         Printer = find_printer_index_by_hnd(p, handle);
6535
6536         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6537
6538         if (!Printer)
6539                 return WERR_BADFID;
6540
6541         if (!get_printer_snum(p, handle, &snum, NULL))
6542                 return WERR_BADFID;
6543
6544         nt_printer_publish(Printer, snum, info7->action);
6545
6546         return WERR_OK;
6547 #else
6548         return WERR_UNKNOWN_LEVEL;
6549 #endif
6550 }
6551
6552 /****************************************************************
6553  _spoolss_SetPrinter
6554 ****************************************************************/
6555
6556 WERROR _spoolss_SetPrinter(pipes_struct *p,
6557                            struct spoolss_SetPrinter *r)
6558 {
6559         POLICY_HND *handle = r->in.handle;
6560         WERROR result;
6561
6562         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6563
6564         if (!Printer) {
6565                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6566                         OUR_HANDLE(handle)));
6567                 return WERR_BADFID;
6568         }
6569
6570         /* check the level */
6571         switch (r->in.info_ctr->level) {
6572                 case 0:
6573                         return control_printer(handle, r->in.command, p);
6574                 case 2:
6575                         result = update_printer(p, handle,
6576                                                 r->in.info_ctr,
6577                                                 r->in.devmode_ctr->devmode);
6578                         if (!W_ERROR_IS_OK(result))
6579                                 return result;
6580                         if (r->in.secdesc_ctr->sd)
6581                                 result = update_printer_sec(handle, p,
6582                                                             r->in.secdesc_ctr);
6583                         return result;
6584                 case 3:
6585                         return update_printer_sec(handle, p,
6586                                                   r->in.secdesc_ctr);
6587                 case 7:
6588                         return publish_or_unpublish_printer(p, handle,
6589                                                             r->in.info_ctr->info.info7);
6590                 default:
6591                         return WERR_UNKNOWN_LEVEL;
6592         }
6593 }
6594
6595 /****************************************************************
6596  _spoolss_FindClosePrinterNotify
6597 ****************************************************************/
6598
6599 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6600                                        struct spoolss_FindClosePrinterNotify *r)
6601 {
6602         POLICY_HND *handle = r->in.handle;
6603         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6604
6605         if (!Printer) {
6606                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6607                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6608                 return WERR_BADFID;
6609         }
6610
6611         if (Printer->notify.client_connected==True) {
6612                 int snum = -1;
6613
6614                 if ( Printer->printer_type == SPLHND_SERVER)
6615                         snum = -1;
6616                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6617                                 !get_printer_snum(p, handle, &snum, NULL) )
6618                         return WERR_BADFID;
6619
6620                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6621         }
6622
6623         Printer->notify.flags=0;
6624         Printer->notify.options=0;
6625         Printer->notify.localmachine[0]='\0';
6626         Printer->notify.printerlocal=0;
6627         if (Printer->notify.option)
6628                 free_spool_notify_option(&Printer->notify.option);
6629         Printer->notify.client_connected=False;
6630
6631         return WERR_OK;
6632 }
6633
6634 /****************************************************************
6635  _spoolss_AddJob
6636 ****************************************************************/
6637
6638 WERROR _spoolss_AddJob(pipes_struct *p,
6639                        struct spoolss_AddJob *r)
6640 {
6641         if (!r->in.buffer && (r->in.offered != 0)) {
6642                 return WERR_INVALID_PARAM;
6643         }
6644
6645         /* this is what a NT server returns for AddJob. AddJob must fail on
6646          * non-local printers */
6647
6648         return WERR_INVALID_PARAM;
6649 }
6650
6651 /****************************************************************************
6652 ****************************************************************************/
6653
6654 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6655                             int position, int snum,
6656                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6657 {
6658         struct tm *t;
6659
6660         t=gmtime(&queue->time);
6661
6662         job_info->jobid=queue->job;
6663         init_unistr(&job_info->printername, lp_servicename(snum));
6664         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6665         init_unistr(&job_info->username, queue->fs_user);
6666         init_unistr(&job_info->document, queue->fs_file);
6667         init_unistr(&job_info->datatype, "RAW");
6668         init_unistr(&job_info->text_status, "");
6669         job_info->status=nt_printj_status(queue->status);
6670         job_info->priority=queue->priority;
6671         job_info->position=position;
6672         job_info->totalpages=queue->page_count;
6673         job_info->pagesprinted=0;
6674
6675         make_systemtime(&job_info->submitted, t);
6676 }
6677
6678 /****************************************************************************
6679 ****************************************************************************/
6680
6681 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6682                             int position, int snum,
6683                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6684                             DEVICEMODE *devmode)
6685 {
6686         struct tm *t;
6687
6688         t=gmtime(&queue->time);
6689
6690         job_info->jobid=queue->job;
6691
6692         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6693
6694         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6695         init_unistr(&job_info->username, queue->fs_user);
6696         init_unistr(&job_info->document, queue->fs_file);
6697         init_unistr(&job_info->notifyname, queue->fs_user);
6698         init_unistr(&job_info->datatype, "RAW");
6699         init_unistr(&job_info->printprocessor, "winprint");
6700         init_unistr(&job_info->parameters, "");
6701         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6702         init_unistr(&job_info->text_status, "");
6703
6704 /* and here the security descriptor */
6705
6706         job_info->status=nt_printj_status(queue->status);
6707         job_info->priority=queue->priority;
6708         job_info->position=position;
6709         job_info->starttime=0;
6710         job_info->untiltime=0;
6711         job_info->totalpages=queue->page_count;
6712         job_info->size=queue->size;
6713         make_systemtime(&(job_info->submitted), t);
6714         job_info->timeelapsed=0;
6715         job_info->pagesprinted=0;
6716
6717         job_info->devmode = devmode;
6718
6719         return (True);
6720 }
6721
6722 /****************************************************************************
6723  Enumjobs at level 1.
6724 ****************************************************************************/
6725
6726 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6727                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6728                               RPC_BUFFER *buffer, uint32 offered,
6729                               uint32 *needed, uint32 *returned)
6730 {
6731         JOB_INFO_1 *info;
6732         int i;
6733         WERROR result = WERR_OK;
6734
6735         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6736         if (info==NULL) {
6737                 *returned=0;
6738                 return WERR_NOMEM;
6739         }
6740
6741         for (i=0; i<*returned; i++)
6742                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6743
6744         /* check the required size. */
6745         for (i=0; i<*returned; i++)
6746                 (*needed) += spoolss_size_job_info_1(&info[i]);
6747
6748         if (*needed > offered) {
6749                 result = WERR_INSUFFICIENT_BUFFER;
6750                 goto out;
6751         }
6752
6753         if (!rpcbuf_alloc_size(buffer, *needed)) {
6754                 result = WERR_NOMEM;
6755                 goto out;
6756         }
6757
6758         /* fill the buffer with the structures */
6759         for (i=0; i<*returned; i++)
6760                 smb_io_job_info_1("", buffer, &info[i], 0);
6761
6762 out:
6763         /* clear memory */
6764         SAFE_FREE(info);
6765
6766         if ( !W_ERROR_IS_OK(result) )
6767                 *returned = 0;
6768
6769         return result;
6770 }
6771
6772 /****************************************************************************
6773  Enumjobs at level 2.
6774 ****************************************************************************/
6775
6776 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6777                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6778                               RPC_BUFFER *buffer, uint32 offered,
6779                               uint32 *needed, uint32 *returned)
6780 {
6781         JOB_INFO_2 *info = NULL;
6782         int i;
6783         WERROR result = WERR_OK;
6784         DEVICEMODE *devmode = NULL;
6785
6786         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6787                 *returned=0;
6788                 return WERR_NOMEM;
6789         }
6790
6791         /* this should not be a failure condition if the devmode is NULL */
6792
6793         devmode = construct_dev_mode(lp_const_servicename(snum));
6794
6795         for (i=0; i<*returned; i++)
6796                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6797
6798         /* check the required size. */
6799         for (i=0; i<*returned; i++)
6800                 (*needed) += spoolss_size_job_info_2(&info[i]);
6801
6802         if (*needed > offered) {
6803                 result = WERR_INSUFFICIENT_BUFFER;
6804                 goto out;
6805         }
6806
6807         if (!rpcbuf_alloc_size(buffer, *needed)) {
6808                 result = WERR_NOMEM;
6809                 goto out;
6810         }
6811
6812         /* fill the buffer with the structures */
6813         for (i=0; i<*returned; i++)
6814                 smb_io_job_info_2("", buffer, &info[i], 0);
6815
6816 out:
6817         free_devmode(devmode);
6818         SAFE_FREE(info);
6819
6820         if ( !W_ERROR_IS_OK(result) )
6821                 *returned = 0;
6822
6823         return result;
6824
6825 }
6826
6827 /****************************************************************************
6828  Enumjobs.
6829 ****************************************************************************/
6830
6831 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6832 {
6833         POLICY_HND *handle = &q_u->handle;
6834         uint32 level = q_u->level;
6835         RPC_BUFFER *buffer = NULL;
6836         uint32 offered = q_u->offered;
6837         uint32 *needed = &r_u->needed;
6838         uint32 *returned = &r_u->returned;
6839         WERROR wret;
6840         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6841         int snum;
6842         print_status_struct prt_status;
6843         print_queue_struct *queue=NULL;
6844
6845         /* that's an [in out] buffer */
6846
6847         if (!q_u->buffer && (offered!=0)) {
6848                 return WERR_INVALID_PARAM;
6849         }
6850
6851         if (offered > MAX_RPC_DATA_SIZE) {
6852                 return WERR_INVALID_PARAM;
6853         }
6854
6855         rpcbuf_move(q_u->buffer, &r_u->buffer);
6856         buffer = r_u->buffer;
6857
6858         DEBUG(4,("_spoolss_enumjobs\n"));
6859
6860         *needed=0;
6861         *returned=0;
6862
6863         /* lookup the printer snum and tdb entry */
6864
6865         if (!get_printer_snum(p, handle, &snum, NULL))
6866                 return WERR_BADFID;
6867
6868         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6869         if ( !W_ERROR_IS_OK(wret) )
6870                 return wret;
6871
6872         *returned = print_queue_status(snum, &queue, &prt_status);
6873         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6874
6875         if (*returned == 0) {
6876                 SAFE_FREE(queue);
6877                 free_a_printer(&ntprinter, 2);
6878                 return WERR_OK;
6879         }
6880
6881         switch (level) {
6882         case 1:
6883                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6884                 break;
6885         case 2:
6886                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6887                 break;
6888         default:
6889                 *returned=0;
6890                 wret = WERR_UNKNOWN_LEVEL;
6891                 break;
6892         }
6893
6894         SAFE_FREE(queue);
6895         free_a_printer( &ntprinter, 2 );
6896         return wret;
6897 }
6898
6899 /****************************************************************
6900  _spoolss_ScheduleJob
6901 ****************************************************************/
6902
6903 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6904                             struct spoolss_ScheduleJob *r)
6905 {
6906         return WERR_OK;
6907 }
6908
6909 /****************************************************************
6910  _spoolss_SetJob
6911 ****************************************************************/
6912
6913 WERROR _spoolss_SetJob(pipes_struct *p,
6914                        struct spoolss_SetJob *r)
6915 {
6916         POLICY_HND *handle = r->in.handle;
6917         uint32 jobid = r->in.job_id;
6918         uint32 command = r->in.command;
6919
6920         int snum;
6921         WERROR errcode = WERR_BADFUNC;
6922
6923         if (!get_printer_snum(p, handle, &snum, NULL)) {
6924                 return WERR_BADFID;
6925         }
6926
6927         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6928                 return WERR_INVALID_PRINTER_NAME;
6929         }
6930
6931         switch (command) {
6932         case SPOOLSS_JOB_CONTROL_CANCEL:
6933         case SPOOLSS_JOB_CONTROL_DELETE:
6934                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6935                         errcode = WERR_OK;
6936                 }
6937                 break;
6938         case SPOOLSS_JOB_CONTROL_PAUSE:
6939                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6940                         errcode = WERR_OK;
6941                 }
6942                 break;
6943         case SPOOLSS_JOB_CONTROL_RESTART:
6944         case SPOOLSS_JOB_CONTROL_RESUME:
6945                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6946                         errcode = WERR_OK;
6947                 }
6948                 break;
6949         default:
6950                 return WERR_UNKNOWN_LEVEL;
6951         }
6952
6953         return errcode;
6954 }
6955
6956 /****************************************************************************
6957  Enumerates all printer drivers at level 1.
6958 ****************************************************************************/
6959
6960 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6961 {
6962         int i;
6963         int ndrivers;
6964         uint32 version;
6965         fstring *list = NULL;
6966         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6967         DRIVER_INFO_1 *driver_info_1=NULL;
6968         WERROR result = WERR_OK;
6969
6970         *returned=0;
6971
6972         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6973                 list=NULL;
6974                 ndrivers=get_ntdrivers(&list, architecture, version);
6975                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6976
6977                 if(ndrivers == -1) {
6978                         SAFE_FREE(driver_info_1);
6979                         return WERR_NOMEM;
6980                 }
6981
6982                 if(ndrivers != 0) {
6983                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6984                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6985                                 SAFE_FREE(list);
6986                                 return WERR_NOMEM;
6987                         }
6988                 }
6989
6990                 for (i=0; i<ndrivers; i++) {
6991                         WERROR status;
6992                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6993                         ZERO_STRUCT(driver);
6994                         status = get_a_printer_driver(&driver, 3, list[i],
6995                                                       architecture, version);
6996                         if (!W_ERROR_IS_OK(status)) {
6997                                 SAFE_FREE(list);
6998                                 SAFE_FREE(driver_info_1);
6999                                 return status;
7000                         }
7001                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
7002                         free_a_printer_driver(driver, 3);
7003                 }
7004
7005                 *returned+=ndrivers;
7006                 SAFE_FREE(list);
7007         }
7008
7009         /* check the required size. */
7010         for (i=0; i<*returned; i++) {
7011                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7012                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
7013         }
7014
7015         if (*needed > offered) {
7016                 result = WERR_INSUFFICIENT_BUFFER;
7017                 goto out;
7018         }
7019
7020         if (!rpcbuf_alloc_size(buffer, *needed)) {
7021                 result = WERR_NOMEM;
7022                 goto out;
7023         }
7024
7025         /* fill the buffer with the driver structures */
7026         for (i=0; i<*returned; i++) {
7027                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7028                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7029         }
7030
7031 out:
7032         SAFE_FREE(driver_info_1);
7033
7034         if ( !W_ERROR_IS_OK(result) )
7035                 *returned = 0;
7036
7037         return result;
7038 }
7039
7040 /****************************************************************************
7041  Enumerates all printer drivers at level 2.
7042 ****************************************************************************/
7043
7044 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7045 {
7046         int i;
7047         int ndrivers;
7048         uint32 version;
7049         fstring *list = NULL;
7050         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7051         DRIVER_INFO_2 *driver_info_2=NULL;
7052         WERROR result = WERR_OK;
7053
7054         *returned=0;
7055
7056         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7057                 list=NULL;
7058                 ndrivers=get_ntdrivers(&list, architecture, version);
7059                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7060
7061                 if(ndrivers == -1) {
7062                         SAFE_FREE(driver_info_2);
7063                         return WERR_NOMEM;
7064                 }
7065
7066                 if(ndrivers != 0) {
7067                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7068                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7069                                 SAFE_FREE(list);
7070                                 return WERR_NOMEM;
7071                         }
7072                 }
7073
7074                 for (i=0; i<ndrivers; i++) {
7075                         WERROR status;
7076
7077                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7078                         ZERO_STRUCT(driver);
7079                         status = get_a_printer_driver(&driver, 3, list[i],
7080                                                       architecture, version);
7081                         if (!W_ERROR_IS_OK(status)) {
7082                                 SAFE_FREE(list);
7083                                 SAFE_FREE(driver_info_2);
7084                                 return status;
7085                         }
7086                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7087                         free_a_printer_driver(driver, 3);
7088                 }
7089
7090                 *returned+=ndrivers;
7091                 SAFE_FREE(list);
7092         }
7093
7094         /* check the required size. */
7095         for (i=0; i<*returned; i++) {
7096                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7097                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7098         }
7099
7100         if (*needed > offered) {
7101                 result = WERR_INSUFFICIENT_BUFFER;
7102                 goto out;
7103         }
7104
7105         if (!rpcbuf_alloc_size(buffer, *needed)) {
7106                 result = WERR_NOMEM;
7107                 goto out;
7108         }
7109
7110         /* fill the buffer with the form structures */
7111         for (i=0; i<*returned; i++) {
7112                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7113                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7114         }
7115
7116 out:
7117         SAFE_FREE(driver_info_2);
7118
7119         if ( !W_ERROR_IS_OK(result) )
7120                 *returned = 0;
7121
7122         return result;
7123 }
7124
7125 /****************************************************************************
7126  Enumerates all printer drivers at level 3.
7127 ****************************************************************************/
7128
7129 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7130 {
7131         int i;
7132         int ndrivers;
7133         uint32 version;
7134         fstring *list = NULL;
7135         DRIVER_INFO_3 *driver_info_3=NULL;
7136         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7137         WERROR result = WERR_OK;
7138
7139         *returned=0;
7140
7141         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7142                 list=NULL;
7143                 ndrivers=get_ntdrivers(&list, architecture, version);
7144                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7145
7146                 if(ndrivers == -1) {
7147                         SAFE_FREE(driver_info_3);
7148                         return WERR_NOMEM;
7149                 }
7150
7151                 if(ndrivers != 0) {
7152                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7153                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7154                                 SAFE_FREE(list);
7155                                 return WERR_NOMEM;
7156                         }
7157                 }
7158
7159                 for (i=0; i<ndrivers; i++) {
7160                         WERROR status;
7161
7162                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7163                         ZERO_STRUCT(driver);
7164                         status = get_a_printer_driver(&driver, 3, list[i],
7165                                                       architecture, version);
7166                         if (!W_ERROR_IS_OK(status)) {
7167                                 SAFE_FREE(list);
7168                                 SAFE_FREE(driver_info_3);
7169                                 return status;
7170                         }
7171                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7172                         free_a_printer_driver(driver, 3);
7173                 }
7174
7175                 *returned+=ndrivers;
7176                 SAFE_FREE(list);
7177         }
7178
7179         /* check the required size. */
7180         for (i=0; i<*returned; i++) {
7181                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7182                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7183         }
7184
7185         if (*needed > offered) {
7186                 result = WERR_INSUFFICIENT_BUFFER;
7187                 goto out;
7188         }
7189
7190         if (!rpcbuf_alloc_size(buffer, *needed)) {
7191                 result = WERR_NOMEM;
7192                 goto out;
7193         }
7194
7195         /* fill the buffer with the driver structures */
7196         for (i=0; i<*returned; i++) {
7197                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7198                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7199         }
7200
7201 out:
7202         for (i=0; i<*returned; i++) {
7203                 SAFE_FREE(driver_info_3[i].dependentfiles);
7204         }
7205
7206         SAFE_FREE(driver_info_3);
7207
7208         if ( !W_ERROR_IS_OK(result) )
7209                 *returned = 0;
7210
7211         return result;
7212 }
7213
7214 /****************************************************************************
7215  Enumerates all printer drivers.
7216 ****************************************************************************/
7217
7218 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7219 {
7220         uint32 level = q_u->level;
7221         RPC_BUFFER *buffer = NULL;
7222         uint32 offered = q_u->offered;
7223         uint32 *needed = &r_u->needed;
7224         uint32 *returned = &r_u->returned;
7225         const char *cservername;
7226         fstring servername;
7227         fstring architecture;
7228
7229         /* that's an [in out] buffer */
7230
7231         if (!q_u->buffer && (offered!=0)) {
7232                 return WERR_INVALID_PARAM;
7233         }
7234
7235         if (offered > MAX_RPC_DATA_SIZE) {
7236                 return WERR_INVALID_PARAM;
7237         }
7238
7239         rpcbuf_move(q_u->buffer, &r_u->buffer);
7240         buffer = r_u->buffer;
7241
7242         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7243
7244         *needed   = 0;
7245         *returned = 0;
7246
7247         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7248         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7249
7250         cservername = canon_servername(servername);
7251
7252         if (!is_myname_or_ipaddr(cservername))
7253                 return WERR_UNKNOWN_PRINTER_DRIVER;
7254
7255         switch (level) {
7256         case 1:
7257                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7258         case 2:
7259                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7260         case 3:
7261                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7262         default:
7263                 return WERR_UNKNOWN_LEVEL;
7264         }
7265 }
7266
7267 /****************************************************************************
7268 ****************************************************************************/
7269
7270 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7271 {
7272         form->flag=list->flag;
7273         init_unistr(&form->name, list->name);
7274         form->width=list->width;
7275         form->length=list->length;
7276         form->left=list->left;
7277         form->top=list->top;
7278         form->right=list->right;
7279         form->bottom=list->bottom;
7280 }
7281
7282 /****************************************************************************
7283 ****************************************************************************/
7284
7285 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7286                                struct spoolss_FormInfo1 *form,
7287                                nt_forms_struct *list)
7288 {
7289         form->form_name         = talloc_strdup(mem_ctx, list->name);
7290         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7291
7292         form->flags             = list->flag;
7293         form->size.width        = list->width;
7294         form->size.height       = list->length;
7295         form->area.left         = list->left;
7296         form->area.top          = list->top;
7297         form->area.right        = list->right;
7298         form->area.bottom       = list->bottom;
7299
7300         return WERR_OK;
7301 }
7302
7303 /****************************************************************************
7304 ****************************************************************************/
7305
7306 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7307 {
7308         uint32 level = q_u->level;
7309         RPC_BUFFER *buffer = NULL;
7310         uint32 offered = q_u->offered;
7311         uint32 *needed = &r_u->needed;
7312         uint32 *numofforms = &r_u->numofforms;
7313         uint32 numbuiltinforms;
7314
7315         nt_forms_struct *list=NULL;
7316         nt_forms_struct *builtinlist=NULL;
7317         FORM_1 *forms_1;
7318         int buffer_size=0;
7319         int i;
7320
7321         /* that's an [in out] buffer */
7322
7323         if (!q_u->buffer && (offered!=0) ) {
7324                 return WERR_INVALID_PARAM;
7325         }
7326
7327         if (offered > MAX_RPC_DATA_SIZE) {
7328                 return WERR_INVALID_PARAM;
7329         }
7330
7331         rpcbuf_move(q_u->buffer, &r_u->buffer);
7332         buffer = r_u->buffer;
7333
7334         DEBUG(4,("_spoolss_enumforms\n"));
7335         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7336         DEBUGADD(5,("Info level [%d]\n",          level));
7337
7338         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7339         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7340         *numofforms = get_ntforms(&list);
7341         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7342         *numofforms += numbuiltinforms;
7343
7344         if (*numofforms == 0) {
7345                 SAFE_FREE(builtinlist);
7346                 SAFE_FREE(list);
7347                 return WERR_NO_MORE_ITEMS;
7348         }
7349
7350         switch (level) {
7351         case 1:
7352                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7353                         SAFE_FREE(builtinlist);
7354                         SAFE_FREE(list);
7355                         *numofforms=0;
7356                         return WERR_NOMEM;
7357                 }
7358
7359                 /* construct the list of form structures */
7360                 for (i=0; i<numbuiltinforms; i++) {
7361                         DEBUGADD(6,("Filling form number [%d]\n",i));
7362                         fill_form_1(&forms_1[i], &builtinlist[i]);
7363                 }
7364
7365                 SAFE_FREE(builtinlist);
7366
7367                 for (; i<*numofforms; i++) {
7368                         DEBUGADD(6,("Filling form number [%d]\n",i));
7369                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7370                 }
7371
7372                 SAFE_FREE(list);
7373
7374                 /* check the required size. */
7375                 for (i=0; i<numbuiltinforms; i++) {
7376                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7377                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7378                 }
7379                 for (; i<*numofforms; i++) {
7380                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7381                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7382                 }
7383
7384                 *needed=buffer_size;
7385
7386                 if (*needed > offered) {
7387                         SAFE_FREE(forms_1);
7388                         *numofforms=0;
7389                         return WERR_INSUFFICIENT_BUFFER;
7390                 }
7391
7392                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7393                         SAFE_FREE(forms_1);
7394                         *numofforms=0;
7395                         return WERR_NOMEM;
7396                 }
7397
7398                 /* fill the buffer with the form structures */
7399                 for (i=0; i<numbuiltinforms; i++) {
7400                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7401                         smb_io_form_1("", buffer, &forms_1[i], 0);
7402                 }
7403                 for (; i<*numofforms; i++) {
7404                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7405                         smb_io_form_1("", buffer, &forms_1[i], 0);
7406                 }
7407
7408                 SAFE_FREE(forms_1);
7409
7410                 return WERR_OK;
7411
7412         default:
7413                 SAFE_FREE(list);
7414                 SAFE_FREE(builtinlist);
7415                 return WERR_UNKNOWN_LEVEL;
7416         }
7417 }
7418
7419 /****************************************************************
7420  _spoolss_GetForm
7421 ****************************************************************/
7422
7423 WERROR _spoolss_GetForm(pipes_struct *p,
7424                         struct spoolss_GetForm *r)
7425 {
7426         uint32 level = r->in.level;
7427         uint32 offered = r->in.offered;
7428         uint32 *needed = r->out.needed;
7429
7430         nt_forms_struct *list=NULL;
7431         nt_forms_struct builtin_form;
7432         bool foundBuiltin;
7433         union spoolss_FormInfo info;
7434         struct spoolss_FormInfo1 form_1;
7435         int numofforms=0, i=0;
7436
7437         /* that's an [in out] buffer */
7438
7439         if (!r->in.buffer && (offered!=0)) {
7440                 return WERR_INVALID_PARAM;
7441         }
7442
7443         DEBUG(4,("_spoolss_GetForm\n"));
7444         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7445         DEBUGADD(5,("Info level [%d]\n",          level));
7446
7447         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7448         if (!foundBuiltin) {
7449                 numofforms = get_ntforms(&list);
7450                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7451
7452                 if (numofforms == 0)
7453                         return WERR_BADFID;
7454         }
7455
7456         ZERO_STRUCT(form_1);
7457
7458         switch (level) {
7459         case 1:
7460                 if (foundBuiltin) {
7461                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7462                 } else {
7463
7464                         /* Check if the requested name is in the list of form structures */
7465                         for (i=0; i<numofforms; i++) {
7466
7467                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7468                                         list[i].name, r->in.form_name));
7469
7470                                 if (strequal(r->in.form_name, list[i].name)) {
7471                                         DEBUGADD(6,("Found form %s number [%d]\n",
7472                                                 r->in.form_name, i));
7473                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7474                                         break;
7475                                 }
7476                         }
7477
7478                         SAFE_FREE(list);
7479                         if (i == numofforms) {
7480                                 return WERR_BADFID;
7481                         }
7482                 }
7483                 /* check the required size. */
7484
7485                 info.info1 = form_1;
7486
7487                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7488
7489                 if (*needed > offered) {
7490                         r->out.info = NULL;
7491                         return WERR_INSUFFICIENT_BUFFER;
7492                 }
7493
7494                 r->out.info->info1 = form_1;
7495
7496                 /* fill the buffer with the form structures */
7497                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7498                         r->in.form_name, i));
7499
7500                 return WERR_OK;
7501
7502         default:
7503                 SAFE_FREE(list);
7504                 return WERR_UNKNOWN_LEVEL;
7505         }
7506 }
7507
7508 /****************************************************************************
7509 ****************************************************************************/
7510
7511 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7512 {
7513         init_unistr(&port->port_name, name);
7514 }
7515
7516 /****************************************************************************
7517  TODO: This probably needs distinguish between TCP/IP and Local ports
7518  somehow.
7519 ****************************************************************************/
7520
7521 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7522 {
7523         init_unistr(&port->port_name, name);
7524         init_unistr(&port->monitor_name, "Local Monitor");
7525         init_unistr(&port->description, SPL_LOCAL_PORT );
7526         port->port_type=PORT_TYPE_WRITE;
7527         port->reserved=0x0;
7528 }
7529
7530
7531 /****************************************************************************
7532  wrapper around the enumer ports command
7533 ****************************************************************************/
7534
7535 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7536 {
7537         char *cmd = lp_enumports_cmd();
7538         char **qlines = NULL;
7539         char *command = NULL;
7540         int numlines;
7541         int ret;
7542         int fd;
7543
7544         *count = 0;
7545         *lines = NULL;
7546
7547         /* if no hook then just fill in the default port */
7548
7549         if ( !*cmd ) {
7550                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7551                         return WERR_NOMEM;
7552                 }
7553                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7554                         TALLOC_FREE(qlines);
7555                         return WERR_NOMEM;
7556                 }
7557                 qlines[1] = NULL;
7558                 numlines = 1;
7559         }
7560         else {
7561                 /* we have a valid enumport command */
7562
7563                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7564                 if (!command) {
7565                         return WERR_NOMEM;
7566                 }
7567
7568                 DEBUG(10,("Running [%s]\n", command));
7569                 ret = smbrun(command, &fd);
7570                 DEBUG(10,("Returned [%d]\n", ret));
7571                 TALLOC_FREE(command);
7572                 if (ret != 0) {
7573                         if (fd != -1) {
7574                                 close(fd);
7575                         }
7576                         return WERR_ACCESS_DENIED;
7577                 }
7578
7579                 numlines = 0;
7580                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7581                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7582                 close(fd);
7583         }
7584
7585         *count = numlines;
7586         *lines = qlines;
7587
7588         return WERR_OK;
7589 }
7590
7591 /****************************************************************************
7592  enumports level 1.
7593 ****************************************************************************/
7594
7595 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7596 {
7597         PORT_INFO_1 *ports=NULL;
7598         int i=0;
7599         WERROR result = WERR_OK;
7600         char **qlines = NULL;
7601         int numlines = 0;
7602
7603         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7604         if (!W_ERROR_IS_OK(result)) {
7605                 TALLOC_FREE(qlines);
7606                 return result;
7607         }
7608
7609         if(numlines) {
7610                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7611                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7612                                   win_errstr(WERR_NOMEM)));
7613                         TALLOC_FREE(qlines);
7614                         return WERR_NOMEM;
7615                 }
7616
7617                 for (i=0; i<numlines; i++) {
7618                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7619                         fill_port_1(&ports[i], qlines[i]);
7620                 }
7621         }
7622         TALLOC_FREE(qlines);
7623
7624         *returned = numlines;
7625
7626         /* check the required size. */
7627         for (i=0; i<*returned; i++) {
7628                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7629                 *needed += spoolss_size_port_info_1(&ports[i]);
7630         }
7631
7632         if (*needed > offered) {
7633                 result = WERR_INSUFFICIENT_BUFFER;
7634                 goto out;
7635         }
7636
7637         if (!rpcbuf_alloc_size(buffer, *needed)) {
7638                 result = WERR_NOMEM;
7639                 goto out;
7640         }
7641
7642         /* fill the buffer with the ports structures */
7643         for (i=0; i<*returned; i++) {
7644                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7645                 smb_io_port_1("", buffer, &ports[i], 0);
7646         }
7647
7648 out:
7649         SAFE_FREE(ports);
7650
7651         if ( !W_ERROR_IS_OK(result) )
7652                 *returned = 0;
7653
7654         return result;
7655 }
7656
7657 /****************************************************************************
7658  enumports level 2.
7659 ****************************************************************************/
7660
7661 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7662 {
7663         PORT_INFO_2 *ports=NULL;
7664         int i=0;
7665         WERROR result = WERR_OK;
7666         char **qlines = NULL;
7667         int numlines = 0;
7668
7669         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7670         if ( !W_ERROR_IS_OK(result)) {
7671                 TALLOC_FREE(qlines);
7672                 return result;
7673         }
7674
7675         if(numlines) {
7676                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7677                         TALLOC_FREE(qlines);
7678                         return WERR_NOMEM;
7679                 }
7680
7681                 for (i=0; i<numlines; i++) {
7682                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7683                         fill_port_2(&(ports[i]), qlines[i]);
7684                 }
7685         }
7686
7687         TALLOC_FREE(qlines);
7688
7689         *returned = numlines;
7690
7691         /* check the required size. */
7692         for (i=0; i<*returned; i++) {
7693                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7694                 *needed += spoolss_size_port_info_2(&ports[i]);
7695         }
7696
7697         if (*needed > offered) {
7698                 result = WERR_INSUFFICIENT_BUFFER;
7699                 goto out;
7700         }
7701
7702         if (!rpcbuf_alloc_size(buffer, *needed)) {
7703                 result = WERR_NOMEM;
7704                 goto out;
7705         }
7706
7707         /* fill the buffer with the ports structures */
7708         for (i=0; i<*returned; i++) {
7709                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7710                 smb_io_port_2("", buffer, &ports[i], 0);
7711         }
7712
7713 out:
7714         SAFE_FREE(ports);
7715
7716         if ( !W_ERROR_IS_OK(result) )
7717                 *returned = 0;
7718
7719         return result;
7720 }
7721
7722 /****************************************************************************
7723  enumports.
7724 ****************************************************************************/
7725
7726 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7727 {
7728         uint32 level = q_u->level;
7729         RPC_BUFFER *buffer = NULL;
7730         uint32 offered = q_u->offered;
7731         uint32 *needed = &r_u->needed;
7732         uint32 *returned = &r_u->returned;
7733
7734         /* that's an [in out] buffer */
7735
7736         if (!q_u->buffer && (offered!=0)) {
7737                 return WERR_INVALID_PARAM;
7738         }
7739
7740         if (offered > MAX_RPC_DATA_SIZE) {
7741                 return WERR_INVALID_PARAM;
7742         }
7743
7744         rpcbuf_move(q_u->buffer, &r_u->buffer);
7745         buffer = r_u->buffer;
7746
7747         DEBUG(4,("_spoolss_enumports\n"));
7748
7749         *returned=0;
7750         *needed=0;
7751
7752         switch (level) {
7753         case 1:
7754                 return enumports_level_1(buffer, offered, needed, returned);
7755         case 2:
7756                 return enumports_level_2(buffer, offered, needed, returned);
7757         default:
7758                 return WERR_UNKNOWN_LEVEL;
7759         }
7760 }
7761
7762 /****************************************************************************
7763 ****************************************************************************/
7764
7765 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7766                                            const char *server,
7767                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7768                                            struct spoolss_DeviceMode *devmode,
7769                                            struct security_descriptor *sec_desc,
7770                                            struct spoolss_UserLevelCtr *user_ctr,
7771                                            POLICY_HND *handle)
7772 {
7773         NT_PRINTER_INFO_LEVEL *printer = NULL;
7774         fstring name;
7775         int     snum;
7776         WERROR err = WERR_OK;
7777
7778         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7779                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7780                 return WERR_NOMEM;
7781         }
7782
7783         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7784         if (!convert_printer_info_new(info_ctr, printer)) {
7785                 free_a_printer(&printer, 2);
7786                 return WERR_NOMEM;
7787         }
7788
7789         /* check to see if the printer already exists */
7790
7791         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7792                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7793                         printer->info_2->sharename));
7794                 free_a_printer(&printer, 2);
7795                 return WERR_PRINTER_ALREADY_EXISTS;
7796         }
7797
7798         /* FIXME!!!  smbd should check to see if the driver is installed before
7799            trying to add a printer like this  --jerry */
7800
7801         if (*lp_addprinter_cmd() ) {
7802                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7803                                        printer) ) {
7804                         free_a_printer(&printer,2);
7805                         return WERR_ACCESS_DENIED;
7806                 }
7807         } else {
7808                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7809                         "smb.conf parameter \"addprinter command\" is defined. This"
7810                         "parameter must exist for this call to succeed\n",
7811                         printer->info_2->sharename ));
7812         }
7813
7814         /* use our primary netbios name since get_a_printer() will convert
7815            it to what the client expects on a case by case basis */
7816
7817         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7818              printer->info_2->sharename);
7819
7820
7821         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7822                 free_a_printer(&printer,2);
7823                 return WERR_ACCESS_DENIED;
7824         }
7825
7826         /* you must be a printer admin to add a new printer */
7827         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7828                 free_a_printer(&printer,2);
7829                 return WERR_ACCESS_DENIED;
7830         }
7831
7832         /*
7833          * Do sanity check on the requested changes for Samba.
7834          */
7835
7836         if (!check_printer_ok(printer->info_2, snum)) {
7837                 free_a_printer(&printer,2);
7838                 return WERR_INVALID_PARAM;
7839         }
7840
7841         /*
7842          * When a printer is created, the drivername bound to the printer is used
7843          * to lookup previously saved driver initialization info, which is then
7844          * bound to the new printer, simulating what happens in the Windows arch.
7845          */
7846
7847         if (!devmode)
7848         {
7849                 set_driver_init(printer, 2);
7850         }
7851         else
7852         {
7853                 /* A valid devmode was included, convert and link it
7854                 */
7855                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7856
7857                 if (!convert_devicemode_new(printer->info_2->printername,
7858                                             devmode,
7859                                             &printer->info_2->devmode))
7860                         return  WERR_NOMEM;
7861         }
7862
7863         /* write the ASCII on disk */
7864         err = mod_a_printer(printer, 2);
7865         if (!W_ERROR_IS_OK(err)) {
7866                 free_a_printer(&printer,2);
7867                 return err;
7868         }
7869
7870         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7871                 /* Handle open failed - remove addition. */
7872                 del_a_printer(printer->info_2->sharename);
7873                 free_a_printer(&printer,2);
7874                 ZERO_STRUCTP(handle);
7875                 return WERR_ACCESS_DENIED;
7876         }
7877
7878         update_c_setprinter(False);
7879         free_a_printer(&printer,2);
7880
7881         return WERR_OK;
7882 }
7883
7884 /****************************************************************
7885  _spoolss_AddPrinterEx
7886 ****************************************************************/
7887
7888 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7889                              struct spoolss_AddPrinterEx *r)
7890 {
7891         switch (r->in.info_ctr->level) {
7892         case 1:
7893                 /* we don't handle yet */
7894                 /* but I know what to do ... */
7895                 return WERR_UNKNOWN_LEVEL;
7896         case 2:
7897                 return spoolss_addprinterex_level_2(p, r->in.server,
7898                                                     r->in.info_ctr,
7899                                                     r->in.devmode_ctr->devmode,
7900                                                     r->in.secdesc_ctr->sd,
7901                                                     r->in.userlevel_ctr,
7902                                                     r->out.handle);
7903         default:
7904                 return WERR_UNKNOWN_LEVEL;
7905         }
7906 }
7907
7908 /****************************************************************************
7909 ****************************************************************************/
7910
7911 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7912 {
7913         uint32 level = q_u->level;
7914         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7915         WERROR err = WERR_OK;
7916         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7917         fstring driver_name;
7918         uint32 version;
7919
7920         ZERO_STRUCT(driver);
7921
7922         if (!convert_printer_driver_info(info, &driver, level)) {
7923                 err = WERR_NOMEM;
7924                 goto done;
7925         }
7926
7927         DEBUG(5,("Cleaning driver's information\n"));
7928         err = clean_up_driver_struct(p, driver, level);
7929         if (!W_ERROR_IS_OK(err))
7930                 goto done;
7931
7932         DEBUG(5,("Moving driver to final destination\n"));
7933         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7934                                                               &err)) ) {
7935                 goto done;
7936         }
7937
7938         if (add_a_printer_driver(driver, level)!=0) {
7939                 err = WERR_ACCESS_DENIED;
7940                 goto done;
7941         }
7942
7943         switch(level) {
7944         case 3:
7945                 fstrcpy(driver_name,
7946                         driver.info_3->name ? driver.info_3->name : "");
7947                 break;
7948         case 6:
7949                 fstrcpy(driver_name,
7950                         driver.info_6->name ?  driver.info_6->name : "");
7951                 break;
7952         }
7953
7954         /*
7955          * I think this is where he DrvUpgradePrinter() hook would be
7956          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7957          * server.  Right now, we just need to send ourselves a message
7958          * to update each printer bound to this driver.   --jerry
7959          */
7960
7961         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7962                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7963                         driver_name));
7964         }
7965
7966         /*
7967          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7968          * decide if the driver init data should be deleted. The rules are:
7969          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7970          *  2) delete init data only if there is no 2k/Xp driver
7971          *  3) always delete init data
7972          * The generalized rule is always use init data from the highest order driver.
7973          * It is necessary to follow the driver install by an initialization step to
7974          * finish off this process.
7975         */
7976         if (level == 3)
7977                 version = driver.info_3->cversion;
7978         else if (level == 6)
7979                 version = driver.info_6->version;
7980         else
7981                 version = -1;
7982         switch (version) {
7983                 /*
7984                  * 9x printer driver - never delete init data
7985                 */
7986                 case 0:
7987                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7988                                         driver_name));
7989                         break;
7990
7991                 /*
7992                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7993                  * there is no 2k/Xp driver init data for this driver name.
7994                 */
7995                 case 2:
7996                 {
7997                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7998
7999                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
8000                                 /*
8001                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
8002                                 */
8003                                 if (!del_driver_init(driver_name))
8004                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
8005                         } else {
8006                                 /*
8007                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
8008                                 */
8009                                 free_a_printer_driver(driver1,3);
8010                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
8011                                                 driver_name));
8012                         }
8013                 }
8014                 break;
8015
8016                 /*
8017                  * 2k or Xp printer driver - always delete init data
8018                 */
8019                 case 3:
8020                         if (!del_driver_init(driver_name))
8021                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
8022                         break;
8023
8024                 default:
8025                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
8026                         break;
8027         }
8028
8029
8030 done:
8031         free_a_printer_driver(driver, level);
8032         return err;
8033 }
8034
8035 /********************************************************************
8036  * spoolss_addprinterdriverex
8037  ********************************************************************/
8038
8039 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
8040 {
8041         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
8042         SPOOL_R_ADDPRINTERDRIVER r_u_local;
8043
8044         /*
8045          * we only support the semantics of AddPrinterDriver()
8046          * i.e. only copy files that are newer than existing ones
8047          */
8048
8049         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
8050                 return WERR_ACCESS_DENIED;
8051
8052         ZERO_STRUCT(q_u_local);
8053         ZERO_STRUCT(r_u_local);
8054
8055         /* just pass the information off to _spoolss_addprinterdriver() */
8056         q_u_local.server_name_ptr = q_u->server_name_ptr;
8057         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
8058         q_u_local.level = q_u->level;
8059         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
8060
8061         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
8062 }
8063
8064 /****************************************************************************
8065 ****************************************************************************/
8066
8067 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8068                                           const char *servername,
8069                                           const char *long_archi,
8070                                           struct spoolss_DriverDirectoryInfo1 *info1,
8071                                           uint32_t offered,
8072                                           uint32_t *needed)
8073 {
8074         char *path = NULL;
8075         const char *pservername = NULL;
8076         const char *short_archi;
8077
8078         pservername = canon_servername(servername);
8079
8080         if ( !is_myname_or_ipaddr(pservername))
8081                 return WERR_INVALID_PARAM;
8082
8083         if (!(short_archi = get_short_archi(long_archi)))
8084                 return WERR_INVALID_ENVIRONMENT;
8085
8086         path = talloc_asprintf(mem_ctx,
8087                         "\\\\%s\\print$\\%s", pservername, short_archi);
8088         if (!path) {
8089                 return WERR_NOMEM;
8090         }
8091
8092         DEBUG(4,("printer driver directory: [%s]\n", path));
8093
8094         info1->directory_name = path;
8095
8096         *needed += ndr_size_spoolss_DriverDirectoryInfo1(info1, NULL, 0);
8097
8098         if (*needed > offered) {
8099                 talloc_free(path);
8100                 ZERO_STRUCTP(info1);
8101                 return WERR_INSUFFICIENT_BUFFER;
8102         }
8103
8104         return WERR_OK;
8105 }
8106
8107 /****************************************************************
8108  _spoolss_GetPrinterDriverDirectory
8109 ****************************************************************/
8110
8111 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8112                                           struct spoolss_GetPrinterDriverDirectory *r)
8113 {
8114         WERROR werror;
8115
8116         /* that's an [in out] buffer */
8117
8118         if (!r->in.buffer && (r->in.offered != 0)) {
8119                 return WERR_INVALID_PARAM;
8120         }
8121
8122         if (r->in.offered > MAX_RPC_DATA_SIZE) {
8123                 return WERR_INVALID_PARAM;
8124         }
8125
8126         DEBUG(4,("_spoolss_GetPrinterDriverDirectory\n"));
8127
8128         *r->out.needed = 0;
8129
8130         switch (r->in.level) {
8131         case 1:
8132                 werror = getprinterdriverdir_level_1(p->mem_ctx,
8133                                                      r->in.server,
8134                                                      r->in.environment,
8135                                                      &r->out.info->info1,
8136                                                      r->in.offered,
8137                                                      r->out.needed);
8138                 if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
8139                         TALLOC_FREE(r->out.info);
8140                 }
8141                 break;
8142         default:
8143                 return WERR_UNKNOWN_LEVEL;
8144         }
8145
8146         return werror;
8147 }
8148
8149 /****************************************************************************
8150 ****************************************************************************/
8151
8152 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8153 {
8154         POLICY_HND *handle = &q_u->handle;
8155         uint32 idx               = q_u->index;
8156         uint32 in_value_len      = q_u->valuesize;
8157         uint32 in_data_len       = q_u->datasize;
8158         uint32 *out_max_value_len = &r_u->valuesize;
8159         uint16 **out_value       = &r_u->value;
8160         uint32 *out_value_len    = &r_u->realvaluesize;
8161         uint32 *out_type         = &r_u->type;
8162         uint32 *out_max_data_len = &r_u->datasize;
8163         uint8  **data_out        = &r_u->data;
8164         uint32 *out_data_len     = &r_u->realdatasize;
8165
8166         NT_PRINTER_INFO_LEVEL *printer = NULL;
8167
8168         uint32          biggest_valuesize;
8169         uint32          biggest_datasize;
8170         uint32          data_len;
8171         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8172         int             snum;
8173         WERROR          result;
8174         REGISTRY_VALUE  *val = NULL;
8175         NT_PRINTER_DATA *p_data;
8176         int             i, key_index, num_values;
8177         int             name_length;
8178
8179         *out_type = 0;
8180
8181         *out_max_data_len = 0;
8182         *data_out         = NULL;
8183         *out_data_len     = 0;
8184
8185         DEBUG(5,("spoolss_enumprinterdata\n"));
8186
8187         if (!Printer) {
8188                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8189                 return WERR_BADFID;
8190         }
8191
8192         if (!get_printer_snum(p,handle, &snum, NULL))
8193                 return WERR_BADFID;
8194
8195         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8196         if (!W_ERROR_IS_OK(result))
8197                 return result;
8198
8199         p_data = printer->info_2->data;
8200         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8201
8202         result = WERR_OK;
8203
8204         /*
8205          * The NT machine wants to know the biggest size of value and data
8206          *
8207          * cf: MSDN EnumPrinterData remark section
8208          */
8209
8210         if ( !in_value_len && !in_data_len && (key_index != -1) )
8211         {
8212                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8213
8214                 biggest_valuesize = 0;
8215                 biggest_datasize  = 0;
8216
8217                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8218
8219                 for ( i=0; i<num_values; i++ )
8220                 {
8221                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8222
8223                         name_length = strlen(val->valuename);
8224                         if ( strlen(val->valuename) > biggest_valuesize )
8225                                 biggest_valuesize = name_length;
8226
8227                         if ( val->size > biggest_datasize )
8228                                 biggest_datasize = val->size;
8229
8230                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8231                                 biggest_datasize));
8232                 }
8233
8234                 /* the value is an UNICODE string but real_value_size is the length
8235                    in bytes including the trailing 0 */
8236
8237                 *out_value_len = 2 * (1+biggest_valuesize);
8238                 *out_data_len  = biggest_datasize;
8239
8240                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8241
8242                 goto done;
8243         }
8244
8245         /*
8246          * the value len is wrong in NT sp3
8247          * that's the number of bytes not the number of unicode chars
8248          */
8249
8250         if ( key_index != -1 )
8251                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8252
8253         if ( !val )
8254         {
8255
8256                 /* out_value should default to "" or else NT4 has
8257                    problems unmarshalling the response */
8258
8259                 *out_max_value_len=(in_value_len/sizeof(uint16));
8260
8261                 if (in_value_len) {
8262                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8263                         {
8264                                 result = WERR_NOMEM;
8265                                 goto done;
8266                         }
8267                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8268                 } else {
8269                         *out_value=NULL;
8270                         *out_value_len = 0;
8271                 }
8272
8273                 /* the data is counted in bytes */
8274
8275                 *out_max_data_len = in_data_len;
8276                 *out_data_len     = in_data_len;
8277
8278                 /* only allocate when given a non-zero data_len */
8279
8280                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8281                 {
8282                         result = WERR_NOMEM;
8283                         goto done;
8284                 }
8285
8286                 result = WERR_NO_MORE_ITEMS;
8287         }
8288         else
8289         {
8290                 /*
8291                  * the value is:
8292                  * - counted in bytes in the request
8293                  * - counted in UNICODE chars in the max reply
8294                  * - counted in bytes in the real size
8295                  *
8296                  * take a pause *before* coding not *during* coding
8297                  */
8298
8299                 /* name */
8300                 *out_max_value_len=(in_value_len/sizeof(uint16));
8301                 if (in_value_len) {
8302                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8303                         {
8304                                 result = WERR_NOMEM;
8305                                 goto done;
8306                         }
8307
8308                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8309                 } else {
8310                         *out_value = NULL;
8311                         *out_value_len = 0;
8312                 }
8313
8314                 /* type */
8315
8316                 *out_type = regval_type( val );
8317
8318                 /* data - counted in bytes */
8319
8320                 *out_max_data_len = in_data_len;
8321                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8322                 {
8323                         result = WERR_NOMEM;
8324                         goto done;
8325                 }
8326                 data_len = regval_size(val);
8327                 if ( *data_out && data_len )
8328                         memcpy( *data_out, regval_data_p(val), data_len );
8329                 *out_data_len = data_len;
8330         }
8331
8332 done:
8333         free_a_printer(&printer, 2);
8334         return result;
8335 }
8336
8337 /****************************************************************************
8338 ****************************************************************************/
8339
8340 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8341 {
8342         POLICY_HND              *handle = &q_u->handle;
8343         UNISTR2                 *value = &q_u->value;
8344         uint32                  type = q_u->type;
8345         uint8                   *data = q_u->data;
8346         uint32                  real_len = q_u->real_len;
8347
8348         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8349         int                     snum=0;
8350         WERROR                  status = WERR_OK;
8351         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8352         fstring                 valuename;
8353
8354         DEBUG(5,("spoolss_setprinterdata\n"));
8355
8356         if (!Printer) {
8357                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8358                 return WERR_BADFID;
8359         }
8360
8361         if ( Printer->printer_type == SPLHND_SERVER ) {
8362                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8363                 return WERR_INVALID_PARAM;
8364         }
8365
8366         if (!get_printer_snum(p,handle, &snum, NULL))
8367                 return WERR_BADFID;
8368
8369         /*
8370          * Access check : NT returns "access denied" if you make a
8371          * SetPrinterData call without the necessary privildge.
8372          * we were originally returning OK if nothing changed
8373          * which made Win2k issue **a lot** of SetPrinterData
8374          * when connecting to a printer  --jerry
8375          */
8376
8377         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8378         {
8379                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8380                 status = WERR_ACCESS_DENIED;
8381                 goto done;
8382         }
8383
8384         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8385         if (!W_ERROR_IS_OK(status))
8386                 return status;
8387
8388         unistr2_to_ascii(valuename, value, sizeof(valuename));
8389
8390         /*
8391          * When client side code sets a magic printer data key, detect it and save
8392          * the current printer data and the magic key's data (its the DEVMODE) for
8393          * future printer/driver initializations.
8394          */
8395         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8396         {
8397                 /* Set devmode and printer initialization info */
8398                 status = save_driver_init( printer, 2, data, real_len );
8399
8400                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8401         }
8402         else
8403         {
8404         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8405                                         type, data, real_len );
8406                 if ( W_ERROR_IS_OK(status) )
8407                         status = mod_a_printer(printer, 2);
8408         }
8409
8410 done:
8411         free_a_printer(&printer, 2);
8412
8413         return status;
8414 }
8415
8416 /****************************************************************
8417  _spoolss_ResetPrinter
8418 ****************************************************************/
8419
8420 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8421                              struct spoolss_ResetPrinter *r)
8422 {
8423         POLICY_HND      *handle = r->in.handle;
8424         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8425         int             snum;
8426
8427         DEBUG(5,("_spoolss_ResetPrinter\n"));
8428
8429         /*
8430          * All we do is to check to see if the handle and queue is valid.
8431          * This call really doesn't mean anything to us because we only
8432          * support RAW printing.   --jerry
8433          */
8434
8435         if (!Printer) {
8436                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8437                         OUR_HANDLE(handle)));
8438                 return WERR_BADFID;
8439         }
8440
8441         if (!get_printer_snum(p,handle, &snum, NULL))
8442                 return WERR_BADFID;
8443
8444
8445         /* blindly return success */
8446         return WERR_OK;
8447 }
8448
8449 /****************************************************************
8450  _spoolss_DeletePrinterData
8451 ****************************************************************/
8452
8453 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8454                                   struct spoolss_DeletePrinterData *r)
8455 {
8456         POLICY_HND      *handle = r->in.handle;
8457         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8458         int             snum=0;
8459         WERROR          status = WERR_OK;
8460         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8461
8462         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8463
8464         if (!Printer) {
8465                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8466                         OUR_HANDLE(handle)));
8467                 return WERR_BADFID;
8468         }
8469
8470         if (!get_printer_snum(p, handle, &snum, NULL))
8471                 return WERR_BADFID;
8472
8473         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8474                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8475                         "printer properties change denied by handle\n"));
8476                 return WERR_ACCESS_DENIED;
8477         }
8478
8479         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8480         if (!W_ERROR_IS_OK(status))
8481                 return status;
8482
8483         if (!r->in.value_name) {
8484                 free_a_printer(&printer, 2);
8485                 return WERR_NOMEM;
8486         }
8487
8488         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8489                                         r->in.value_name );
8490
8491         if ( W_ERROR_IS_OK(status) )
8492                 mod_a_printer( printer, 2 );
8493
8494         free_a_printer(&printer, 2);
8495
8496         return status;
8497 }
8498
8499 /****************************************************************
8500  _spoolss_AddForm
8501 ****************************************************************/
8502
8503 WERROR _spoolss_AddForm(pipes_struct *p,
8504                         struct spoolss_AddForm *r)
8505 {
8506         POLICY_HND *handle = r->in.handle;
8507         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8508         nt_forms_struct tmpForm;
8509         int snum;
8510         WERROR status = WERR_OK;
8511         NT_PRINTER_INFO_LEVEL *printer = NULL;
8512
8513         int count=0;
8514         nt_forms_struct *list=NULL;
8515         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8516
8517         DEBUG(5,("_spoolss_AddForm\n"));
8518
8519         if (!Printer) {
8520                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8521                         OUR_HANDLE(handle)));
8522                 return WERR_BADFID;
8523         }
8524
8525
8526         /* forms can be added on printer of on the print server handle */
8527
8528         if ( Printer->printer_type == SPLHND_PRINTER )
8529         {
8530                 if (!get_printer_snum(p,handle, &snum, NULL))
8531                         return WERR_BADFID;
8532
8533                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8534                 if (!W_ERROR_IS_OK(status))
8535                         goto done;
8536         }
8537
8538         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8539                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8540                 status = WERR_ACCESS_DENIED;
8541                 goto done;
8542         }
8543
8544         /* can't add if builtin */
8545
8546         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8547                 status = WERR_FILE_EXISTS;
8548                 goto done;
8549         }
8550
8551         count = get_ntforms(&list);
8552
8553         if(!add_a_form(&list, form, &count)) {
8554                 status =  WERR_NOMEM;
8555                 goto done;
8556         }
8557
8558         write_ntforms(&list, count);
8559
8560         /*
8561          * ChangeID must always be set if this is a printer
8562          */
8563
8564         if ( Printer->printer_type == SPLHND_PRINTER )
8565                 status = mod_a_printer(printer, 2);
8566
8567 done:
8568         if ( printer )
8569                 free_a_printer(&printer, 2);
8570         SAFE_FREE(list);
8571
8572         return status;
8573 }
8574
8575 /****************************************************************
8576  _spoolss_DeleteForm
8577 ****************************************************************/
8578
8579 WERROR _spoolss_DeleteForm(pipes_struct *p,
8580                            struct spoolss_DeleteForm *r)
8581 {
8582         POLICY_HND *handle = r->in.handle;
8583         const char *form_name = r->in.form_name;
8584         nt_forms_struct tmpForm;
8585         int count=0;
8586         nt_forms_struct *list=NULL;
8587         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8588         int snum;
8589         WERROR status = WERR_OK;
8590         NT_PRINTER_INFO_LEVEL *printer = NULL;
8591
8592         DEBUG(5,("_spoolss_DeleteForm\n"));
8593
8594         if (!Printer) {
8595                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8596                         OUR_HANDLE(handle)));
8597                 return WERR_BADFID;
8598         }
8599
8600         /* forms can be deleted on printer of on the print server handle */
8601
8602         if ( Printer->printer_type == SPLHND_PRINTER )
8603         {
8604                 if (!get_printer_snum(p,handle, &snum, NULL))
8605                         return WERR_BADFID;
8606
8607                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8608                 if (!W_ERROR_IS_OK(status))
8609                         goto done;
8610         }
8611
8612         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8613                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8614                 status = WERR_ACCESS_DENIED;
8615                 goto done;
8616         }
8617
8618         /* can't delete if builtin */
8619
8620         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8621                 status = WERR_INVALID_PARAM;
8622                 goto done;
8623         }
8624
8625         count = get_ntforms(&list);
8626
8627         if ( !delete_a_form(&list, form_name, &count, &status ))
8628                 goto done;
8629
8630         /*
8631          * ChangeID must always be set if this is a printer
8632          */
8633
8634         if ( Printer->printer_type == SPLHND_PRINTER )
8635                 status = mod_a_printer(printer, 2);
8636
8637 done:
8638         if ( printer )
8639                 free_a_printer(&printer, 2);
8640         SAFE_FREE(list);
8641
8642         return status;
8643 }
8644
8645 /****************************************************************
8646  _spoolss_SetForm
8647 ****************************************************************/
8648
8649 WERROR _spoolss_SetForm(pipes_struct *p,
8650                         struct spoolss_SetForm *r)
8651 {
8652         POLICY_HND *handle = r->in.handle;
8653         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8654         nt_forms_struct tmpForm;
8655         int snum;
8656         WERROR status = WERR_OK;
8657         NT_PRINTER_INFO_LEVEL *printer = NULL;
8658
8659         int count=0;
8660         nt_forms_struct *list=NULL;
8661         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8662
8663         DEBUG(5,("_spoolss_SetForm\n"));
8664
8665         if (!Printer) {
8666                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8667                         OUR_HANDLE(handle)));
8668                 return WERR_BADFID;
8669         }
8670
8671         /* forms can be modified on printer of on the print server handle */
8672
8673         if ( Printer->printer_type == SPLHND_PRINTER )
8674         {
8675                 if (!get_printer_snum(p,handle, &snum, NULL))
8676                         return WERR_BADFID;
8677
8678                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8679                 if (!W_ERROR_IS_OK(status))
8680                         goto done;
8681         }
8682
8683         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8684                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8685                 status = WERR_ACCESS_DENIED;
8686                 goto done;
8687         }
8688
8689         /* can't set if builtin */
8690         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8691                 status = WERR_INVALID_PARAM;
8692                 goto done;
8693         }
8694
8695         count = get_ntforms(&list);
8696         update_a_form(&list, form, count);
8697         write_ntforms(&list, count);
8698
8699         /*
8700          * ChangeID must always be set if this is a printer
8701          */
8702
8703         if ( Printer->printer_type == SPLHND_PRINTER )
8704                 status = mod_a_printer(printer, 2);
8705
8706
8707 done:
8708         if ( printer )
8709                 free_a_printer(&printer, 2);
8710         SAFE_FREE(list);
8711
8712         return status;
8713 }
8714
8715 /****************************************************************************
8716  enumprintprocessors level 1.
8717 ****************************************************************************/
8718
8719 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8720 {
8721         PRINTPROCESSOR_1 *info_1=NULL;
8722         WERROR result = WERR_OK;
8723
8724         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8725                 return WERR_NOMEM;
8726
8727         (*returned) = 0x1;
8728
8729         init_unistr(&info_1->name, "winprint");
8730
8731         *needed += spoolss_size_printprocessor_info_1(info_1);
8732
8733         if (*needed > offered) {
8734                 result = WERR_INSUFFICIENT_BUFFER;
8735                 goto out;
8736         }
8737
8738         if (!rpcbuf_alloc_size(buffer, *needed)) {
8739                 result = WERR_NOMEM;
8740                 goto out;
8741         }
8742
8743         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8744
8745 out:
8746         SAFE_FREE(info_1);
8747
8748         if ( !W_ERROR_IS_OK(result) )
8749                 *returned = 0;
8750
8751         return result;
8752 }
8753
8754 /****************************************************************************
8755 ****************************************************************************/
8756
8757 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8758 {
8759         uint32 level = q_u->level;
8760         RPC_BUFFER *buffer = NULL;
8761         uint32 offered = q_u->offered;
8762         uint32 *needed = &r_u->needed;
8763         uint32 *returned = &r_u->returned;
8764
8765         /* that's an [in out] buffer */
8766
8767         if (!q_u->buffer && (offered!=0)) {
8768                 return WERR_INVALID_PARAM;
8769         }
8770
8771         if (offered > MAX_RPC_DATA_SIZE) {
8772                 return WERR_INVALID_PARAM;
8773         }
8774
8775         rpcbuf_move(q_u->buffer, &r_u->buffer);
8776         buffer = r_u->buffer;
8777
8778         DEBUG(5,("spoolss_enumprintprocessors\n"));
8779
8780         /*
8781          * Enumerate the print processors ...
8782          *
8783          * Just reply with "winprint", to keep NT happy
8784          * and I can use my nice printer checker.
8785          */
8786
8787         *returned=0;
8788         *needed=0;
8789
8790         switch (level) {
8791         case 1:
8792                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8793         default:
8794                 return WERR_UNKNOWN_LEVEL;
8795         }
8796 }
8797
8798 /****************************************************************************
8799  enumprintprocdatatypes level 1.
8800 ****************************************************************************/
8801
8802 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8803 {
8804         PRINTPROCDATATYPE_1 *info_1=NULL;
8805         WERROR result = WERR_OK;
8806
8807         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8808                 return WERR_NOMEM;
8809
8810         (*returned) = 0x1;
8811
8812         init_unistr(&info_1->name, "RAW");
8813
8814         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8815
8816         if (*needed > offered) {
8817                 result = WERR_INSUFFICIENT_BUFFER;
8818                 goto out;
8819         }
8820
8821         if (!rpcbuf_alloc_size(buffer, *needed)) {
8822                 result = WERR_NOMEM;
8823                 goto out;
8824         }
8825
8826         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8827
8828 out:
8829         SAFE_FREE(info_1);
8830
8831         if ( !W_ERROR_IS_OK(result) )
8832                 *returned = 0;
8833
8834         return result;
8835 }
8836
8837 /****************************************************************************
8838 ****************************************************************************/
8839
8840 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8841 {
8842         uint32 level = q_u->level;
8843         RPC_BUFFER *buffer = NULL;
8844         uint32 offered = q_u->offered;
8845         uint32 *needed = &r_u->needed;
8846         uint32 *returned = &r_u->returned;
8847
8848         /* that's an [in out] buffer */
8849
8850         if (!q_u->buffer && (offered!=0)) {
8851                 return WERR_INVALID_PARAM;
8852         }
8853
8854         if (offered > MAX_RPC_DATA_SIZE) {
8855                 return WERR_INVALID_PARAM;
8856         }
8857
8858         rpcbuf_move(q_u->buffer, &r_u->buffer);
8859         buffer = r_u->buffer;
8860
8861         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8862
8863         *returned=0;
8864         *needed=0;
8865
8866         switch (level) {
8867         case 1:
8868                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8869         default:
8870                 return WERR_UNKNOWN_LEVEL;
8871         }
8872 }
8873
8874 /****************************************************************************
8875  enumprintmonitors level 1.
8876 ****************************************************************************/
8877
8878 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8879 {
8880         PRINTMONITOR_1 *info_1;
8881         WERROR result = WERR_OK;
8882         int i;
8883
8884         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8885                 return WERR_NOMEM;
8886
8887         *returned = 2;
8888
8889         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8890         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8891
8892         for ( i=0; i<*returned; i++ ) {
8893                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8894         }
8895
8896         if (*needed > offered) {
8897                 result = WERR_INSUFFICIENT_BUFFER;
8898                 goto out;
8899         }
8900
8901         if (!rpcbuf_alloc_size(buffer, *needed)) {
8902                 result = WERR_NOMEM;
8903                 goto out;
8904         }
8905
8906         for ( i=0; i<*returned; i++ ) {
8907                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8908         }
8909
8910 out:
8911         SAFE_FREE(info_1);
8912
8913         if ( !W_ERROR_IS_OK(result) )
8914                 *returned = 0;
8915
8916         return result;
8917 }
8918
8919 /****************************************************************************
8920  enumprintmonitors level 2.
8921 ****************************************************************************/
8922
8923 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8924 {
8925         PRINTMONITOR_2 *info_2;
8926         WERROR result = WERR_OK;
8927         int i;
8928
8929         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8930                 return WERR_NOMEM;
8931
8932         *returned = 2;
8933
8934         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8935         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8936         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8937
8938         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8939         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8940         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8941
8942         for ( i=0; i<*returned; i++ ) {
8943                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8944         }
8945
8946         if (*needed > offered) {
8947                 result = WERR_INSUFFICIENT_BUFFER;
8948                 goto out;
8949         }
8950
8951         if (!rpcbuf_alloc_size(buffer, *needed)) {
8952                 result = WERR_NOMEM;
8953                 goto out;
8954         }
8955
8956         for ( i=0; i<*returned; i++ ) {
8957                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8958         }
8959
8960 out:
8961         SAFE_FREE(info_2);
8962
8963         if ( !W_ERROR_IS_OK(result) )
8964                 *returned = 0;
8965
8966         return result;
8967 }
8968
8969 /****************************************************************************
8970 ****************************************************************************/
8971
8972 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8973 {
8974         uint32 level = q_u->level;
8975         RPC_BUFFER *buffer = NULL;
8976         uint32 offered = q_u->offered;
8977         uint32 *needed = &r_u->needed;
8978         uint32 *returned = &r_u->returned;
8979
8980         /* that's an [in out] buffer */
8981
8982         if (!q_u->buffer && (offered!=0)) {
8983                 return WERR_INVALID_PARAM;
8984         }
8985
8986         if (offered > MAX_RPC_DATA_SIZE) {
8987                 return WERR_INVALID_PARAM;
8988         }
8989
8990         rpcbuf_move(q_u->buffer, &r_u->buffer);
8991         buffer = r_u->buffer;
8992
8993         DEBUG(5,("spoolss_enumprintmonitors\n"));
8994
8995         /*
8996          * Enumerate the print monitors ...
8997          *
8998          * Just reply with "Local Port", to keep NT happy
8999          * and I can use my nice printer checker.
9000          */
9001
9002         *returned=0;
9003         *needed=0;
9004
9005         switch (level) {
9006         case 1:
9007                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
9008         case 2:
9009                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
9010         default:
9011                 return WERR_UNKNOWN_LEVEL;
9012         }
9013 }
9014
9015 /****************************************************************************
9016 ****************************************************************************/
9017
9018 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9019                              NT_PRINTER_INFO_LEVEL *ntprinter,
9020                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9021                              uint32 *needed)
9022 {
9023         int i=0;
9024         bool found=False;
9025         JOB_INFO_1 *info_1=NULL;
9026         WERROR result = WERR_OK;
9027
9028         info_1=SMB_MALLOC_P(JOB_INFO_1);
9029
9030         if (info_1 == NULL) {
9031                 return WERR_NOMEM;
9032         }
9033
9034         for (i=0; i<count && found==False; i++) {
9035                 if ((*queue)[i].job==(int)jobid)
9036                         found=True;
9037         }
9038
9039         if (found==False) {
9040                 SAFE_FREE(info_1);
9041                 /* NT treats not found as bad param... yet another bad choice */
9042                 return WERR_INVALID_PARAM;
9043         }
9044
9045         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9046
9047         *needed += spoolss_size_job_info_1(info_1);
9048
9049         if (*needed > offered) {
9050                 result = WERR_INSUFFICIENT_BUFFER;
9051                 goto out;
9052         }
9053
9054         if (!rpcbuf_alloc_size(buffer, *needed)) {
9055                 result = WERR_NOMEM;
9056                 goto out;
9057         }
9058
9059         smb_io_job_info_1("", buffer, info_1, 0);
9060
9061 out:
9062         SAFE_FREE(info_1);
9063
9064         return result;
9065 }
9066
9067 /****************************************************************************
9068 ****************************************************************************/
9069
9070 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9071                              NT_PRINTER_INFO_LEVEL *ntprinter,
9072                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9073                              uint32 *needed)
9074 {
9075         int             i = 0;
9076         bool            found = False;
9077         JOB_INFO_2      *info_2;
9078         WERROR          result;
9079         DEVICEMODE      *devmode = NULL;
9080         NT_DEVICEMODE   *nt_devmode = NULL;
9081
9082         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9083                 return WERR_NOMEM;
9084
9085         ZERO_STRUCTP(info_2);
9086
9087         for ( i=0; i<count && found==False; i++ )
9088         {
9089                 if ((*queue)[i].job == (int)jobid)
9090                         found = True;
9091         }
9092
9093         if ( !found ) {
9094                 /* NT treats not found as bad param... yet another bad
9095                    choice */
9096                 result = WERR_INVALID_PARAM;
9097                 goto done;
9098         }
9099
9100         /*
9101          * if the print job does not have a DEVMODE associated with it,
9102          * just use the one for the printer. A NULL devicemode is not
9103          *  a failure condition
9104          */
9105
9106         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9107                 devmode = construct_dev_mode(lp_const_servicename(snum));
9108         else {
9109                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9110                         ZERO_STRUCTP( devmode );
9111                         convert_nt_devicemode( devmode, nt_devmode );
9112                 }
9113         }
9114
9115         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9116
9117         *needed += spoolss_size_job_info_2(info_2);
9118
9119         if (*needed > offered) {
9120                 result = WERR_INSUFFICIENT_BUFFER;
9121                 goto done;
9122         }
9123
9124         if (!rpcbuf_alloc_size(buffer, *needed)) {
9125                 result = WERR_NOMEM;
9126                 goto done;
9127         }
9128
9129         smb_io_job_info_2("", buffer, info_2, 0);
9130
9131         result = WERR_OK;
9132
9133  done:
9134         /* Cleanup allocated memory */
9135
9136         free_job_info_2(info_2);        /* Also frees devmode */
9137         SAFE_FREE(info_2);
9138
9139         return result;
9140 }
9141
9142 /****************************************************************************
9143 ****************************************************************************/
9144
9145 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9146 {
9147         POLICY_HND *handle = &q_u->handle;
9148         uint32 jobid = q_u->jobid;
9149         uint32 level = q_u->level;
9150         RPC_BUFFER *buffer = NULL;
9151         uint32 offered = q_u->offered;
9152         uint32 *needed = &r_u->needed;
9153         WERROR          wstatus = WERR_OK;
9154         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9155         int snum;
9156         int count;
9157         print_queue_struct      *queue = NULL;
9158         print_status_struct prt_status;
9159
9160         /* that's an [in out] buffer */
9161
9162         if (!q_u->buffer && (offered!=0)) {
9163                 return WERR_INVALID_PARAM;
9164         }
9165
9166         if (offered > MAX_RPC_DATA_SIZE) {
9167                 return WERR_INVALID_PARAM;
9168         }
9169
9170         rpcbuf_move(q_u->buffer, &r_u->buffer);
9171         buffer = r_u->buffer;
9172
9173         DEBUG(5,("spoolss_getjob\n"));
9174
9175         *needed = 0;
9176
9177         if (!get_printer_snum(p, handle, &snum, NULL))
9178                 return WERR_BADFID;
9179
9180         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9181         if ( !W_ERROR_IS_OK(wstatus) )
9182                 return wstatus;
9183
9184         count = print_queue_status(snum, &queue, &prt_status);
9185
9186         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9187                      count, prt_status.status, prt_status.message));
9188
9189         switch ( level ) {
9190         case 1:
9191                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9192                                 buffer, offered, needed);
9193                         break;
9194         case 2:
9195                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9196                                 buffer, offered, needed);
9197                         break;
9198         default:
9199                         wstatus = WERR_UNKNOWN_LEVEL;
9200                         break;
9201         }
9202
9203         SAFE_FREE(queue);
9204         free_a_printer( &ntprinter, 2 );
9205
9206         return wstatus;
9207 }
9208
9209 /****************************************************************
9210  _spoolss_GetPrinterDataEx
9211
9212  From MSDN documentation of GetPrinterDataEx: pass request
9213  to GetPrinterData if key is "PrinterDriverData".
9214 ****************************************************************/
9215
9216 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9217                                  struct spoolss_GetPrinterDataEx *r)
9218 {
9219         POLICY_HND      *handle = r->in.handle;
9220         uint8           *data = NULL;
9221         const char      *keyname = r->in.key_name;
9222         const char      *valuename = r->in.value_name;
9223
9224         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9225
9226         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9227         int                     snum = 0;
9228         WERROR                  status = WERR_OK;
9229
9230         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9231
9232         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9233                 keyname, valuename));
9234
9235         /* in case of problem, return some default values */
9236
9237         *r->out.needed  = 0;
9238         *r->out.type    = 0;
9239
9240         if (!Printer) {
9241                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9242                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9243                 status = WERR_BADFID;
9244                 goto done;
9245         }
9246
9247         /* Is the handle to a printer or to the server? */
9248
9249         if (Printer->printer_type == SPLHND_SERVER) {
9250                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9251                         "Not implemented for server handles yet\n"));
9252                 status = WERR_INVALID_PARAM;
9253                 goto done;
9254         }
9255
9256         if ( !get_printer_snum(p,handle, &snum, NULL) )
9257                 return WERR_BADFID;
9258
9259         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9260         if ( !W_ERROR_IS_OK(status) )
9261                 goto done;
9262
9263         /* check to see if the keyname is valid */
9264         if ( !strlen(keyname) ) {
9265                 status = WERR_INVALID_PARAM;
9266                 goto done;
9267         }
9268
9269         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9270                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9271                         "Invalid keyname [%s]\n", keyname ));
9272                 free_a_printer( &printer, 2 );
9273                 status = WERR_BADFILE;
9274                 goto done;
9275         }
9276
9277         /* When given a new keyname, we should just create it */
9278
9279         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9280                                      r->out.type, &data, r->out.needed,
9281                                      r->in.offered );
9282
9283         if (*r->out.needed > r->in.offered) {
9284                 status = WERR_MORE_DATA;
9285         }
9286
9287         if (W_ERROR_IS_OK(status)) {
9288                 memcpy(r->out.buffer, data, r->in.offered);
9289         }
9290
9291 done:
9292         if ( printer )
9293         free_a_printer( &printer, 2 );
9294
9295         return status;
9296 }
9297
9298 /****************************************************************
9299  _spoolss_SetPrinterDataEx
9300 ****************************************************************/
9301
9302 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9303                                  struct spoolss_SetPrinterDataEx *r)
9304 {
9305         POLICY_HND              *handle = r->in.handle;
9306         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9307         int                     snum = 0;
9308         WERROR                  status = WERR_OK;
9309         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9310         char                    *oid_string;
9311
9312         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9313
9314         /* From MSDN documentation of SetPrinterDataEx: pass request to
9315            SetPrinterData if key is "PrinterDriverData" */
9316
9317         if (!Printer) {
9318                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9319                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9320                 return WERR_BADFID;
9321         }
9322
9323         if ( Printer->printer_type == SPLHND_SERVER ) {
9324                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9325                         "Not implemented for server handles yet\n"));
9326                 return WERR_INVALID_PARAM;
9327         }
9328
9329         if ( !get_printer_snum(p,handle, &snum, NULL) )
9330                 return WERR_BADFID;
9331
9332         /*
9333          * Access check : NT returns "access denied" if you make a
9334          * SetPrinterData call without the necessary privildge.
9335          * we were originally returning OK if nothing changed
9336          * which made Win2k issue **a lot** of SetPrinterData
9337          * when connecting to a printer  --jerry
9338          */
9339
9340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9341         {
9342                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9343                         "change denied by handle access permissions\n"));
9344                 return WERR_ACCESS_DENIED;
9345         }
9346
9347         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9348         if (!W_ERROR_IS_OK(status))
9349                 return status;
9350
9351         /* check for OID in valuename */
9352
9353         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9354         {
9355                 *oid_string = '\0';
9356                 oid_string++;
9357         }
9358
9359         /* save the registry data */
9360
9361         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9362                                      r->in.type, r->in.buffer, r->in.offered );
9363
9364         if ( W_ERROR_IS_OK(status) )
9365         {
9366                 /* save the OID if one was specified */
9367                 if ( oid_string ) {
9368                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9369                                 r->in.key_name, SPOOL_OID_KEY);
9370                         if (!str) {
9371                                 return WERR_NOMEM;
9372                         }
9373
9374                         /*
9375                          * I'm not checking the status here on purpose.  Don't know
9376                          * if this is right, but I'm returning the status from the
9377                          * previous set_printer_dataex() call.  I have no idea if
9378                          * this is right.    --jerry
9379                          */
9380
9381                         set_printer_dataex( printer, str, r->in.value_name,
9382                                             REG_SZ, (uint8 *)oid_string,
9383                                             strlen(oid_string)+1 );
9384                 }
9385
9386                 status = mod_a_printer(printer, 2);
9387         }
9388
9389         free_a_printer(&printer, 2);
9390
9391         return status;
9392 }
9393
9394 /****************************************************************
9395  _spoolss_DeletePrinterDataEx
9396 ****************************************************************/
9397
9398 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9399                                     struct spoolss_DeletePrinterDataEx *r)
9400 {
9401         POLICY_HND      *handle = r->in.handle;
9402         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9403         int             snum=0;
9404         WERROR          status = WERR_OK;
9405         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9406
9407         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9408
9409         if (!Printer) {
9410                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9411                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9412                 return WERR_BADFID;
9413         }
9414
9415         if (!get_printer_snum(p, handle, &snum, NULL))
9416                 return WERR_BADFID;
9417
9418         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9419                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9420                         "printer properties change denied by handle\n"));
9421                 return WERR_ACCESS_DENIED;
9422         }
9423
9424         if (!r->in.value_name || !r->in.key_name) {
9425                 return WERR_NOMEM;
9426         }
9427
9428         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9429         if (!W_ERROR_IS_OK(status))
9430                 return status;
9431
9432         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9433
9434         if ( W_ERROR_IS_OK(status) )
9435                 mod_a_printer( printer, 2 );
9436
9437         free_a_printer(&printer, 2);
9438
9439         return status;
9440 }
9441
9442 /********************************************************************
9443  * spoolss_enumprinterkey
9444  ********************************************************************/
9445
9446
9447 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9448 {
9449         fstring         key;
9450         fstring         *keynames = NULL;
9451         uint16          *enumkeys = NULL;
9452         int             num_keys;
9453         int             printerkey_len;
9454         POLICY_HND      *handle = &q_u->handle;
9455         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9456         NT_PRINTER_DATA *data;
9457         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9458         int             snum = 0;
9459         WERROR          status = WERR_BADFILE;
9460
9461
9462         DEBUG(4,("_spoolss_enumprinterkey\n"));
9463
9464         if (!Printer) {
9465                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9466                 return WERR_BADFID;
9467         }
9468
9469         if ( !get_printer_snum(p,handle, &snum, NULL) )
9470                 return WERR_BADFID;
9471
9472         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9473         if (!W_ERROR_IS_OK(status))
9474                 return status;
9475
9476         /* get the list of subkey names */
9477
9478         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9479         data = printer->info_2->data;
9480
9481         num_keys = get_printer_subkeys( data, key, &keynames );
9482
9483         if ( num_keys == -1 ) {
9484                 status = WERR_BADFILE;
9485                 goto done;
9486         }
9487
9488         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9489
9490         r_u->needed = printerkey_len*2;
9491
9492         if ( q_u->size < r_u->needed ) {
9493                 status = WERR_MORE_DATA;
9494                 goto done;
9495         }
9496
9497         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9498                 status = WERR_NOMEM;
9499                 goto done;
9500         }
9501
9502         status = WERR_OK;
9503
9504         if ( q_u->size < r_u->needed )
9505                 status = WERR_MORE_DATA;
9506
9507 done:
9508         free_a_printer( &printer, 2 );
9509         SAFE_FREE( keynames );
9510
9511         return status;
9512 }
9513
9514 /****************************************************************
9515  _spoolss_DeletePrinterKey
9516 ****************************************************************/
9517
9518 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9519                                  struct spoolss_DeletePrinterKey *r)
9520 {
9521         POLICY_HND              *handle = r->in.handle;
9522         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9523         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9524         int                     snum=0;
9525         WERROR                  status;
9526
9527         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9528
9529         if (!Printer) {
9530                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9531                         OUR_HANDLE(handle)));
9532                 return WERR_BADFID;
9533         }
9534
9535         /* if keyname == NULL, return error */
9536
9537         if ( !r->in.key_name )
9538                 return WERR_INVALID_PARAM;
9539
9540         if (!get_printer_snum(p, handle, &snum, NULL))
9541                 return WERR_BADFID;
9542
9543         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9544                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9545                         "printer properties change denied by handle\n"));
9546                 return WERR_ACCESS_DENIED;
9547         }
9548
9549         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9550         if (!W_ERROR_IS_OK(status))
9551                 return status;
9552
9553         /* delete the key and all subneys */
9554
9555         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9556
9557         if ( W_ERROR_IS_OK(status) )
9558                 status = mod_a_printer(printer, 2);
9559
9560         free_a_printer( &printer, 2 );
9561
9562         return status;
9563 }
9564
9565
9566 /********************************************************************
9567  * spoolss_enumprinterdataex
9568  ********************************************************************/
9569
9570 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9571 {
9572         POLICY_HND      *handle = &q_u->handle;
9573         uint32          in_size = q_u->size;
9574         uint32          num_entries,
9575                         needed;
9576         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9577         PRINTER_ENUM_VALUES     *enum_values = NULL;
9578         NT_PRINTER_DATA         *p_data;
9579         fstring         key;
9580         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9581         int             snum;
9582         WERROR          result;
9583         int             key_index;
9584         int             i;
9585         REGISTRY_VALUE  *val;
9586         char            *value_name;
9587         uint32          data_len;
9588
9589
9590         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9591
9592         if (!Printer) {
9593                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9594                 return WERR_BADFID;
9595         }
9596
9597         /*
9598          * first check for a keyname of NULL or "".  Win2k seems to send
9599          * this a lot and we should send back WERR_INVALID_PARAM
9600          * no need to spend time looking up the printer in this case.
9601          * --jerry
9602          */
9603
9604         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9605         if ( !strlen(key) ) {
9606                 result = WERR_INVALID_PARAM;
9607                 goto done;
9608         }
9609
9610         /* get the printer off of disk */
9611
9612         if (!get_printer_snum(p,handle, &snum, NULL))
9613                 return WERR_BADFID;
9614
9615         ZERO_STRUCT(printer);
9616         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9617         if (!W_ERROR_IS_OK(result))
9618                 return result;
9619
9620         /* now look for a match on the key name */
9621
9622         p_data = printer->info_2->data;
9623
9624         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9625         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9626         {
9627                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9628                 result = WERR_INVALID_PARAM;
9629                 goto done;
9630         }
9631
9632         result = WERR_OK;
9633         needed = 0;
9634
9635         /* allocate the memory for the array of pointers -- if necessary */
9636
9637         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9638         if ( num_entries )
9639         {
9640                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9641                 {
9642                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9643                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9644                         result = WERR_NOMEM;
9645                         goto done;
9646                 }
9647
9648                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9649         }
9650
9651         /*
9652          * loop through all params and build the array to pass
9653          * back to the  client
9654          */
9655
9656         for ( i=0; i<num_entries; i++ )
9657         {
9658                 /* lookup the registry value */
9659
9660                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9661                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9662
9663                 /* copy the data */
9664
9665                 value_name = regval_name( val );
9666                 init_unistr( &enum_values[i].valuename, value_name );
9667                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9668                 enum_values[i].type      = regval_type( val );
9669
9670                 data_len = regval_size( val );
9671                 if ( data_len ) {
9672                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9673                         {
9674                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9675                                         data_len ));
9676                                 result = WERR_NOMEM;
9677                                 goto done;
9678                         }
9679                 }
9680                 enum_values[i].data_len = data_len;
9681
9682                 /* keep track of the size of the array in bytes */
9683
9684                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9685         }
9686
9687         /* housekeeping information in the reply */
9688
9689         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9690          * the hand marshalled container size is a multiple
9691          * of 4 bytes for RPC alignment.
9692          */
9693
9694         if (needed % 4) {
9695                 needed += 4-(needed % 4);
9696         }
9697
9698         r_u->needed     = needed;
9699         r_u->returned   = num_entries;
9700
9701         if (needed > in_size) {
9702                 result = WERR_MORE_DATA;
9703                 goto done;
9704         }
9705
9706         /* copy data into the reply */
9707
9708         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9709            response buffer size is != the offered buffer size
9710
9711                 r_u->ctr.size           = r_u->needed;
9712         */
9713         r_u->ctr.size           = in_size;
9714
9715         r_u->ctr.size_of_array  = r_u->returned;
9716         r_u->ctr.values         = enum_values;
9717
9718 done:
9719         if ( printer )
9720         free_a_printer(&printer, 2);
9721
9722         return result;
9723 }
9724
9725 /****************************************************************************
9726 ****************************************************************************/
9727
9728 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9729 {
9730         init_unistr(&info->name, name);
9731 }
9732
9733 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9734                                                  UNISTR2 *environment,
9735                                                  RPC_BUFFER *buffer,
9736                                                  uint32 offered,
9737                                                  uint32 *needed)
9738 {
9739         char *long_archi = NULL;
9740         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9741         WERROR result = WERR_OK;
9742         TALLOC_CTX *ctx = talloc_tos();
9743
9744         long_archi = unistr2_to_ascii_talloc(ctx, environment);
9745         if (!long_archi) {
9746                 return WERR_NOMEM;
9747         }
9748
9749         if (!get_short_archi(long_archi))
9750                 return WERR_INVALID_ENVIRONMENT;
9751
9752         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9753                 return WERR_NOMEM;
9754
9755         fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9756
9757         *needed += spoolss_size_printprocessordirectory_info_1(info);
9758
9759         if (*needed > offered) {
9760                 result = WERR_INSUFFICIENT_BUFFER;
9761                 goto out;
9762         }
9763
9764         if (!rpcbuf_alloc_size(buffer, *needed)) {
9765                 result = WERR_INSUFFICIENT_BUFFER;
9766                 goto out;
9767         }
9768
9769         smb_io_printprocessordirectory_1("", buffer, info, 0);
9770
9771 out:
9772         SAFE_FREE(info);
9773
9774         return result;
9775 }
9776
9777 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9778 {
9779         uint32 level = q_u->level;
9780         RPC_BUFFER *buffer = NULL;
9781         uint32 offered = q_u->offered;
9782         uint32 *needed = &r_u->needed;
9783         WERROR result;
9784
9785         /* that's an [in out] buffer */
9786
9787         if (!q_u->buffer && (offered!=0)) {
9788                 return WERR_INVALID_PARAM;
9789         }
9790
9791         if (offered > MAX_RPC_DATA_SIZE) {
9792                 return WERR_INVALID_PARAM;
9793         }
9794
9795         rpcbuf_move(q_u->buffer, &r_u->buffer);
9796         buffer = r_u->buffer;
9797
9798         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9799
9800         *needed=0;
9801
9802         switch(level) {
9803         case 1:
9804                 result = getprintprocessordirectory_level_1
9805                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9806                 break;
9807         default:
9808                 result = WERR_UNKNOWN_LEVEL;
9809         }
9810
9811         return result;
9812 }
9813
9814 /*******************************************************************
9815  ********************************************************************/
9816
9817 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9818                                const char *dllname)
9819 {
9820         enum ndr_err_code ndr_err;
9821         struct spoolss_MonitorUi ui;
9822
9823         ui.dll_name = dllname;
9824
9825         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9826                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9827         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9828                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9829         }
9830         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9831 }
9832
9833 /*******************************************************************
9834  Streams the monitor UI DLL name in UNICODE
9835 *******************************************************************/
9836
9837 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9838                                NT_USER_TOKEN *token, DATA_BLOB *in,
9839                                DATA_BLOB *out, uint32_t *needed)
9840 {
9841         const char *dllname = "tcpmonui.dll";
9842
9843         *needed = (strlen(dllname)+1) * 2;
9844
9845         if (out->length < *needed) {
9846                 return WERR_INSUFFICIENT_BUFFER;
9847         }
9848
9849         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9850                 return WERR_NOMEM;
9851         }
9852
9853         return WERR_OK;
9854 }
9855
9856 /*******************************************************************
9857  ********************************************************************/
9858
9859 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9860                              struct spoolss_PortData1 *port1,
9861                              const DATA_BLOB *buf)
9862 {
9863         enum ndr_err_code ndr_err;
9864         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9865                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9866         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9867                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9868         }
9869         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9870 }
9871
9872 /*******************************************************************
9873  ********************************************************************/
9874
9875 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9876                              struct spoolss_PortData2 *port2,
9877                              const DATA_BLOB *buf)
9878 {
9879         enum ndr_err_code ndr_err;
9880         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9881                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9882         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9883                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9884         }
9885         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9886 }
9887
9888 /*******************************************************************
9889  Create a new TCP/IP port
9890 *******************************************************************/
9891
9892 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9893                              NT_USER_TOKEN *token, DATA_BLOB *in,
9894                              DATA_BLOB *out, uint32_t *needed)
9895 {
9896         struct spoolss_PortData1 port1;
9897         struct spoolss_PortData2 port2;
9898         char *device_uri = NULL;
9899         uint32_t version;
9900
9901         const char *portname;
9902         const char *hostaddress;
9903         const char *queue;
9904         uint32_t port_number;
9905         uint32_t protocol;
9906
9907         /* peek for spoolss_PortData version */
9908
9909         if (!in || (in->length < (128 + 4))) {
9910                 return WERR_GENERAL_FAILURE;
9911         }
9912
9913         version = IVAL(in->data, 128);
9914
9915         switch (version) {
9916                 case 1:
9917                         ZERO_STRUCT(port1);
9918
9919                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9920                                 return WERR_NOMEM;
9921                         }
9922
9923                         portname        = port1.portname;
9924                         hostaddress     = port1.hostaddress;
9925                         queue           = port1.queue;
9926                         protocol        = port1.protocol;
9927                         port_number     = port1.port_number;
9928
9929                         break;
9930                 case 2:
9931                         ZERO_STRUCT(port2);
9932
9933                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9934                                 return WERR_NOMEM;
9935                         }
9936
9937                         portname        = port2.portname;
9938                         hostaddress     = port2.hostaddress;
9939                         queue           = port2.queue;
9940                         protocol        = port2.protocol;
9941                         port_number     = port2.port_number;
9942
9943                         break;
9944                 default:
9945                         DEBUG(1,("xcvtcp_addport: "
9946                                 "unknown version of port_data: %d\n", version));
9947                         return WERR_UNKNOWN_PORT;
9948         }
9949
9950         /* create the device URI and call the add_port_hook() */
9951
9952         switch (protocol) {
9953         case PROTOCOL_RAWTCP_TYPE:
9954                 device_uri = talloc_asprintf(mem_ctx,
9955                                 "socket://%s:%d/", hostaddress,
9956                                 port_number);
9957                 break;
9958
9959         case PROTOCOL_LPR_TYPE:
9960                 device_uri = talloc_asprintf(mem_ctx,
9961                         "lpr://%s/%s", hostaddress, queue );
9962                 break;
9963
9964         default:
9965                 return WERR_UNKNOWN_PORT;
9966         }
9967
9968         if (!device_uri) {
9969                 return WERR_NOMEM;
9970         }
9971
9972         return add_port_hook(mem_ctx, token, portname, device_uri);
9973 }
9974
9975 /*******************************************************************
9976 *******************************************************************/
9977
9978 struct xcv_api_table xcvtcp_cmds[] = {
9979         { "MonitorUI",  xcvtcp_monitorui },
9980         { "AddPort",    xcvtcp_addport},
9981         { NULL,         NULL }
9982 };
9983
9984 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9985                                      NT_USER_TOKEN *token, const char *command,
9986                                      DATA_BLOB *inbuf,
9987                                      DATA_BLOB *outbuf,
9988                                      uint32_t *needed )
9989 {
9990         int i;
9991
9992         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9993
9994         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9995                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9996                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9997         }
9998
9999         return WERR_BADFUNC;
10000 }
10001
10002 /*******************************************************************
10003 *******************************************************************/
10004 #if 0   /* don't support management using the "Local Port" monitor */
10005
10006 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10007                                  NT_USER_TOKEN *token, DATA_BLOB *in,
10008                                  DATA_BLOB *out, uint32_t *needed)
10009 {
10010         const char *dllname = "localui.dll";
10011
10012         *needed = (strlen(dllname)+1) * 2;
10013
10014         if (out->length < *needed) {
10015                 return WERR_INSUFFICIENT_BUFFER;
10016         }
10017
10018         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10019                 return WERR_NOMEM;
10020         }
10021
10022         return WERR_OK;
10023 }
10024
10025 /*******************************************************************
10026 *******************************************************************/
10027
10028 struct xcv_api_table xcvlocal_cmds[] = {
10029         { "MonitorUI",  xcvlocal_monitorui },
10030         { NULL,         NULL }
10031 };
10032 #else
10033 struct xcv_api_table xcvlocal_cmds[] = {
10034         { NULL,         NULL }
10035 };
10036 #endif
10037
10038
10039
10040 /*******************************************************************
10041 *******************************************************************/
10042
10043 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10044                                        NT_USER_TOKEN *token, const char *command,
10045                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10046                                        uint32_t *needed)
10047 {
10048         int i;
10049
10050         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10051
10052         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10053                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10054                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10055         }
10056         return WERR_BADFUNC;
10057 }
10058
10059 /****************************************************************
10060  _spoolss_XcvData
10061 ****************************************************************/
10062
10063 WERROR _spoolss_XcvData(pipes_struct *p,
10064                         struct spoolss_XcvData *r)
10065 {
10066         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10067         DATA_BLOB out_data;
10068         WERROR werror;
10069
10070         if (!Printer) {
10071                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10072                         OUR_HANDLE(r->in.handle)));
10073                 return WERR_BADFID;
10074         }
10075
10076         /* Has to be a handle to the TCP/IP port monitor */
10077
10078         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10079                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10080                 return WERR_BADFID;
10081         }
10082
10083         /* requires administrative access to the server */
10084
10085         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10086                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10087                 return WERR_ACCESS_DENIED;
10088         }
10089
10090         /* Allocate the outgoing buffer */
10091
10092         if (r->in.out_data_size) {
10093                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10094                 if (out_data.data == NULL) {
10095                         return WERR_NOMEM;
10096                 }
10097         }
10098
10099         switch ( Printer->printer_type ) {
10100         case SPLHND_PORTMON_TCP:
10101                 werror = process_xcvtcp_command(p->mem_ctx,
10102                                                 p->server_info->ptok,
10103                                                 r->in.function_name,
10104                                                 &r->in.in_data, &out_data,
10105                                                 r->out.needed);
10106                 break;
10107         case SPLHND_PORTMON_LOCAL:
10108                 werror = process_xcvlocal_command(p->mem_ctx,
10109                                                   p->server_info->ptok,
10110                                                   r->in.function_name,
10111                                                   &r->in.in_data, &out_data,
10112                                                   r->out.needed);
10113                 break;
10114         default:
10115                 werror = WERR_INVALID_PRINT_MONITOR;
10116         }
10117
10118         if (!W_ERROR_IS_OK(werror)) {
10119                 return werror;
10120         }
10121
10122         *r->out.status_code = 0;
10123
10124         memcpy(r->out.out_data, out_data.data, out_data.length);
10125
10126         return WERR_OK;
10127 }
10128
10129 /****************************************************************
10130  _spoolss_AddPrintProcessor
10131 ****************************************************************/
10132
10133 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10134                                   struct spoolss_AddPrintProcessor *r)
10135 {
10136         /* for now, just indicate success and ignore the add.  We'll
10137            automatically set the winprint processor for printer
10138            entries later.  Used to debug the LexMark Optra S 1855 PCL
10139            driver --jerry */
10140
10141         return WERR_OK;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_EnumPrinters
10146 ****************************************************************/
10147
10148 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10149                              struct spoolss_EnumPrinters *r)
10150 {
10151         p->rng_fault_state = true;
10152         return WERR_NOT_SUPPORTED;
10153 }
10154
10155 /****************************************************************
10156  _spoolss_GetJob
10157 ****************************************************************/
10158
10159 WERROR _spoolss_GetJob(pipes_struct *p,
10160                        struct spoolss_GetJob *r)
10161 {
10162         p->rng_fault_state = true;
10163         return WERR_NOT_SUPPORTED;
10164 }
10165
10166 /****************************************************************
10167  _spoolss_EnumJobs
10168 ****************************************************************/
10169
10170 WERROR _spoolss_EnumJobs(pipes_struct *p,
10171                          struct spoolss_EnumJobs *r)
10172 {
10173         p->rng_fault_state = true;
10174         return WERR_NOT_SUPPORTED;
10175 }
10176
10177 /****************************************************************
10178  _spoolss_AddPrinter
10179 ****************************************************************/
10180
10181 WERROR _spoolss_AddPrinter(pipes_struct *p,
10182                            struct spoolss_AddPrinter *r)
10183 {
10184         p->rng_fault_state = true;
10185         return WERR_NOT_SUPPORTED;
10186 }
10187
10188 /****************************************************************
10189  _spoolss_GetPrinter
10190 ****************************************************************/
10191
10192 WERROR _spoolss_GetPrinter(pipes_struct *p,
10193                            struct spoolss_GetPrinter *r)
10194 {
10195         p->rng_fault_state = true;
10196         return WERR_NOT_SUPPORTED;
10197 }
10198
10199 /****************************************************************
10200  _spoolss_AddPrinterDriver
10201 ****************************************************************/
10202
10203 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
10204                                  struct spoolss_AddPrinterDriver *r)
10205 {
10206         p->rng_fault_state = true;
10207         return WERR_NOT_SUPPORTED;
10208 }
10209
10210 /****************************************************************
10211  _spoolss_EnumPrinterDrivers
10212 ****************************************************************/
10213
10214 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10215                                    struct spoolss_EnumPrinterDrivers *r)
10216 {
10217         p->rng_fault_state = true;
10218         return WERR_NOT_SUPPORTED;
10219 }
10220
10221 /****************************************************************
10222  _spoolss_GetPrinterDriver
10223 ****************************************************************/
10224
10225 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10226                                  struct spoolss_GetPrinterDriver *r)
10227 {
10228         p->rng_fault_state = true;
10229         return WERR_NOT_SUPPORTED;
10230 }
10231
10232 /****************************************************************
10233  _spoolss_EnumPrintProcessors
10234 ****************************************************************/
10235
10236 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10237                                     struct spoolss_EnumPrintProcessors *r)
10238 {
10239         p->rng_fault_state = true;
10240         return WERR_NOT_SUPPORTED;
10241 }
10242
10243 /****************************************************************
10244  _spoolss_GetPrintProcessorDirectory
10245 ****************************************************************/
10246
10247 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10248                                            struct spoolss_GetPrintProcessorDirectory *r)
10249 {
10250         p->rng_fault_state = true;
10251         return WERR_NOT_SUPPORTED;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_ReadPrinter
10256 ****************************************************************/
10257
10258 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10259                             struct spoolss_ReadPrinter *r)
10260 {
10261         p->rng_fault_state = true;
10262         return WERR_NOT_SUPPORTED;
10263 }
10264
10265 /****************************************************************
10266  _spoolss_GetPrinterData
10267 ****************************************************************/
10268
10269 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10270                                struct spoolss_GetPrinterData *r)
10271 {
10272         p->rng_fault_state = true;
10273         return WERR_NOT_SUPPORTED;
10274 }
10275
10276 /****************************************************************
10277  _spoolss_SetPrinterData
10278 ****************************************************************/
10279
10280 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10281                                struct spoolss_SetPrinterData *r)
10282 {
10283         p->rng_fault_state = true;
10284         return WERR_NOT_SUPPORTED;
10285 }
10286
10287 /****************************************************************
10288  _spoolss_WaitForPrinterChange
10289 ****************************************************************/
10290
10291 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10292                                      struct spoolss_WaitForPrinterChange *r)
10293 {
10294         p->rng_fault_state = true;
10295         return WERR_NOT_SUPPORTED;
10296 }
10297
10298 /****************************************************************
10299  _spoolss_EnumForms
10300 ****************************************************************/
10301
10302 WERROR _spoolss_EnumForms(pipes_struct *p,
10303                           struct spoolss_EnumForms *r)
10304 {
10305         p->rng_fault_state = true;
10306         return WERR_NOT_SUPPORTED;
10307 }
10308
10309 /****************************************************************
10310  _spoolss_EnumPorts
10311 ****************************************************************/
10312
10313 WERROR _spoolss_EnumPorts(pipes_struct *p,
10314                           struct spoolss_EnumPorts *r)
10315 {
10316         p->rng_fault_state = true;
10317         return WERR_NOT_SUPPORTED;
10318 }
10319
10320 /****************************************************************
10321  _spoolss_EnumMonitors
10322 ****************************************************************/
10323
10324 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10325                              struct spoolss_EnumMonitors *r)
10326 {
10327         p->rng_fault_state = true;
10328         return WERR_NOT_SUPPORTED;
10329 }
10330
10331 /****************************************************************
10332  _spoolss_AddPort
10333 ****************************************************************/
10334
10335 WERROR _spoolss_AddPort(pipes_struct *p,
10336                         struct spoolss_AddPort *r)
10337 {
10338         p->rng_fault_state = true;
10339         return WERR_NOT_SUPPORTED;
10340 }
10341
10342 /****************************************************************
10343  _spoolss_ConfigurePort
10344 ****************************************************************/
10345
10346 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10347                               struct spoolss_ConfigurePort *r)
10348 {
10349         p->rng_fault_state = true;
10350         return WERR_NOT_SUPPORTED;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_DeletePort
10355 ****************************************************************/
10356
10357 WERROR _spoolss_DeletePort(pipes_struct *p,
10358                            struct spoolss_DeletePort *r)
10359 {
10360         p->rng_fault_state = true;
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_CreatePrinterIC
10366 ****************************************************************/
10367
10368 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10369                                 struct spoolss_CreatePrinterIC *r)
10370 {
10371         p->rng_fault_state = true;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_PlayGDIScriptOnPrinterIC
10377 ****************************************************************/
10378
10379 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10380                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10381 {
10382         p->rng_fault_state = true;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_DeletePrinterIC
10388 ****************************************************************/
10389
10390 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10391                                 struct spoolss_DeletePrinterIC *r)
10392 {
10393         p->rng_fault_state = true;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_AddPrinterConnection
10399 ****************************************************************/
10400
10401 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10402                                      struct spoolss_AddPrinterConnection *r)
10403 {
10404         p->rng_fault_state = true;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_DeletePrinterConnection
10410 ****************************************************************/
10411
10412 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10413                                         struct spoolss_DeletePrinterConnection *r)
10414 {
10415         p->rng_fault_state = true;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_PrinterMessageBox
10421 ****************************************************************/
10422
10423 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10424                                   struct spoolss_PrinterMessageBox *r)
10425 {
10426         p->rng_fault_state = true;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_AddMonitor
10432 ****************************************************************/
10433
10434 WERROR _spoolss_AddMonitor(pipes_struct *p,
10435                            struct spoolss_AddMonitor *r)
10436 {
10437         p->rng_fault_state = true;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_DeleteMonitor
10443 ****************************************************************/
10444
10445 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10446                               struct spoolss_DeleteMonitor *r)
10447 {
10448         p->rng_fault_state = true;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_DeletePrintProcessor
10454 ****************************************************************/
10455
10456 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10457                                      struct spoolss_DeletePrintProcessor *r)
10458 {
10459         p->rng_fault_state = true;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_AddPrintProvidor
10465 ****************************************************************/
10466
10467 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10468                                  struct spoolss_AddPrintProvidor *r)
10469 {
10470         p->rng_fault_state = true;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_DeletePrintProvidor
10476 ****************************************************************/
10477
10478 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10479                                     struct spoolss_DeletePrintProvidor *r)
10480 {
10481         p->rng_fault_state = true;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_EnumPrintProcDataTypes
10487 ****************************************************************/
10488
10489 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10490                                        struct spoolss_EnumPrintProcDataTypes *r)
10491 {
10492         p->rng_fault_state = true;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_GetPrinterDriver2
10498 ****************************************************************/
10499
10500 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10501                                   struct spoolss_GetPrinterDriver2 *r)
10502 {
10503         p->rng_fault_state = true;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_FindFirstPrinterChangeNotification
10509 ****************************************************************/
10510
10511 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10512                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10513 {
10514         p->rng_fault_state = true;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_FindNextPrinterChangeNotification
10520 ****************************************************************/
10521
10522 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10523                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10524 {
10525         p->rng_fault_state = true;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10531 ****************************************************************/
10532
10533 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10534                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10535 {
10536         p->rng_fault_state = true;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_ReplyOpenPrinter
10542 ****************************************************************/
10543
10544 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10545                                  struct spoolss_ReplyOpenPrinter *r)
10546 {
10547         p->rng_fault_state = true;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_RouterReplyPrinter
10553 ****************************************************************/
10554
10555 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10556                                    struct spoolss_RouterReplyPrinter *r)
10557 {
10558         p->rng_fault_state = true;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_ReplyClosePrinter
10564 ****************************************************************/
10565
10566 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10567                                   struct spoolss_ReplyClosePrinter *r)
10568 {
10569         p->rng_fault_state = true;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_AddPortEx
10575 ****************************************************************/
10576
10577 WERROR _spoolss_AddPortEx(pipes_struct *p,
10578                           struct spoolss_AddPortEx *r)
10579 {
10580         p->rng_fault_state = true;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_RouterFindFirstPrinterChangeNotification
10586 ****************************************************************/
10587
10588 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10589                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10590 {
10591         p->rng_fault_state = true;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_SpoolerInit
10597 ****************************************************************/
10598
10599 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10600                             struct spoolss_SpoolerInit *r)
10601 {
10602         p->rng_fault_state = true;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_ResetPrinterEx
10608 ****************************************************************/
10609
10610 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10611                                struct spoolss_ResetPrinterEx *r)
10612 {
10613         p->rng_fault_state = true;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10619 ****************************************************************/
10620
10621 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10622                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10623 {
10624         p->rng_fault_state = true;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_RouterReplyPrinterEx
10630 ****************************************************************/
10631
10632 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10633                                      struct spoolss_RouterReplyPrinterEx *r)
10634 {
10635         p->rng_fault_state = true;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
10641 ****************************************************************/
10642
10643 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
10644                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
10645 {
10646         p->rng_fault_state = true;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_44
10652 ****************************************************************/
10653
10654 WERROR _spoolss_44(pipes_struct *p,
10655                    struct spoolss_44 *r)
10656 {
10657         p->rng_fault_state = true;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_47
10663 ****************************************************************/
10664
10665 WERROR _spoolss_47(pipes_struct *p,
10666                    struct spoolss_47 *r)
10667 {
10668         p->rng_fault_state = true;
10669         return WERR_NOT_SUPPORTED;
10670 }
10671
10672 /****************************************************************
10673  _spoolss_EnumPrinterData
10674 ****************************************************************/
10675
10676 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10677                                 struct spoolss_EnumPrinterData *r)
10678 {
10679         p->rng_fault_state = true;
10680         return WERR_NOT_SUPPORTED;
10681 }
10682
10683 /****************************************************************
10684  _spoolss_4a
10685 ****************************************************************/
10686
10687 WERROR _spoolss_4a(pipes_struct *p,
10688                    struct spoolss_4a *r)
10689 {
10690         p->rng_fault_state = true;
10691         return WERR_NOT_SUPPORTED;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_4b
10696 ****************************************************************/
10697
10698 WERROR _spoolss_4b(pipes_struct *p,
10699                    struct spoolss_4b *r)
10700 {
10701         p->rng_fault_state = true;
10702         return WERR_NOT_SUPPORTED;
10703 }
10704
10705 /****************************************************************
10706  _spoolss_4c
10707 ****************************************************************/
10708
10709 WERROR _spoolss_4c(pipes_struct *p,
10710                    struct spoolss_4c *r)
10711 {
10712         p->rng_fault_state = true;
10713         return WERR_NOT_SUPPORTED;
10714 }
10715
10716 /****************************************************************
10717  _spoolss_EnumPrinterDataEx
10718 ****************************************************************/
10719
10720 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10721                                   struct spoolss_EnumPrinterDataEx *r)
10722 {
10723         p->rng_fault_state = true;
10724         return WERR_NOT_SUPPORTED;
10725 }
10726
10727 /****************************************************************
10728  _spoolss_EnumPrinterKey
10729 ****************************************************************/
10730
10731 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10732                                struct spoolss_EnumPrinterKey *r)
10733 {
10734         p->rng_fault_state = true;
10735         return WERR_NOT_SUPPORTED;
10736 }
10737
10738 /****************************************************************
10739  _spoolss_53
10740 ****************************************************************/
10741
10742 WERROR _spoolss_53(pipes_struct *p,
10743                    struct spoolss_53 *r)
10744 {
10745         p->rng_fault_state = true;
10746         return WERR_NOT_SUPPORTED;
10747 }
10748
10749 /****************************************************************
10750  _spoolss_55
10751 ****************************************************************/
10752
10753 WERROR _spoolss_55(pipes_struct *p,
10754                    struct spoolss_55 *r)
10755 {
10756         p->rng_fault_state = true;
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_56
10762 ****************************************************************/
10763
10764 WERROR _spoolss_56(pipes_struct *p,
10765                    struct spoolss_56 *r)
10766 {
10767         p->rng_fault_state = true;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_57
10773 ****************************************************************/
10774
10775 WERROR _spoolss_57(pipes_struct *p,
10776                    struct spoolss_57 *r)
10777 {
10778         p->rng_fault_state = true;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_AddPrinterDriverEx
10784 ****************************************************************/
10785
10786 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
10787                                    struct spoolss_AddPrinterDriverEx *r)
10788 {
10789         p->rng_fault_state = true;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792
10793 /****************************************************************
10794  _spoolss_5a
10795 ****************************************************************/
10796
10797 WERROR _spoolss_5a(pipes_struct *p,
10798                    struct spoolss_5a *r)
10799 {
10800         p->rng_fault_state = true;
10801         return WERR_NOT_SUPPORTED;
10802 }
10803
10804 /****************************************************************
10805  _spoolss_5b
10806 ****************************************************************/
10807
10808 WERROR _spoolss_5b(pipes_struct *p,
10809                    struct spoolss_5b *r)
10810 {
10811         p->rng_fault_state = true;
10812         return WERR_NOT_SUPPORTED;
10813 }
10814
10815 /****************************************************************
10816  _spoolss_5c
10817 ****************************************************************/
10818
10819 WERROR _spoolss_5c(pipes_struct *p,
10820                    struct spoolss_5c *r)
10821 {
10822         p->rng_fault_state = true;
10823         return WERR_NOT_SUPPORTED;
10824 }
10825
10826 /****************************************************************
10827  _spoolss_5d
10828 ****************************************************************/
10829
10830 WERROR _spoolss_5d(pipes_struct *p,
10831                    struct spoolss_5d *r)
10832 {
10833         p->rng_fault_state = true;
10834         return WERR_NOT_SUPPORTED;
10835 }
10836
10837 /****************************************************************
10838  _spoolss_5e
10839 ****************************************************************/
10840
10841 WERROR _spoolss_5e(pipes_struct *p,
10842                    struct spoolss_5e *r)
10843 {
10844         p->rng_fault_state = true;
10845         return WERR_NOT_SUPPORTED;
10846 }
10847
10848 /****************************************************************
10849  _spoolss_5f
10850 ****************************************************************/
10851
10852 WERROR _spoolss_5f(pipes_struct *p,
10853                    struct spoolss_5f *r)
10854 {
10855         p->rng_fault_state = true;
10856         return WERR_NOT_SUPPORTED;
10857 }
10858