s3-spoolss: use pidl for _spoolss_GetPrinterDataEx.
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *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                 return WERR_INVALID_PARAM;
1533         }
1534
1535         Printer=find_printer_index_by_hnd(p, handle);
1536         if ( !Printer ) {
1537                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1538                         "handle we created for printer %s\n", name ));
1539                 close_printer_handle(p,handle);
1540                 return WERR_INVALID_PARAM;
1541         }
1542
1543         /*
1544          * First case: the user is opening the print server:
1545          *
1546          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1547          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1548          *
1549          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1550          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1551          * or if the user is listed in the smb.conf printer admin parameter.
1552          *
1553          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1554          * client view printer folder, but does not show the MSAPW.
1555          *
1556          * Note: this test needs code to check access rights here too. Jeremy
1557          * could you look at this?
1558          *
1559          * Second case: the user is opening a printer:
1560          * NT doesn't let us connect to a printer if the connecting user
1561          * doesn't have print permission.
1562          *
1563          * Third case: user is opening a Port Monitor
1564          * access checks same as opening a handle to the print server.
1565          */
1566
1567         switch (Printer->printer_type )
1568         {
1569         case SPLHND_SERVER:
1570         case SPLHND_PORTMON_TCP:
1571         case SPLHND_PORTMON_LOCAL:
1572                 /* Printserver handles use global struct... */
1573
1574                 snum = -1;
1575
1576                 /* Map standard access rights to object specific access rights */
1577
1578                 se_map_standard(&r->in.access_mask,
1579                                 &printserver_std_mapping);
1580
1581                 /* Deny any object specific bits that don't apply to print
1582                    servers (i.e printer and job specific bits) */
1583
1584                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1585
1586                 if (r->in.access_mask &
1587                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1588                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1589                         close_printer_handle(p, handle);
1590                         return WERR_ACCESS_DENIED;
1591                 }
1592
1593                 /* Allow admin access */
1594
1595                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1596                 {
1597                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1598
1599                         if (!lp_ms_add_printer_wizard()) {
1600                                 close_printer_handle(p, handle);
1601                                 return WERR_ACCESS_DENIED;
1602                         }
1603
1604                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1605                            and not a printer admin, then fail */
1606
1607                         if ((p->server_info->utok.uid != 0) &&
1608                             !user_has_privileges(p->server_info->ptok,
1609                                                  &se_printop ) &&
1610                             !token_contains_name_in_list(
1611                                     uidtoname(p->server_info->utok.uid),
1612                                     NULL, NULL,
1613                                     p->server_info->ptok,
1614                                     lp_printer_admin(snum))) {
1615                                 close_printer_handle(p, handle);
1616                                 return WERR_ACCESS_DENIED;
1617                         }
1618
1619                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1620                 }
1621                 else
1622                 {
1623                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1624                 }
1625
1626                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1627                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1628
1629                 /* We fall through to return WERR_OK */
1630                 break;
1631
1632         case SPLHND_PRINTER:
1633                 /* NT doesn't let us connect to a printer if the connecting user
1634                    doesn't have print permission.  */
1635
1636                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1637                         close_printer_handle(p, handle);
1638                         return WERR_BADFID;
1639                 }
1640
1641                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1642
1643                 /* map an empty access mask to the minimum access mask */
1644                 if (r->in.access_mask == 0x0)
1645                         r->in.access_mask = PRINTER_ACCESS_USE;
1646
1647                 /*
1648                  * If we are not serving the printer driver for this printer,
1649                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1650                  * will keep NT clients happy  --jerry
1651                  */
1652
1653                 if (lp_use_client_driver(snum)
1654                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1655                 {
1656                         r->in.access_mask = PRINTER_ACCESS_USE;
1657                 }
1658
1659                 /* check smb.conf parameters and the the sec_desc */
1660
1661                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1662                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1663                         return WERR_ACCESS_DENIED;
1664                 }
1665
1666                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1667                                    p->server_info->ptok, snum) ||
1668                     !print_access_check(p->server_info, snum,
1669                                         r->in.access_mask)) {
1670                         DEBUG(3, ("access DENIED for printer open\n"));
1671                         close_printer_handle(p, handle);
1672                         return WERR_ACCESS_DENIED;
1673                 }
1674
1675                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1676                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1677                         close_printer_handle(p, handle);
1678                         return WERR_ACCESS_DENIED;
1679                 }
1680
1681                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1682                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1683                 else
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685
1686                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1687                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1688
1689                 break;
1690
1691         default:
1692                 /* sanity check to prevent programmer error */
1693                 return WERR_BADFID;
1694         }
1695
1696         Printer->access_granted = r->in.access_mask;
1697
1698         /*
1699          * If the client sent a devmode in the OpenPrinter() call, then
1700          * save it here in case we get a job submission on this handle
1701          */
1702
1703          if ( (Printer->printer_type != SPLHND_SERVER)
1704                 && r->in.devmode_ctr.devmode )
1705          {
1706                 convert_devicemode_new(Printer->sharename,
1707                                        r->in.devmode_ctr.devmode,
1708                                        &Printer->nt_devmode);
1709          }
1710
1711 #if 0   /* JERRY -- I'm doubtful this is really effective */
1712         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713            optimization in Windows 2000 clients  --jerry */
1714
1715         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1716                 && (RA_WIN2K == get_remote_arch()) )
1717         {
1718                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1719                 sys_usleep( 500000 );
1720         }
1721 #endif
1722
1723         return WERR_OK;
1724 }
1725
1726 /****************************************************************************
1727 ****************************************************************************/
1728
1729 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1731 {
1732         bool ret;
1733
1734         switch (level) {
1735                 case 2:
1736                         /* allocate memory if needed.  Messy because
1737                            convert_printer_info is used to update an existing
1738                            printer or build a new one */
1739
1740                         if ( !printer->info_2 ) {
1741                                 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742                                 if ( !printer->info_2 ) {
1743                                         DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1744                                         return False;
1745                                 }
1746                         }
1747
1748                         ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749                         printer->info_2->setuptime = time(NULL);
1750
1751                         return ret;
1752         }
1753
1754         return False;
1755 }
1756
1757 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1759 {
1760         bool result = True;
1761
1762         switch (level) {
1763                 case 3:
1764                         printer->info_3=NULL;
1765                         if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1766                                 result = False;
1767                         break;
1768                 case 6:
1769                         printer->info_6=NULL;
1770                         if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771                                 result = False;
1772                         break;
1773                 default:
1774                         break;
1775         }
1776
1777         return result;
1778 }
1779
1780 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781                                 NT_DEVICEMODE **pp_nt_devmode)
1782 {
1783         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1784
1785         /*
1786          * Ensure nt_devmode is a valid pointer
1787          * as we will be overwriting it.
1788          */
1789
1790         if (nt_devmode == NULL) {
1791                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1793                         return False;
1794         }
1795
1796         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1798
1799         nt_devmode->specversion=devmode->specversion;
1800         nt_devmode->driverversion=devmode->driverversion;
1801         nt_devmode->size=devmode->size;
1802         nt_devmode->fields=devmode->fields;
1803         nt_devmode->orientation=devmode->orientation;
1804         nt_devmode->papersize=devmode->papersize;
1805         nt_devmode->paperlength=devmode->paperlength;
1806         nt_devmode->paperwidth=devmode->paperwidth;
1807         nt_devmode->scale=devmode->scale;
1808         nt_devmode->copies=devmode->copies;
1809         nt_devmode->defaultsource=devmode->defaultsource;
1810         nt_devmode->printquality=devmode->printquality;
1811         nt_devmode->color=devmode->color;
1812         nt_devmode->duplex=devmode->duplex;
1813         nt_devmode->yresolution=devmode->yresolution;
1814         nt_devmode->ttoption=devmode->ttoption;
1815         nt_devmode->collate=devmode->collate;
1816
1817         nt_devmode->logpixels=devmode->logpixels;
1818         nt_devmode->bitsperpel=devmode->bitsperpel;
1819         nt_devmode->pelswidth=devmode->pelswidth;
1820         nt_devmode->pelsheight=devmode->pelsheight;
1821         nt_devmode->displayflags=devmode->displayflags;
1822         nt_devmode->displayfrequency=devmode->displayfrequency;
1823         nt_devmode->icmmethod=devmode->icmmethod;
1824         nt_devmode->icmintent=devmode->icmintent;
1825         nt_devmode->mediatype=devmode->mediatype;
1826         nt_devmode->dithertype=devmode->dithertype;
1827         nt_devmode->reserved1=devmode->reserved1;
1828         nt_devmode->reserved2=devmode->reserved2;
1829         nt_devmode->panningwidth=devmode->panningwidth;
1830         nt_devmode->panningheight=devmode->panningheight;
1831
1832         /*
1833          * Only change private and driverextra if the incoming devmode
1834          * has a new one. JRA.
1835          */
1836
1837         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838                 SAFE_FREE(nt_devmode->nt_dev_private);
1839                 nt_devmode->driverextra=devmode->driverextra;
1840                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1841                         return False;
1842                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1843         }
1844
1845         *pp_nt_devmode = nt_devmode;
1846
1847         return True;
1848 }
1849
1850 /********************************************************************
1851  * _spoolss_enddocprinter_internal.
1852  ********************************************************************/
1853
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1855 {
1856         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1857         int snum;
1858
1859         if (!Printer) {
1860                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1861                 return WERR_BADFID;
1862         }
1863
1864         if (!get_printer_snum(p, handle, &snum, NULL))
1865                 return WERR_BADFID;
1866
1867         Printer->document_started=False;
1868         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1869         /* error codes unhandled so far ... */
1870
1871         return WERR_OK;
1872 }
1873
1874 /****************************************************************
1875  _spoolss_ClosePrinter
1876 ****************************************************************/
1877
1878 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1879                              struct spoolss_ClosePrinter *r)
1880 {
1881         POLICY_HND *handle = r->in.handle;
1882
1883         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1884
1885         if (Printer && Printer->document_started)
1886                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1887
1888         if (!close_printer_handle(p, handle))
1889                 return WERR_BADFID;
1890
1891         /* clear the returned printer handle.  Observed behavior
1892            from Win2k server.  Don't think this really matters.
1893            Previous code just copied the value of the closed
1894            handle.    --jerry */
1895
1896         ZERO_STRUCTP(r->out.handle);
1897
1898         return WERR_OK;
1899 }
1900
1901 /****************************************************************
1902  _spoolss_DeletePrinter
1903 ****************************************************************/
1904
1905 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1906                               struct spoolss_DeletePrinter *r)
1907 {
1908         POLICY_HND *handle = r->in.handle;
1909         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1910         WERROR result;
1911
1912         if (Printer && Printer->document_started)
1913                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1914
1915         result = delete_printer_handle(p, handle);
1916
1917         update_c_setprinter(False);
1918
1919         return result;
1920 }
1921
1922 /*******************************************************************
1923  * static function to lookup the version id corresponding to an
1924  * long architecture string
1925  ******************************************************************/
1926
1927 static int get_version_id (char * arch)
1928 {
1929         int i;
1930         struct table_node archi_table[]= {
1931
1932                 {"Windows 4.0",          "WIN40",       0 },
1933                 {"Windows NT x86",       "W32X86",      2 },
1934                 {"Windows NT R4000",     "W32MIPS",     2 },
1935                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
1936                 {"Windows NT PowerPC",   "W32PPC",      2 },
1937                 {"Windows IA64",         "IA64",        3 },
1938                 {"Windows x64",          "x64",         3 },
1939                 {NULL,                   "",            -1 }
1940         };
1941
1942         for (i=0; archi_table[i].long_archi != NULL; i++)
1943         {
1944                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1945                         return (archi_table[i].version);
1946         }
1947
1948         return -1;
1949 }
1950
1951 /****************************************************************
1952  _spoolss_DeletePrinterDriver
1953 ****************************************************************/
1954
1955 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1956                                     struct spoolss_DeletePrinterDriver *r)
1957 {
1958         char *driver;
1959         char *arch;
1960         NT_PRINTER_DRIVER_INFO_LEVEL    info;
1961         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
1962         int                             version;
1963         WERROR                          status;
1964         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1965         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1966
1967         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968            and not a printer admin, then fail */
1969
1970         if ( (p->server_info->utok.uid != 0)
1971                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1972                 && !token_contains_name_in_list(
1973                         uidtoname(p->server_info->utok.uid), NULL,
1974                         NULL, p->server_info->ptok,
1975                         lp_printer_admin(-1)) )
1976         {
1977                 return WERR_ACCESS_DENIED;
1978         }
1979
1980         driver = CONST_DISCARD(char *, r->in.driver);
1981         arch   = CONST_DISCARD(char *, r->in.architecture);
1982
1983         /* check that we have a valid driver name first */
1984
1985         if ((version=get_version_id(arch)) == -1)
1986                 return WERR_INVALID_ENVIRONMENT;
1987
1988         ZERO_STRUCT(info);
1989         ZERO_STRUCT(info_win2k);
1990
1991         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1992         {
1993                 /* try for Win2k driver if "Windows NT x86" */
1994
1995                 if ( version == 2 ) {
1996                         version = 3;
1997                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1998                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1999                                 goto done;
2000                         }
2001                 }
2002                 /* otherwise it was a failure */
2003                 else {
2004                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2005                         goto done;
2006                 }
2007
2008         }
2009
2010         if (printer_driver_in_use(info.info_3)) {
2011                 status = WERR_PRINTER_DRIVER_IN_USE;
2012                 goto done;
2013         }
2014
2015         if ( version == 2 )
2016         {
2017                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2018                 {
2019                         /* if we get to here, we now have 2 driver info structures to remove */
2020                         /* remove the Win2k driver first*/
2021
2022                         status_win2k = delete_printer_driver(
2023                                 p, info_win2k.info_3, 3, False );
2024                         free_a_printer_driver( info_win2k, 3 );
2025
2026                         /* this should not have failed---if it did, report to client */
2027                         if ( !W_ERROR_IS_OK(status_win2k) )
2028                         {
2029                                 status = status_win2k;
2030                                 goto done;
2031                         }
2032                 }
2033         }
2034
2035         status = delete_printer_driver(p, info.info_3, version, False);
2036
2037         /* if at least one of the deletes succeeded return OK */
2038
2039         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2040                 status = WERR_OK;
2041
2042 done:
2043         free_a_printer_driver( info, 3 );
2044
2045         return status;
2046 }
2047
2048 /****************************************************************
2049  _spoolss_DeletePrinterDriverEx
2050 ****************************************************************/
2051
2052 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2053                                       struct spoolss_DeletePrinterDriverEx *r)
2054 {
2055         char *driver;
2056         char *arch;
2057         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2058         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2059         int                             version;
2060         uint32_t                        flags = r->in.delete_flags;
2061         bool                            delete_files;
2062         WERROR                          status;
2063         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2064         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2065
2066         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2067            and not a printer admin, then fail */
2068
2069         if ( (p->server_info->utok.uid != 0)
2070                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2071                 && !token_contains_name_in_list(
2072                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2073                         p->server_info->ptok, lp_printer_admin(-1)) )
2074         {
2075                 return WERR_ACCESS_DENIED;
2076         }
2077
2078         driver = CONST_DISCARD(char *, r->in.driver);
2079         arch   = CONST_DISCARD(char *, r->in.architecture);
2080
2081         /* check that we have a valid driver name first */
2082         if ((version=get_version_id(arch)) == -1) {
2083                 /* this is what NT returns */
2084                 return WERR_INVALID_ENVIRONMENT;
2085         }
2086
2087         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2088                 version = r->in.version;
2089
2090         ZERO_STRUCT(info);
2091         ZERO_STRUCT(info_win2k);
2092
2093         status = get_a_printer_driver(&info, 3, driver, arch, version);
2094
2095         if ( !W_ERROR_IS_OK(status) )
2096         {
2097                 /*
2098                  * if the client asked for a specific version,
2099                  * or this is something other than Windows NT x86,
2100                  * then we've failed
2101                  */
2102
2103                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2104                         goto done;
2105
2106                 /* try for Win2k driver if "Windows NT x86" */
2107
2108                 version = 3;
2109                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2110                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2111                         goto done;
2112                 }
2113         }
2114
2115         if ( printer_driver_in_use(info.info_3) ) {
2116                 status = WERR_PRINTER_DRIVER_IN_USE;
2117                 goto done;
2118         }
2119
2120         /*
2121          * we have a couple of cases to consider.
2122          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2123          *     then the delete should fail if **any** files overlap with
2124          *     other drivers
2125          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2126          *     non-overlapping files
2127          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2128          *     is set, the do not delete any files
2129          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2130          */
2131
2132         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2133
2134         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2135
2136         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2137                 /* no idea of the correct error here */
2138                 status = WERR_ACCESS_DENIED;
2139                 goto done;
2140         }
2141
2142
2143         /* also check for W32X86/3 if necessary; maybe we already have? */
2144
2145         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2146                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2147                 {
2148
2149                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2150                                 /* no idea of the correct error here */
2151                                 free_a_printer_driver( info_win2k, 3 );
2152                                 status = WERR_ACCESS_DENIED;
2153                                 goto done;
2154                         }
2155
2156                         /* if we get to here, we now have 2 driver info structures to remove */
2157                         /* remove the Win2k driver first*/
2158
2159                         status_win2k = delete_printer_driver(
2160                                 p, info_win2k.info_3, 3, delete_files);
2161                         free_a_printer_driver( info_win2k, 3 );
2162
2163                         /* this should not have failed---if it did, report to client */
2164
2165                         if ( !W_ERROR_IS_OK(status_win2k) )
2166                                 goto done;
2167                 }
2168         }
2169
2170         status = delete_printer_driver(p, info.info_3, version, delete_files);
2171
2172         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2173                 status = WERR_OK;
2174 done:
2175         free_a_printer_driver( info, 3 );
2176
2177         return status;
2178 }
2179
2180
2181 /****************************************************************************
2182  Internal routine for retreiving printerdata
2183  ***************************************************************************/
2184
2185 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2186                                   const char *key, const char *value, uint32 *type, uint8 **data,
2187                                   uint32 *needed, uint32 in_size  )
2188 {
2189         REGISTRY_VALUE          *val;
2190         uint32                  size;
2191         int                     data_len;
2192
2193         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2194                 return WERR_BADFILE;
2195
2196         *type = regval_type( val );
2197
2198         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2199
2200         size = regval_size( val );
2201
2202         /* copy the min(in_size, len) */
2203
2204         if ( in_size ) {
2205                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2206
2207                 /* special case for 0 length values */
2208                 if ( data_len ) {
2209                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2210                                 return WERR_NOMEM;
2211                 }
2212                 else {
2213                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2214                                 return WERR_NOMEM;
2215                 }
2216         }
2217         else
2218                 *data = NULL;
2219
2220         *needed = size;
2221
2222         DEBUG(5,("get_printer_dataex: copy done\n"));
2223
2224         return WERR_OK;
2225 }
2226
2227 /****************************************************************************
2228  Internal routine for removing printerdata
2229  ***************************************************************************/
2230
2231 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2232 {
2233         return delete_printer_data( printer->info_2, key, value );
2234 }
2235
2236 /****************************************************************************
2237  Internal routine for storing printerdata
2238  ***************************************************************************/
2239
2240 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2241                                   uint32 type, uint8 *data, int real_len  )
2242 {
2243         /* the registry objects enforce uniqueness based on value name */
2244
2245         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2246 }
2247
2248 /********************************************************************
2249  GetPrinterData on a printer server Handle.
2250 ********************************************************************/
2251
2252 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2253 {
2254         int i;
2255
2256         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2257
2258         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2259                 *type = REG_DWORD;
2260                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2261                         return WERR_NOMEM;
2262                 SIVAL(*data, 0, 0x00);
2263                 *needed = 0x4;
2264                 return WERR_OK;
2265         }
2266
2267         if (!StrCaseCmp(value, "BeepEnabled")) {
2268                 *type = REG_DWORD;
2269                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270                         return WERR_NOMEM;
2271                 SIVAL(*data, 0, 0x00);
2272                 *needed = 0x4;
2273                 return WERR_OK;
2274         }
2275
2276         if (!StrCaseCmp(value, "EventLog")) {
2277                 *type = REG_DWORD;
2278                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279                         return WERR_NOMEM;
2280                 /* formally was 0x1b */
2281                 SIVAL(*data, 0, 0x0);
2282                 *needed = 0x4;
2283                 return WERR_OK;
2284         }
2285
2286         if (!StrCaseCmp(value, "NetPopup")) {
2287                 *type = REG_DWORD;
2288                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289                         return WERR_NOMEM;
2290                 SIVAL(*data, 0, 0x00);
2291                 *needed = 0x4;
2292                 return WERR_OK;
2293         }
2294
2295         if (!StrCaseCmp(value, "MajorVersion")) {
2296                 *type = REG_DWORD;
2297                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2298                         return WERR_NOMEM;
2299
2300                 /* Windows NT 4.0 seems to not allow uploading of drivers
2301                    to a server that reports 0x3 as the MajorVersion.
2302                    need to investigate more how Win2k gets around this .
2303                    -- jerry */
2304
2305                 if ( RA_WINNT == get_remote_arch() )
2306                         SIVAL(*data, 0, 2);
2307                 else
2308                         SIVAL(*data, 0, 3);
2309
2310                 *needed = 0x4;
2311                 return WERR_OK;
2312         }
2313
2314         if (!StrCaseCmp(value, "MinorVersion")) {
2315                 *type = REG_DWORD;
2316                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2317                         return WERR_NOMEM;
2318                 SIVAL(*data, 0, 0);
2319                 *needed = 0x4;
2320                 return WERR_OK;
2321         }
2322
2323         /* REG_BINARY
2324          *  uint32 size          = 0x114
2325          *  uint32 major         = 5
2326          *  uint32 minor         = [0|1]
2327          *  uint32 build         = [2195|2600]
2328          *  extra unicode string = e.g. "Service Pack 3"
2329          */
2330         if (!StrCaseCmp(value, "OSVersion")) {
2331                 *type = REG_BINARY;
2332                 *needed = 0x114;
2333
2334                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2335                         return WERR_NOMEM;
2336
2337                 SIVAL(*data, 0, *needed);       /* size */
2338                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2339                 SIVAL(*data, 8, 0);
2340                 SIVAL(*data, 12, 2195);         /* build */
2341
2342                 /* leave extra string empty */
2343
2344                 return WERR_OK;
2345         }
2346
2347
2348         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2349                 const char *string="C:\\PRINTERS";
2350                 *type = REG_SZ;
2351                 *needed = 2*(strlen(string)+1);
2352                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2353                         return WERR_NOMEM;
2354                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2355
2356                 /* it's done by hand ready to go on the wire */
2357                 for (i=0; i<strlen(string); i++) {
2358                         (*data)[2*i]=string[i];
2359                         (*data)[2*i+1]='\0';
2360                 }
2361                 return WERR_OK;
2362         }
2363
2364         if (!StrCaseCmp(value, "Architecture")) {
2365                 const char *string="Windows NT x86";
2366                 *type = REG_SZ;
2367                 *needed = 2*(strlen(string)+1);
2368                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2369                         return WERR_NOMEM;
2370                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2371                 for (i=0; i<strlen(string); i++) {
2372                         (*data)[2*i]=string[i];
2373                         (*data)[2*i+1]='\0';
2374                 }
2375                 return WERR_OK;
2376         }
2377
2378         if (!StrCaseCmp(value, "DsPresent")) {
2379                 *type = REG_DWORD;
2380                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2381                         return WERR_NOMEM;
2382
2383                 /* only show the publish check box if we are a
2384                    memeber of a AD domain */
2385
2386                 if ( lp_security() == SEC_ADS )
2387                         SIVAL(*data, 0, 0x01);
2388                 else
2389                         SIVAL(*data, 0, 0x00);
2390
2391                 *needed = 0x4;
2392                 return WERR_OK;
2393         }
2394
2395         if (!StrCaseCmp(value, "DNSMachineName")) {
2396                 const char *hostname = get_mydnsfullname();
2397
2398                 if (!hostname)
2399                         return WERR_BADFILE;
2400                 *type = REG_SZ;
2401                 *needed = 2*(strlen(hostname)+1);
2402                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2403                         return WERR_NOMEM;
2404                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2405                 for (i=0; i<strlen(hostname); i++) {
2406                         (*data)[2*i]=hostname[i];
2407                         (*data)[2*i+1]='\0';
2408                 }
2409                 return WERR_OK;
2410         }
2411
2412
2413         return WERR_BADFILE;
2414 }
2415
2416 /********************************************************************
2417  * spoolss_getprinterdata
2418  ********************************************************************/
2419
2420 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2421 {
2422         POLICY_HND      *handle = &q_u->handle;
2423         UNISTR2         *valuename = &q_u->valuename;
2424         uint32          in_size = q_u->size;
2425         uint32          *type = &r_u->type;
2426         uint32          *out_size = &r_u->size;
2427         uint8           **data = &r_u->data;
2428         uint32          *needed = &r_u->needed;
2429         WERROR          status;
2430         fstring         value;
2431         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2432         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2433         int             snum = 0;
2434
2435         /*
2436          * Reminder: when it's a string, the length is in BYTES
2437          * even if UNICODE is negociated.
2438          *
2439          * JFM, 4/19/1999
2440          */
2441
2442         *out_size = in_size;
2443
2444         /* in case of problem, return some default values */
2445
2446         *needed = 0;
2447         *type   = 0;
2448
2449         DEBUG(4,("_spoolss_getprinterdata\n"));
2450
2451         if ( !Printer ) {
2452                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2453                 status = WERR_BADFID;
2454                 goto done;
2455         }
2456
2457         unistr2_to_ascii(value, valuename, sizeof(value));
2458
2459         if ( Printer->printer_type == SPLHND_SERVER )
2460                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2461         else
2462         {
2463                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2464                         status = WERR_BADFID;
2465                         goto done;
2466                 }
2467
2468                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2469                 if ( !W_ERROR_IS_OK(status) )
2470                         goto done;
2471
2472                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2473
2474                 if ( strequal(value, "ChangeId") ) {
2475                         *type = REG_DWORD;
2476                         *needed = sizeof(uint32);
2477                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2478                                 status = WERR_NOMEM;
2479                                 goto done;
2480                         }
2481                         SIVAL( *data, 0, printer->info_2->changeid );
2482                         status = WERR_OK;
2483                 }
2484                 else
2485                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2486         }
2487
2488         if (*needed > *out_size)
2489                 status = WERR_MORE_DATA;
2490
2491 done:
2492         if ( !W_ERROR_IS_OK(status) )
2493         {
2494                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2495
2496                 /* reply this param doesn't exist */
2497
2498                 if ( *out_size ) {
2499                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2500                                 if ( printer )
2501                                         free_a_printer( &printer, 2 );
2502                                 return WERR_NOMEM;
2503                         }
2504                 } else {
2505                         *data = NULL;
2506                 }
2507         }
2508
2509         /* cleanup & exit */
2510
2511         if ( printer )
2512                 free_a_printer( &printer, 2 );
2513
2514         return status;
2515 }
2516
2517 /*********************************************************
2518  Connect to the client machine.
2519 **********************************************************/
2520
2521 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2522                         struct sockaddr_storage *client_ss, const char *remote_machine)
2523 {
2524         NTSTATUS ret;
2525         struct cli_state *the_cli;
2526         struct sockaddr_storage rm_addr;
2527
2528         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2529                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2530                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2531                         return False;
2532                 }
2533
2534                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2535                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2536                         return False;
2537                 }
2538         } else {
2539                 char addr[INET6_ADDRSTRLEN];
2540                 rm_addr = *client_ss;
2541                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2542                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2543                         addr));
2544         }
2545
2546         /* setup the connection */
2547
2548         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2549                 &rm_addr, 0, "IPC$", "IPC",
2550                 "", /* username */
2551                 "", /* domain */
2552                 "", /* password */
2553                 0, lp_client_signing(), NULL );
2554
2555         if ( !NT_STATUS_IS_OK( ret ) ) {
2556                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2557                         remote_machine ));
2558                 return False;
2559         }
2560
2561         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2562                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2563                 cli_shutdown(the_cli);
2564                 return False;
2565         }
2566
2567         /*
2568          * Ok - we have an anonymous connection to the IPC$ share.
2569          * Now start the NT Domain stuff :-).
2570          */
2571
2572         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2573         if (!NT_STATUS_IS_OK(ret)) {
2574                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2575                         remote_machine, nt_errstr(ret)));
2576                 cli_shutdown(the_cli);
2577                 return False;
2578         }
2579
2580         return True;
2581 }
2582
2583 /***************************************************************************
2584  Connect to the client.
2585 ****************************************************************************/
2586
2587 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2588                                         uint32 localprinter, uint32 type,
2589                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2590 {
2591         WERROR result;
2592         NTSTATUS status;
2593
2594         /*
2595          * If it's the first connection, contact the client
2596          * and connect to the IPC$ share anonymously
2597          */
2598         if (smb_connections==0) {
2599                 fstring unix_printer;
2600
2601                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2602
2603                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2604                         return False;
2605
2606                 messaging_register(smbd_messaging_context(), NULL,
2607                                    MSG_PRINTER_NOTIFY2,
2608                                    receive_notify2_message_list);
2609                 /* Tell the connections db we're now interested in printer
2610                  * notify messages. */
2611                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2612         }
2613
2614         /*
2615          * Tell the specific printing tdb we want messages for this printer
2616          * by registering our PID.
2617          */
2618
2619         if (!print_notify_register_pid(snum))
2620                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2621
2622         smb_connections++;
2623
2624         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2625                                                  printer,
2626                                                  localprinter,
2627                                                  type,
2628                                                  0,
2629                                                  NULL,
2630                                                  handle,
2631                                                  &result);
2632         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2633                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2634                         win_errstr(result)));
2635
2636         return (W_ERROR_IS_OK(result));
2637 }
2638
2639 /********************************************************************
2640  * _spoolss_rffpcnex
2641  * ReplyFindFirstPrinterChangeNotifyEx
2642  *
2643  * before replying OK: status=0 a rpc call is made to the workstation
2644  * asking ReplyOpenPrinter
2645  *
2646  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2647  * called from api_spoolss_rffpcnex
2648  ********************************************************************/
2649
2650 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2651 {
2652         POLICY_HND *handle = &q_u->handle;
2653         uint32 flags = q_u->flags;
2654         uint32 options = q_u->options;
2655         UNISTR2 *localmachine = &q_u->localmachine;
2656         uint32 printerlocal = q_u->printerlocal;
2657         int snum = -1;
2658         SPOOL_NOTIFY_OPTION *option = q_u->option;
2659         struct sockaddr_storage client_ss;
2660
2661         /* store the notify value in the printer struct */
2662
2663         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2664
2665         if (!Printer) {
2666                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2667                 return WERR_BADFID;
2668         }
2669
2670         Printer->notify.flags=flags;
2671         Printer->notify.options=options;
2672         Printer->notify.printerlocal=printerlocal;
2673
2674         if (Printer->notify.option)
2675                 free_spool_notify_option(&Printer->notify.option);
2676
2677         Printer->notify.option=dup_spool_notify_option(option);
2678
2679         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2680                        sizeof(Printer->notify.localmachine));
2681
2682         /* Connect to the client machine and send a ReplyOpenPrinter */
2683
2684         if ( Printer->printer_type == SPLHND_SERVER)
2685                 snum = -1;
2686         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2687                         !get_printer_snum(p, handle, &snum, NULL) )
2688                 return WERR_BADFID;
2689
2690         if (!interpret_string_addr(&client_ss, p->client_address,
2691                                    AI_NUMERICHOST)) {
2692                 return WERR_SERVER_UNAVAILABLE;
2693         }
2694
2695         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2696                                         Printer->notify.printerlocal, 1,
2697                                         &Printer->notify.client_hnd, &client_ss))
2698                 return WERR_SERVER_UNAVAILABLE;
2699
2700         Printer->notify.client_connected=True;
2701
2702         return WERR_OK;
2703 }
2704
2705 /*******************************************************************
2706  * fill a notify_info_data with the servername
2707  ********************************************************************/
2708
2709 void spoolss_notify_server_name(int snum,
2710                                        SPOOL_NOTIFY_INFO_DATA *data,
2711                                        print_queue_struct *queue,
2712                                        NT_PRINTER_INFO_LEVEL *printer,
2713                                        TALLOC_CTX *mem_ctx)
2714 {
2715         smb_ucs2_t *temp = NULL;
2716         uint32 len;
2717
2718         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2719         if (len == (uint32)-1) {
2720                 len = 0;
2721         }
2722
2723         data->notify_data.data.length = len;
2724         if (len) {
2725                 data->notify_data.data.string = (uint16 *)temp;
2726         } else {
2727                 data->notify_data.data.string = NULL;
2728         }
2729 }
2730
2731 /*******************************************************************
2732  * fill a notify_info_data with the printername (not including the servername).
2733  ********************************************************************/
2734
2735 void spoolss_notify_printer_name(int snum,
2736                                         SPOOL_NOTIFY_INFO_DATA *data,
2737                                         print_queue_struct *queue,
2738                                         NT_PRINTER_INFO_LEVEL *printer,
2739                                         TALLOC_CTX *mem_ctx)
2740 {
2741         smb_ucs2_t *temp = NULL;
2742         uint32 len;
2743
2744         /* the notify name should not contain the \\server\ part */
2745         char *p = strrchr(printer->info_2->printername, '\\');
2746
2747         if (!p) {
2748                 p = printer->info_2->printername;
2749         } else {
2750                 p++;
2751         }
2752
2753         len = rpcstr_push_talloc(mem_ctx, &temp, p);
2754         if (len == (uint32)-1) {
2755                 len = 0;
2756         }
2757
2758         data->notify_data.data.length = len;
2759         if (len) {
2760                 data->notify_data.data.string = (uint16 *)temp;
2761         } else {
2762                 data->notify_data.data.string = NULL;
2763         }
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the servicename
2768  ********************************************************************/
2769
2770 void spoolss_notify_share_name(int snum,
2771                                       SPOOL_NOTIFY_INFO_DATA *data,
2772                                       print_queue_struct *queue,
2773                                       NT_PRINTER_INFO_LEVEL *printer,
2774                                       TALLOC_CTX *mem_ctx)
2775 {
2776         smb_ucs2_t *temp = NULL;
2777         uint32 len;
2778
2779         len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2780         if (len == (uint32)-1) {
2781                 len = 0;
2782         }
2783
2784         data->notify_data.data.length = len;
2785         if (len) {
2786                 data->notify_data.data.string = (uint16 *)temp;
2787         } else {
2788                 data->notify_data.data.string = NULL;
2789         }
2790
2791 }
2792
2793 /*******************************************************************
2794  * fill a notify_info_data with the port name
2795  ********************************************************************/
2796
2797 void spoolss_notify_port_name(int snum,
2798                                      SPOOL_NOTIFY_INFO_DATA *data,
2799                                      print_queue_struct *queue,
2800                                      NT_PRINTER_INFO_LEVEL *printer,
2801                                      TALLOC_CTX *mem_ctx)
2802 {
2803         smb_ucs2_t *temp = NULL;
2804         uint32 len;
2805
2806         /* even if it's strange, that's consistant in all the code */
2807
2808         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2809         if (len == (uint32)-1) {
2810                 len = 0;
2811         }
2812
2813         data->notify_data.data.length = len;
2814         if (len) {
2815                 data->notify_data.data.string = (uint16 *)temp;
2816         } else {
2817                 data->notify_data.data.string = NULL;
2818         }
2819 }
2820
2821 /*******************************************************************
2822  * fill a notify_info_data with the printername
2823  * but it doesn't exist, have to see what to do
2824  ********************************************************************/
2825
2826 void spoolss_notify_driver_name(int snum,
2827                                        SPOOL_NOTIFY_INFO_DATA *data,
2828                                        print_queue_struct *queue,
2829                                        NT_PRINTER_INFO_LEVEL *printer,
2830                                        TALLOC_CTX *mem_ctx)
2831 {
2832         smb_ucs2_t *temp = NULL;
2833         uint32 len;
2834
2835         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2836         if (len == (uint32)-1) {
2837                 len = 0;
2838         }
2839
2840         data->notify_data.data.length = len;
2841         if (len) {
2842                 data->notify_data.data.string = (uint16 *)temp;
2843         } else {
2844                 data->notify_data.data.string = NULL;
2845         }
2846 }
2847
2848 /*******************************************************************
2849  * fill a notify_info_data with the comment
2850  ********************************************************************/
2851
2852 void spoolss_notify_comment(int snum,
2853                                    SPOOL_NOTIFY_INFO_DATA *data,
2854                                    print_queue_struct *queue,
2855                                    NT_PRINTER_INFO_LEVEL *printer,
2856                                    TALLOC_CTX *mem_ctx)
2857 {
2858         smb_ucs2_t *temp = NULL;
2859         uint32 len;
2860
2861         if (*printer->info_2->comment == '\0')
2862                 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2863         else
2864                 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2865
2866         if (len == (uint32)-1) {
2867                 len = 0;
2868         }
2869         data->notify_data.data.length = len;
2870         if (len) {
2871                 data->notify_data.data.string = (uint16 *)temp;
2872         } else {
2873                 data->notify_data.data.string = NULL;
2874         }
2875 }
2876
2877 /*******************************************************************
2878  * fill a notify_info_data with the comment
2879  * location = "Room 1, floor 2, building 3"
2880  ********************************************************************/
2881
2882 void spoolss_notify_location(int snum,
2883                                     SPOOL_NOTIFY_INFO_DATA *data,
2884                                     print_queue_struct *queue,
2885                                     NT_PRINTER_INFO_LEVEL *printer,
2886                                     TALLOC_CTX *mem_ctx)
2887 {
2888         smb_ucs2_t *temp = NULL;
2889         uint32 len;
2890
2891         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2892         if (len == (uint32)-1) {
2893                 len = 0;
2894         }
2895
2896         data->notify_data.data.length = len;
2897         if (len) {
2898                 data->notify_data.data.string = (uint16 *)temp;
2899         } else {
2900                 data->notify_data.data.string = NULL;
2901         }
2902 }
2903
2904 /*******************************************************************
2905  * fill a notify_info_data with the device mode
2906  * jfm:xxxx don't to it for know but that's a real problem !!!
2907  ********************************************************************/
2908
2909 static void spoolss_notify_devmode(int snum,
2910                                    SPOOL_NOTIFY_INFO_DATA *data,
2911                                    print_queue_struct *queue,
2912                                    NT_PRINTER_INFO_LEVEL *printer,
2913                                    TALLOC_CTX *mem_ctx)
2914 {
2915         /* for a dummy implementation we have to zero the fields */
2916         data->notify_data.data.length = 0;
2917         data->notify_data.data.string = NULL;
2918 }
2919
2920 /*******************************************************************
2921  * fill a notify_info_data with the separator file name
2922  ********************************************************************/
2923
2924 void spoolss_notify_sepfile(int snum,
2925                                    SPOOL_NOTIFY_INFO_DATA *data,
2926                                    print_queue_struct *queue,
2927                                    NT_PRINTER_INFO_LEVEL *printer,
2928                                    TALLOC_CTX *mem_ctx)
2929 {
2930         smb_ucs2_t *temp = NULL;
2931         uint32 len;
2932
2933         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2934         if (len == (uint32)-1) {
2935                 len = 0;
2936         }
2937
2938         data->notify_data.data.length = len;
2939         if (len) {
2940                 data->notify_data.data.string = (uint16 *)temp;
2941         } else {
2942                 data->notify_data.data.string = NULL;
2943         }
2944 }
2945
2946 /*******************************************************************
2947  * fill a notify_info_data with the print processor
2948  * jfm:xxxx return always winprint to indicate we don't do anything to it
2949  ********************************************************************/
2950
2951 void spoolss_notify_print_processor(int snum,
2952                                            SPOOL_NOTIFY_INFO_DATA *data,
2953                                            print_queue_struct *queue,
2954                                            NT_PRINTER_INFO_LEVEL *printer,
2955                                            TALLOC_CTX *mem_ctx)
2956 {
2957         smb_ucs2_t *temp = NULL;
2958         uint32 len;
2959
2960         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2961         if (len == (uint32)-1) {
2962                 len = 0;
2963         }
2964
2965         data->notify_data.data.length = len;
2966         if (len) {
2967                 data->notify_data.data.string = (uint16 *)temp;
2968         } else {
2969                 data->notify_data.data.string = NULL;
2970         }
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with the print processor options
2975  * jfm:xxxx send an empty string
2976  ********************************************************************/
2977
2978 void spoolss_notify_parameters(int snum,
2979                                       SPOOL_NOTIFY_INFO_DATA *data,
2980                                       print_queue_struct *queue,
2981                                       NT_PRINTER_INFO_LEVEL *printer,
2982                                       TALLOC_CTX *mem_ctx)
2983 {
2984         smb_ucs2_t *temp = NULL;
2985         uint32 len;
2986
2987         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
2988         if (len == (uint32)-1) {
2989                 len = 0;
2990         }
2991
2992         data->notify_data.data.length = len;
2993         if (len) {
2994                 data->notify_data.data.string = (uint16 *)temp;
2995         } else {
2996                 data->notify_data.data.string = NULL;
2997         }
2998 }
2999
3000 /*******************************************************************
3001  * fill a notify_info_data with the data type
3002  * jfm:xxxx always send RAW as data type
3003  ********************************************************************/
3004
3005 void spoolss_notify_datatype(int snum,
3006                                     SPOOL_NOTIFY_INFO_DATA *data,
3007                                     print_queue_struct *queue,
3008                                     NT_PRINTER_INFO_LEVEL *printer,
3009                                     TALLOC_CTX *mem_ctx)
3010 {
3011         smb_ucs2_t *temp = NULL;
3012         uint32 len;
3013
3014         len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3015         if (len == (uint32)-1) {
3016                 len = 0;
3017         }
3018
3019         data->notify_data.data.length = len;
3020         if (len) {
3021                 data->notify_data.data.string = (uint16 *)temp;
3022         } else {
3023                 data->notify_data.data.string = NULL;
3024         }
3025 }
3026
3027 /*******************************************************************
3028  * fill a notify_info_data with the security descriptor
3029  * jfm:xxxx send an null pointer to say no security desc
3030  * have to implement security before !
3031  ********************************************************************/
3032
3033 static void spoolss_notify_security_desc(int snum,
3034                                          SPOOL_NOTIFY_INFO_DATA *data,
3035                                          print_queue_struct *queue,
3036                                          NT_PRINTER_INFO_LEVEL *printer,
3037                                          TALLOC_CTX *mem_ctx)
3038 {
3039         data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3040         data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3041 }
3042
3043 /*******************************************************************
3044  * fill a notify_info_data with the attributes
3045  * jfm:xxxx a samba printer is always shared
3046  ********************************************************************/
3047
3048 void spoolss_notify_attributes(int snum,
3049                                       SPOOL_NOTIFY_INFO_DATA *data,
3050                                       print_queue_struct *queue,
3051                                       NT_PRINTER_INFO_LEVEL *printer,
3052                                       TALLOC_CTX *mem_ctx)
3053 {
3054         data->notify_data.value[0] = printer->info_2->attributes;
3055         data->notify_data.value[1] = 0;
3056 }
3057
3058 /*******************************************************************
3059  * fill a notify_info_data with the priority
3060  ********************************************************************/
3061
3062 static void spoolss_notify_priority(int snum,
3063                                     SPOOL_NOTIFY_INFO_DATA *data,
3064                                     print_queue_struct *queue,
3065                                     NT_PRINTER_INFO_LEVEL *printer,
3066                                     TALLOC_CTX *mem_ctx)
3067 {
3068         data->notify_data.value[0] = printer->info_2->priority;
3069         data->notify_data.value[1] = 0;
3070 }
3071
3072 /*******************************************************************
3073  * fill a notify_info_data with the default priority
3074  ********************************************************************/
3075
3076 static void spoolss_notify_default_priority(int snum,
3077                                             SPOOL_NOTIFY_INFO_DATA *data,
3078                                             print_queue_struct *queue,
3079                                             NT_PRINTER_INFO_LEVEL *printer,
3080                                             TALLOC_CTX *mem_ctx)
3081 {
3082         data->notify_data.value[0] = printer->info_2->default_priority;
3083         data->notify_data.value[1] = 0;
3084 }
3085
3086 /*******************************************************************
3087  * fill a notify_info_data with the start time
3088  ********************************************************************/
3089
3090 static void spoolss_notify_start_time(int snum,
3091                                       SPOOL_NOTIFY_INFO_DATA *data,
3092                                       print_queue_struct *queue,
3093                                       NT_PRINTER_INFO_LEVEL *printer,
3094                                       TALLOC_CTX *mem_ctx)
3095 {
3096         data->notify_data.value[0] = printer->info_2->starttime;
3097         data->notify_data.value[1] = 0;
3098 }
3099
3100 /*******************************************************************
3101  * fill a notify_info_data with the until time
3102  ********************************************************************/
3103
3104 static void spoolss_notify_until_time(int snum,
3105                                       SPOOL_NOTIFY_INFO_DATA *data,
3106                                       print_queue_struct *queue,
3107                                       NT_PRINTER_INFO_LEVEL *printer,
3108                                       TALLOC_CTX *mem_ctx)
3109 {
3110         data->notify_data.value[0] = printer->info_2->untiltime;
3111         data->notify_data.value[1] = 0;
3112 }
3113
3114 /*******************************************************************
3115  * fill a notify_info_data with the status
3116  ********************************************************************/
3117
3118 static void spoolss_notify_status(int snum,
3119                                   SPOOL_NOTIFY_INFO_DATA *data,
3120                                   print_queue_struct *queue,
3121                                   NT_PRINTER_INFO_LEVEL *printer,
3122                                   TALLOC_CTX *mem_ctx)
3123 {
3124         print_status_struct status;
3125
3126         print_queue_length(snum, &status);
3127         data->notify_data.value[0]=(uint32) status.status;
3128         data->notify_data.value[1] = 0;
3129 }
3130
3131 /*******************************************************************
3132  * fill a notify_info_data with the number of jobs queued
3133  ********************************************************************/
3134
3135 void spoolss_notify_cjobs(int snum,
3136                                  SPOOL_NOTIFY_INFO_DATA *data,
3137                                  print_queue_struct *queue,
3138                                  NT_PRINTER_INFO_LEVEL *printer,
3139                                  TALLOC_CTX *mem_ctx)
3140 {
3141         data->notify_data.value[0] = print_queue_length(snum, NULL);
3142         data->notify_data.value[1] = 0;
3143 }
3144
3145 /*******************************************************************
3146  * fill a notify_info_data with the average ppm
3147  ********************************************************************/
3148
3149 static void spoolss_notify_average_ppm(int snum,
3150                                        SPOOL_NOTIFY_INFO_DATA *data,
3151                                        print_queue_struct *queue,
3152                                        NT_PRINTER_INFO_LEVEL *printer,
3153                                        TALLOC_CTX *mem_ctx)
3154 {
3155         /* always respond 8 pages per minutes */
3156         /* a little hard ! */
3157         data->notify_data.value[0] = printer->info_2->averageppm;
3158         data->notify_data.value[1] = 0;
3159 }
3160
3161 /*******************************************************************
3162  * fill a notify_info_data with username
3163  ********************************************************************/
3164
3165 static void spoolss_notify_username(int snum,
3166                                     SPOOL_NOTIFY_INFO_DATA *data,
3167                                     print_queue_struct *queue,
3168                                     NT_PRINTER_INFO_LEVEL *printer,
3169                                     TALLOC_CTX *mem_ctx)
3170 {
3171         smb_ucs2_t *temp = NULL;
3172         uint32 len;
3173
3174         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3175         if (len == (uint32)-1) {
3176                 len = 0;
3177         }
3178
3179         data->notify_data.data.length = len;
3180         if (len) {
3181                 data->notify_data.data.string = (uint16 *)temp;
3182         } else {
3183                 data->notify_data.data.string = NULL;
3184         }
3185 }
3186
3187 /*******************************************************************
3188  * fill a notify_info_data with job status
3189  ********************************************************************/
3190
3191 static void spoolss_notify_job_status(int snum,
3192                                       SPOOL_NOTIFY_INFO_DATA *data,
3193                                       print_queue_struct *queue,
3194                                       NT_PRINTER_INFO_LEVEL *printer,
3195                                       TALLOC_CTX *mem_ctx)
3196 {
3197         data->notify_data.value[0]=nt_printj_status(queue->status);
3198         data->notify_data.value[1] = 0;
3199 }
3200
3201 /*******************************************************************
3202  * fill a notify_info_data with job name
3203  ********************************************************************/
3204
3205 static void spoolss_notify_job_name(int snum,
3206                                     SPOOL_NOTIFY_INFO_DATA *data,
3207                                     print_queue_struct *queue,
3208                                     NT_PRINTER_INFO_LEVEL *printer,
3209                                     TALLOC_CTX *mem_ctx)
3210 {
3211         smb_ucs2_t *temp = NULL;
3212         uint32 len;
3213
3214         len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3215         if (len == (uint32)-1) {
3216                 len = 0;
3217         }
3218
3219         data->notify_data.data.length = len;
3220         if (len) {
3221                 data->notify_data.data.string = (uint16 *)temp;
3222         } else {
3223                 data->notify_data.data.string = NULL;
3224         }
3225 }
3226
3227 /*******************************************************************
3228  * fill a notify_info_data with job status
3229  ********************************************************************/
3230
3231 static void spoolss_notify_job_status_string(int snum,
3232                                              SPOOL_NOTIFY_INFO_DATA *data,
3233                                              print_queue_struct *queue,
3234                                              NT_PRINTER_INFO_LEVEL *printer,
3235                                              TALLOC_CTX *mem_ctx)
3236 {
3237         /*
3238          * Now we're returning job status codes we just return a "" here. JRA.
3239          */
3240
3241         const char *p = "";
3242         smb_ucs2_t *temp = NULL;
3243         uint32 len;
3244
3245 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3246         p = "unknown";
3247
3248         switch (queue->status) {
3249         case LPQ_QUEUED:
3250                 p = "Queued";
3251                 break;
3252         case LPQ_PAUSED:
3253                 p = "";    /* NT provides the paused string */
3254                 break;
3255         case LPQ_SPOOLING:
3256                 p = "Spooling";
3257                 break;
3258         case LPQ_PRINTING:
3259                 p = "Printing";
3260                 break;
3261         }
3262 #endif /* NO LONGER NEEDED. */
3263
3264         len = rpcstr_push_talloc(mem_ctx, &temp, p);
3265         if (len == (uint32)-1) {
3266                 len = 0;
3267         }
3268
3269         data->notify_data.data.length = len;
3270         if (len) {
3271                 data->notify_data.data.string = (uint16 *)temp;
3272         } else {
3273                 data->notify_data.data.string = NULL;
3274         }
3275 }
3276
3277 /*******************************************************************
3278  * fill a notify_info_data with job time
3279  ********************************************************************/
3280
3281 static void spoolss_notify_job_time(int snum,
3282                                     SPOOL_NOTIFY_INFO_DATA *data,
3283                                     print_queue_struct *queue,
3284                                     NT_PRINTER_INFO_LEVEL *printer,
3285                                     TALLOC_CTX *mem_ctx)
3286 {
3287         data->notify_data.value[0]=0x0;
3288         data->notify_data.value[1]=0;
3289 }
3290
3291 /*******************************************************************
3292  * fill a notify_info_data with job size
3293  ********************************************************************/
3294
3295 static void spoolss_notify_job_size(int snum,
3296                                     SPOOL_NOTIFY_INFO_DATA *data,
3297                                     print_queue_struct *queue,
3298                                     NT_PRINTER_INFO_LEVEL *printer,
3299                                     TALLOC_CTX *mem_ctx)
3300 {
3301         data->notify_data.value[0]=queue->size;
3302         data->notify_data.value[1]=0;
3303 }
3304
3305 /*******************************************************************
3306  * fill a notify_info_data with page info
3307  ********************************************************************/
3308 static void spoolss_notify_total_pages(int snum,
3309                                 SPOOL_NOTIFY_INFO_DATA *data,
3310                                 print_queue_struct *queue,
3311                                 NT_PRINTER_INFO_LEVEL *printer,
3312                                 TALLOC_CTX *mem_ctx)
3313 {
3314         data->notify_data.value[0]=queue->page_count;
3315         data->notify_data.value[1]=0;
3316 }
3317
3318 /*******************************************************************
3319  * fill a notify_info_data with pages printed info.
3320  ********************************************************************/
3321 static void spoolss_notify_pages_printed(int snum,
3322                                 SPOOL_NOTIFY_INFO_DATA *data,
3323                                 print_queue_struct *queue,
3324                                 NT_PRINTER_INFO_LEVEL *printer,
3325                                 TALLOC_CTX *mem_ctx)
3326 {
3327         data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
3328         data->notify_data.value[1]=0;
3329 }
3330
3331 /*******************************************************************
3332  Fill a notify_info_data with job position.
3333  ********************************************************************/
3334
3335 static void spoolss_notify_job_position(int snum,
3336                                         SPOOL_NOTIFY_INFO_DATA *data,
3337                                         print_queue_struct *queue,
3338                                         NT_PRINTER_INFO_LEVEL *printer,
3339                                         TALLOC_CTX *mem_ctx)
3340 {
3341         data->notify_data.value[0]=queue->job;
3342         data->notify_data.value[1]=0;
3343 }
3344
3345 /*******************************************************************
3346  Fill a notify_info_data with submitted time.
3347  ********************************************************************/
3348
3349 static void spoolss_notify_submitted_time(int snum,
3350                                           SPOOL_NOTIFY_INFO_DATA *data,
3351                                           print_queue_struct *queue,
3352                                           NT_PRINTER_INFO_LEVEL *printer,
3353                                           TALLOC_CTX *mem_ctx)
3354 {
3355         struct tm *t;
3356         uint32 len;
3357         SYSTEMTIME st;
3358         char *p;
3359
3360         t=gmtime(&queue->time);
3361
3362         len = sizeof(SYSTEMTIME);
3363
3364         data->notify_data.data.length = len;
3365         data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3366
3367         if (!data->notify_data.data.string) {
3368                 data->notify_data.data.length = 0;
3369                 return;
3370         }
3371
3372         make_systemtime(&st, t);
3373
3374         /*
3375          * Systemtime must be linearized as a set of UINT16's.
3376          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3377          */
3378
3379         p = (char *)data->notify_data.data.string;
3380         SSVAL(p, 0, st.year);
3381         SSVAL(p, 2, st.month);
3382         SSVAL(p, 4, st.dayofweek);
3383         SSVAL(p, 6, st.day);
3384         SSVAL(p, 8, st.hour);
3385         SSVAL(p, 10, st.minute);
3386         SSVAL(p, 12, st.second);
3387         SSVAL(p, 14, st.milliseconds);
3388 }
3389
3390 struct s_notify_info_data_table
3391 {
3392         uint16 type;
3393         uint16 field;
3394         const char *name;
3395         uint32 size;
3396         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3397                     print_queue_struct *queue,
3398                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3399 };
3400
3401 /* A table describing the various print notification constants and
3402    whether the notification data is a pointer to a variable sized
3403    buffer, a one value uint32 or a two value uint32. */
3404
3405 static const struct s_notify_info_data_table notify_info_data_table[] =
3406 {
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_STRING,   spoolss_notify_server_name },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_STRING,   spoolss_notify_printer_name },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_STRING,   spoolss_notify_share_name },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_STRING,   spoolss_notify_port_name },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_STRING,   spoolss_notify_driver_name },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_STRING,   spoolss_notify_comment },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_STRING,   spoolss_notify_location },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_POINTER,   spoolss_notify_devmode },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_STRING,   spoolss_notify_sepfile },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_STRING,   spoolss_notify_print_processor },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_STRING,   spoolss_notify_parameters },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_STRING,   spoolss_notify_datatype },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC,   spoolss_notify_security_desc },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_ONE_VALUE, spoolss_notify_priority },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_ONE_VALUE, spoolss_notify_status },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_POINTER,   NULL },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_POINTER,   NULL },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_POINTER,   NULL },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_POINTER,   NULL },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_POINTER,   NULL },
3433 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_STRING,   spoolss_notify_printer_name },
3434 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_STRING,   spoolss_notify_server_name },
3435 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_STRING,   spoolss_notify_port_name },
3436 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_STRING,   spoolss_notify_username },
3437 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_STRING,   spoolss_notify_username },
3438 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_STRING,   spoolss_notify_datatype },
3439 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_STRING,   spoolss_notify_print_processor },
3440 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_STRING,   spoolss_notify_parameters },
3441 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_STRING,   spoolss_notify_driver_name },
3442 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_POINTER,   spoolss_notify_devmode },
3443 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3444 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_STRING,   spoolss_notify_job_status_string },
3445 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_POINTER,   NULL },
3446 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_STRING,   spoolss_notify_job_name },
3447 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_ONE_VALUE, spoolss_notify_priority },
3448 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3449 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_POINTER,   spoolss_notify_submitted_time },
3450 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3451 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3452 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3453 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3454 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3455 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3456 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3457 };
3458
3459 /*******************************************************************
3460  Return the size of info_data structure.
3461 ********************************************************************/
3462
3463 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3464 {
3465         int i=0;
3466
3467         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3468                 if ( (notify_info_data_table[i].type == type)
3469                         && (notify_info_data_table[i].field == field) ) {
3470                         switch(notify_info_data_table[i].size) {
3471                                 case NOTIFY_ONE_VALUE:
3472                                 case NOTIFY_TWO_VALUE:
3473                                         return 1;
3474                                 case NOTIFY_STRING:
3475                                         return 2;
3476
3477                                 /* The only pointer notify data I have seen on
3478                                    the wire is the submitted time and this has
3479                                    the notify size set to 4. -tpot */
3480
3481                                 case NOTIFY_POINTER:
3482                                         return 4;
3483
3484                                 case NOTIFY_SECDESC:
3485                                         return 5;
3486                         }
3487                 }
3488         }
3489
3490         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3491
3492         return 0;
3493 }
3494
3495 /*******************************************************************
3496  Return the type of notify_info_data.
3497 ********************************************************************/
3498
3499 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3500 {
3501         uint32 i=0;
3502
3503         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3504                 if (notify_info_data_table[i].type == type &&
3505                     notify_info_data_table[i].field == field)
3506                         return notify_info_data_table[i].size;
3507         }
3508
3509         return 0;
3510 }
3511
3512 /****************************************************************************
3513 ****************************************************************************/
3514
3515 static bool search_notify(uint16 type, uint16 field, int *value)
3516 {
3517         int i;
3518
3519         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3520                 if (notify_info_data_table[i].type == type &&
3521                     notify_info_data_table[i].field == field &&
3522                     notify_info_data_table[i].fn != NULL) {
3523                         *value = i;
3524                         return True;
3525                 }
3526         }
3527
3528         return False;
3529 }
3530
3531 /****************************************************************************
3532 ****************************************************************************/
3533
3534 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3535 {
3536         info_data->type     = type;
3537         info_data->field    = field;
3538         info_data->reserved = 0;
3539
3540         info_data->size     = size_of_notify_info_data(type, field);
3541         info_data->enc_type = type_of_notify_info_data(type, field);
3542
3543         info_data->id = id;
3544 }
3545
3546 /*******************************************************************
3547  *
3548  * fill a notify_info struct with info asked
3549  *
3550  ********************************************************************/
3551
3552 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3553                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3554                                           *option_type, uint32 id,
3555                                           TALLOC_CTX *mem_ctx)
3556 {
3557         int field_num,j;
3558         uint16 type;
3559         uint16 field;
3560
3561         SPOOL_NOTIFY_INFO_DATA *current_data;
3562         NT_PRINTER_INFO_LEVEL *printer = NULL;
3563         print_queue_struct *queue=NULL;
3564
3565         type=option_type->type;
3566
3567         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3568                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3569                 option_type->count, lp_servicename(snum)));
3570
3571         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3572                 return False;
3573
3574         for(field_num=0; field_num<option_type->count; field_num++) {
3575                 field = option_type->fields[field_num];
3576
3577                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3578
3579                 if (!search_notify(type, field, &j) )
3580                         continue;
3581
3582                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3583                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3584                         free_a_printer(&printer, 2);
3585                         return False;
3586                 }
3587
3588                 current_data = &info->data[info->count];
3589
3590                 construct_info_data(current_data, type, field, id);
3591
3592                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3593                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3594
3595                 notify_info_data_table[j].fn(snum, current_data, queue,
3596                                              printer, mem_ctx);
3597
3598                 info->count++;
3599         }
3600
3601         free_a_printer(&printer, 2);
3602         return True;
3603 }
3604
3605 /*******************************************************************
3606  *
3607  * fill a notify_info struct with info asked
3608  *
3609  ********************************************************************/
3610
3611 static bool construct_notify_jobs_info(print_queue_struct *queue,
3612                                        SPOOL_NOTIFY_INFO *info,
3613                                        NT_PRINTER_INFO_LEVEL *printer,
3614                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3615                                        *option_type, uint32 id,
3616                                        TALLOC_CTX *mem_ctx)
3617 {
3618         int field_num,j;
3619         uint16 type;
3620         uint16 field;
3621
3622         SPOOL_NOTIFY_INFO_DATA *current_data;
3623
3624         DEBUG(4,("construct_notify_jobs_info\n"));
3625
3626         type = option_type->type;
3627
3628         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3629                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3630                 option_type->count));
3631
3632         for(field_num=0; field_num<option_type->count; field_num++) {
3633                 field = option_type->fields[field_num];
3634
3635                 if (!search_notify(type, field, &j) )
3636                         continue;
3637
3638                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3639                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3640                         return False;
3641                 }
3642
3643                 current_data=&(info->data[info->count]);
3644
3645                 construct_info_data(current_data, type, field, id);
3646                 notify_info_data_table[j].fn(snum, current_data, queue,
3647                                              printer, mem_ctx);
3648                 info->count++;
3649         }
3650
3651         return True;
3652 }
3653
3654 /*
3655  * JFM: The enumeration is not that simple, it's even non obvious.
3656  *
3657  * let's take an example: I want to monitor the PRINTER SERVER for
3658  * the printer's name and the number of jobs currently queued.
3659  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3660  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3661  *
3662  * I have 3 printers on the back of my server.
3663  *
3664  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3665  * structures.
3666  *   Number     Data                    Id
3667  *      1       printer 1 name          1
3668  *      2       printer 1 cjob          1
3669  *      3       printer 2 name          2
3670  *      4       printer 2 cjob          2
3671  *      5       printer 3 name          3
3672  *      6       printer 3 name          3
3673  *
3674  * that's the print server case, the printer case is even worse.
3675  */
3676
3677 /*******************************************************************
3678  *
3679  * enumerate all printers on the printserver
3680  * fill a notify_info struct with info asked
3681  *
3682  ********************************************************************/
3683
3684 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3685                                       SPOOL_NOTIFY_INFO *info,
3686                                       TALLOC_CTX *mem_ctx)
3687 {
3688         int snum;
3689         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3690         int n_services=lp_numservices();
3691         int i;
3692         SPOOL_NOTIFY_OPTION *option;
3693         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3694
3695         DEBUG(4,("printserver_notify_info\n"));
3696
3697         if (!Printer)
3698                 return WERR_BADFID;
3699
3700         option=Printer->notify.option;
3701         info->version=2;
3702         info->data=NULL;
3703         info->count=0;
3704
3705         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3706            sending a ffpcn() request first */
3707
3708         if ( !option )
3709                 return WERR_BADFID;
3710
3711         for (i=0; i<option->count; i++) {
3712                 option_type=&(option->ctr.type[i]);
3713
3714                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3715                         continue;
3716
3717                 for (snum=0; snum<n_services; snum++)
3718                 {
3719                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3720                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3721                 }
3722         }
3723
3724 #if 0
3725         /*
3726          * Debugging information, don't delete.
3727          */
3728
3729         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3730         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3731         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3732
3733         for (i=0; i<info->count; i++) {
3734                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3735                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3736                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3737         }
3738 #endif
3739
3740         return WERR_OK;
3741 }
3742
3743 /*******************************************************************
3744  *
3745  * fill a notify_info struct with info asked
3746  *
3747  ********************************************************************/
3748
3749 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3750                                   TALLOC_CTX *mem_ctx)
3751 {
3752         int snum;
3753         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3754         int i;
3755         uint32 id;
3756         SPOOL_NOTIFY_OPTION *option;
3757         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3758         int count,j;
3759         print_queue_struct *queue=NULL;
3760         print_status_struct status;
3761
3762         DEBUG(4,("printer_notify_info\n"));
3763
3764         if (!Printer)
3765                 return WERR_BADFID;
3766
3767         option=Printer->notify.option;
3768         id = 0x0;
3769         info->version=2;
3770         info->data=NULL;
3771         info->count=0;
3772
3773         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3774            sending a ffpcn() request first */
3775
3776         if ( !option )
3777                 return WERR_BADFID;
3778
3779         get_printer_snum(p, hnd, &snum, NULL);
3780
3781         for (i=0; i<option->count; i++) {
3782                 option_type=&option->ctr.type[i];
3783
3784                 switch ( option_type->type ) {
3785                 case PRINTER_NOTIFY_TYPE:
3786                         if(construct_notify_printer_info(Printer, info, snum,
3787                                                          option_type, id,
3788                                                          mem_ctx))
3789                                 id--;
3790                         break;
3791
3792                 case JOB_NOTIFY_TYPE: {
3793                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3794
3795                         count = print_queue_status(snum, &queue, &status);
3796
3797                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3798                                 goto done;
3799
3800                         for (j=0; j<count; j++) {
3801                                 construct_notify_jobs_info(&queue[j], info,
3802                                                            printer, snum,
3803                                                            option_type,
3804                                                            queue[j].job,
3805                                                            mem_ctx);
3806                         }
3807
3808                         free_a_printer(&printer, 2);
3809
3810                 done:
3811                         SAFE_FREE(queue);
3812                         break;
3813                 }
3814                 }
3815         }
3816
3817         /*
3818          * Debugging information, don't delete.
3819          */
3820         /*
3821         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3822         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3823         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3824
3825         for (i=0; i<info->count; i++) {
3826                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3827                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3828                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3829         }
3830         */
3831         return WERR_OK;
3832 }
3833
3834 /********************************************************************
3835  * spoolss_rfnpcnex
3836  ********************************************************************/
3837
3838 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3839 {
3840         POLICY_HND *handle = &q_u->handle;
3841         SPOOL_NOTIFY_INFO *info = &r_u->info;
3842
3843         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3844         WERROR result = WERR_BADFID;
3845
3846         /* we always have a NOTIFY_INFO struct */
3847         r_u->info_ptr=0x1;
3848
3849         if (!Printer) {
3850                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3851                          OUR_HANDLE(handle)));
3852                 goto done;
3853         }
3854
3855         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3856
3857         /*
3858          *      We are now using the change value, and
3859          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3860          *      I don't have a global notification system, I'm sending back all the
3861          *      informations even when _NOTHING_ has changed.
3862          */
3863
3864         /* We need to keep track of the change value to send back in
3865            RRPCN replies otherwise our updates are ignored. */
3866
3867         Printer->notify.fnpcn = True;
3868
3869         if (Printer->notify.client_connected) {
3870                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3871                 Printer->notify.change = q_u->change;
3872         }
3873
3874         /* just ignore the SPOOL_NOTIFY_OPTION */
3875
3876         switch (Printer->printer_type) {
3877                 case SPLHND_SERVER:
3878                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3879                         break;
3880
3881                 case SPLHND_PRINTER:
3882                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3883                         break;
3884         }
3885
3886         Printer->notify.fnpcn = False;
3887
3888 done:
3889         return result;
3890 }
3891
3892 /********************************************************************
3893  * construct_printer_info_0
3894  * fill a printer_info_0 struct
3895  ********************************************************************/
3896
3897 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3898 {
3899         char *chaine = NULL;
3900         int count;
3901         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3902         counter_printer_0 *session_counter;
3903         uint32 global_counter;
3904         struct tm *t;
3905         time_t setuptime;
3906         print_status_struct status;
3907         TALLOC_CTX *ctx = talloc_tos();
3908
3909         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3910                 return False;
3911
3912         init_unistr(&printer->printername, ntprinter->info_2->printername);
3913
3914         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3915         if (!chaine) {
3916                 free_a_printer(&ntprinter,2);
3917                 return false;
3918         }
3919
3920         count = print_queue_length(snum, &status);
3921
3922         /* check if we already have a counter for this printer */
3923         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3924                 if (session_counter->snum == snum)
3925                         break;
3926         }
3927
3928         init_unistr(&printer->servername, chaine);
3929
3930         /* it's the first time, add it to the list */
3931         if (session_counter==NULL) {
3932                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3933                         free_a_printer(&ntprinter, 2);
3934                         return False;
3935                 }
3936                 ZERO_STRUCTP(session_counter);
3937                 session_counter->snum=snum;
3938                 session_counter->counter=0;
3939                 DLIST_ADD(counter_list, session_counter);
3940         }
3941
3942         /* increment it */
3943         session_counter->counter++;
3944
3945         /* JFM:
3946          * the global_counter should be stored in a TDB as it's common to all the clients
3947          * and should be zeroed on samba startup
3948          */
3949         global_counter=session_counter->counter;
3950         printer->cjobs = count;
3951         printer->total_jobs = 0;
3952         printer->total_bytes = 0;
3953
3954         setuptime = (time_t)ntprinter->info_2->setuptime;
3955         t=gmtime(&setuptime);
3956
3957         printer->year = t->tm_year+1900;
3958         printer->month = t->tm_mon+1;
3959         printer->dayofweek = t->tm_wday;
3960         printer->day = t->tm_mday;
3961         printer->hour = t->tm_hour;
3962         printer->minute = t->tm_min;
3963         printer->second = t->tm_sec;
3964         printer->milliseconds = 0;
3965
3966         printer->global_counter = global_counter;
3967         printer->total_pages = 0;
3968
3969         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3970         printer->major_version = 0x0005;        /* NT 5 */
3971         printer->build_version = 0x0893;        /* build 2195 */
3972
3973         printer->unknown7 = 0x1;
3974         printer->unknown8 = 0x0;
3975         printer->unknown9 = 0x0;
3976         printer->session_counter = session_counter->counter;
3977         printer->unknown11 = 0x0;
3978         printer->printer_errors = 0x0;          /* number of print failure */
3979         printer->unknown13 = 0x0;
3980         printer->unknown14 = 0x1;
3981         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
3982         printer->unknown16 =  0x0;
3983         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3984         printer->unknown18 =  0x0;
3985         printer->status = nt_printq_status(status.status);
3986         printer->unknown20 =  0x0;
3987         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3988         printer->unknown22 = 0x0;
3989         printer->unknown23 = 0x6;               /* 6  ???*/
3990         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
3991         printer->unknown25 = 0;
3992         printer->unknown26 = 0;
3993         printer->unknown27 = 0;
3994         printer->unknown28 = 0;
3995         printer->unknown29 = 0;
3996
3997         free_a_printer(&ntprinter,2);
3998         return (True);
3999 }
4000
4001 /********************************************************************
4002  * construct_printer_info_1
4003  * fill a printer_info_1 struct
4004  ********************************************************************/
4005 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4006 {
4007         char *chaine = NULL;
4008         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4009         TALLOC_CTX *ctx = talloc_tos();
4010
4011         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4012                 return false;
4013
4014         printer->flags=flags;
4015
4016         if (*ntprinter->info_2->comment == '\0') {
4017                 init_unistr(&printer->comment, lp_comment(snum));
4018                 chaine = talloc_asprintf(ctx,
4019                                 "%s,%s,%s", ntprinter->info_2->printername,
4020                                 ntprinter->info_2->drivername, lp_comment(snum));
4021         }
4022         else {
4023                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4024                 chaine = talloc_asprintf(ctx,
4025                                 "%s,%s,%s", ntprinter->info_2->printername,
4026                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4027         }
4028
4029         if (!chaine) {
4030                 free_a_printer(&ntprinter,2);
4031                 return false;
4032         }
4033
4034         init_unistr(&printer->description, chaine);
4035         init_unistr(&printer->name, ntprinter->info_2->printername);
4036
4037         free_a_printer(&ntprinter,2);
4038
4039         return True;
4040 }
4041
4042 /****************************************************************************
4043  Free a DEVMODE struct.
4044 ****************************************************************************/
4045
4046 static void free_dev_mode(DEVICEMODE *dev)
4047 {
4048         if (dev == NULL)
4049                 return;
4050
4051         SAFE_FREE(dev->dev_private);
4052         SAFE_FREE(dev);
4053 }
4054
4055
4056 /****************************************************************************
4057  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4058  should be valid upon entry
4059 ****************************************************************************/
4060
4061 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4062 {
4063         if ( !devmode || !ntdevmode )
4064                 return False;
4065
4066         init_unistr(&devmode->devicename, ntdevmode->devicename);
4067
4068         init_unistr(&devmode->formname, ntdevmode->formname);
4069
4070         devmode->specversion      = ntdevmode->specversion;
4071         devmode->driverversion    = ntdevmode->driverversion;
4072         devmode->size             = ntdevmode->size;
4073         devmode->driverextra      = ntdevmode->driverextra;
4074         devmode->fields           = ntdevmode->fields;
4075
4076         devmode->orientation      = ntdevmode->orientation;
4077         devmode->papersize        = ntdevmode->papersize;
4078         devmode->paperlength      = ntdevmode->paperlength;
4079         devmode->paperwidth       = ntdevmode->paperwidth;
4080         devmode->scale            = ntdevmode->scale;
4081         devmode->copies           = ntdevmode->copies;
4082         devmode->defaultsource    = ntdevmode->defaultsource;
4083         devmode->printquality     = ntdevmode->printquality;
4084         devmode->color            = ntdevmode->color;
4085         devmode->duplex           = ntdevmode->duplex;
4086         devmode->yresolution      = ntdevmode->yresolution;
4087         devmode->ttoption         = ntdevmode->ttoption;
4088         devmode->collate          = ntdevmode->collate;
4089         devmode->icmmethod        = ntdevmode->icmmethod;
4090         devmode->icmintent        = ntdevmode->icmintent;
4091         devmode->mediatype        = ntdevmode->mediatype;
4092         devmode->dithertype       = ntdevmode->dithertype;
4093
4094         if (ntdevmode->nt_dev_private != NULL) {
4095                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4096                         return False;
4097         }
4098
4099         return True;
4100 }
4101
4102 /****************************************************************************
4103  Create a DEVMODE struct. Returns malloced memory.
4104 ****************************************************************************/
4105
4106 DEVICEMODE *construct_dev_mode(const char *servicename)
4107 {
4108         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4109         DEVICEMODE              *devmode = NULL;
4110
4111         DEBUG(7,("construct_dev_mode\n"));
4112
4113         DEBUGADD(8,("getting printer characteristics\n"));
4114
4115         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4116                 return NULL;
4117
4118         if ( !printer->info_2->devmode ) {
4119                 DEBUG(5, ("BONG! There was no device mode!\n"));
4120                 goto done;
4121         }
4122
4123         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4124                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4125                 goto done;
4126         }
4127
4128         ZERO_STRUCTP(devmode);
4129
4130         DEBUGADD(8,("loading DEVICEMODE\n"));
4131
4132         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4133                 free_dev_mode( devmode );
4134                 devmode = NULL;
4135         }
4136
4137 done:
4138         free_a_printer(&printer,2);
4139
4140         return devmode;
4141 }
4142
4143 /********************************************************************
4144  * construct_printer_info_2
4145  * fill a printer_info_2 struct
4146  ********************************************************************/
4147
4148 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4149 {
4150         int count;
4151         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4152
4153         print_status_struct status;
4154
4155         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4156                 return False;
4157
4158         count = print_queue_length(snum, &status);
4159
4160         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4161         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4162         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4163         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4164         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4165
4166         if (*ntprinter->info_2->comment == '\0')
4167                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4168         else
4169                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4170
4171         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4172         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4173         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4174         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4175         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4176
4177         printer->attributes = ntprinter->info_2->attributes;
4178
4179         printer->priority = ntprinter->info_2->priority;                                /* priority */
4180         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4181         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4182         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4183         printer->status = nt_printq_status(status.status);                      /* status */
4184         printer->cjobs = count;                                                 /* jobs */
4185         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4186
4187         if ( !(printer->devmode = construct_dev_mode(
4188                        lp_const_servicename(snum))) )
4189                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4190
4191         printer->secdesc = NULL;
4192
4193         if ( ntprinter->info_2->secdesc_buf
4194                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4195         {
4196                 /* don't use talloc_steal() here unless you do a deep steal of all
4197                    the SEC_DESC members */
4198
4199                 printer->secdesc = dup_sec_desc( talloc_tos(),
4200                         ntprinter->info_2->secdesc_buf->sd );
4201         }
4202
4203         free_a_printer(&ntprinter, 2);
4204
4205         return True;
4206 }
4207
4208 /********************************************************************
4209  * construct_printer_info_3
4210  * fill a printer_info_3 struct
4211  ********************************************************************/
4212
4213 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4214 {
4215         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4216         PRINTER_INFO_3 *printer = NULL;
4217
4218         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4219                 return False;
4220
4221         *pp_printer = NULL;
4222         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4223                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4224                 free_a_printer(&ntprinter, 2);
4225                 return False;
4226         }
4227
4228         ZERO_STRUCTP(printer);
4229
4230         /* These are the components of the SD we are returning. */
4231
4232         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4233                 /* don't use talloc_steal() here unless you do a deep steal of all
4234                    the SEC_DESC members */
4235
4236                 printer->secdesc = dup_sec_desc( talloc_tos(),
4237                         ntprinter->info_2->secdesc_buf->sd );
4238         }
4239
4240         free_a_printer(&ntprinter, 2);
4241
4242         *pp_printer = printer;
4243         return True;
4244 }
4245
4246 /********************************************************************
4247  * construct_printer_info_4
4248  * fill a printer_info_4 struct
4249  ********************************************************************/
4250
4251 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4252 {
4253         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4254
4255         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4256                 return False;
4257
4258         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4259         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4260         printer->attributes = ntprinter->info_2->attributes;
4261
4262         free_a_printer(&ntprinter, 2);
4263         return True;
4264 }
4265
4266 /********************************************************************
4267  * construct_printer_info_5
4268  * fill a printer_info_5 struct
4269  ********************************************************************/
4270
4271 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4272 {
4273         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4274
4275         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4276                 return False;
4277
4278         init_unistr(&printer->printername, ntprinter->info_2->printername);
4279         init_unistr(&printer->portname, ntprinter->info_2->portname);
4280         printer->attributes = ntprinter->info_2->attributes;
4281
4282         /* these two are not used by NT+ according to MSDN */
4283
4284         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4285         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4286
4287         free_a_printer(&ntprinter, 2);
4288
4289         return True;
4290 }
4291
4292 /********************************************************************
4293  * construct_printer_info_6
4294  * fill a printer_info_6 struct
4295  ********************************************************************/
4296
4297 static bool construct_printer_info_6(Printer_entry *print_hnd,
4298                                      PRINTER_INFO_6 *printer,
4299                                      int snum)
4300 {
4301         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4302         int count;
4303         print_status_struct status;
4304
4305         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4306                                          lp_const_servicename(snum))))
4307                 return False;
4308
4309         count = print_queue_length(snum, &status);
4310
4311         printer->status = nt_printq_status(status.status);
4312
4313         free_a_printer(&ntprinter, 2);
4314
4315         return True;
4316 }
4317
4318 /********************************************************************
4319  * construct_printer_info_7
4320  * fill a printer_info_7 struct
4321  ********************************************************************/
4322
4323 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4324 {
4325         char *guid_str = NULL;
4326         struct GUID guid;
4327
4328         if (is_printer_published(print_hnd, snum, &guid)) {
4329                 if (asprintf(&guid_str, "{%s}",
4330                              GUID_string(talloc_tos(), &guid)) == -1) {
4331                         return false;
4332                 }
4333                 strupper_m(guid_str);
4334                 init_unistr(&printer->guid, guid_str);
4335                 SAFE_FREE(guid_str);
4336                 printer->action = SPOOL_DS_PUBLISH;
4337         } else {
4338                 init_unistr(&printer->guid, "");
4339                 printer->action = SPOOL_DS_UNPUBLISH;
4340         }
4341
4342         return True;
4343 }
4344
4345 /********************************************************************
4346  Spoolss_enumprinters.
4347 ********************************************************************/
4348
4349 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4350 {
4351         int snum;
4352         int i;
4353         int n_services=lp_numservices();
4354         PRINTER_INFO_1 *printers=NULL;
4355         PRINTER_INFO_1 current_prt;
4356         WERROR result = WERR_OK;
4357
4358         DEBUG(4,("enum_all_printers_info_1\n"));
4359
4360         for (snum=0; snum<n_services; snum++) {
4361                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4362                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4363
4364                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4365                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4366                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4367                                         *returned=0;
4368                                         return WERR_NOMEM;
4369                                 }
4370                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4371
4372                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4373                                 (*returned)++;
4374                         }
4375                 }
4376         }
4377
4378         /* check the required size. */
4379         for (i=0; i<*returned; i++)
4380                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4381
4382         if (*needed > offered) {
4383                 result = WERR_INSUFFICIENT_BUFFER;
4384                 goto out;
4385         }
4386
4387         if (!rpcbuf_alloc_size(buffer, *needed)) {
4388                 result = WERR_NOMEM;
4389                 goto out;
4390         }
4391
4392         /* fill the buffer with the structures */
4393         for (i=0; i<*returned; i++)
4394                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4395
4396 out:
4397         /* clear memory */
4398
4399         SAFE_FREE(printers);
4400
4401         if ( !W_ERROR_IS_OK(result) )
4402                 *returned = 0;
4403
4404         return result;
4405 }
4406
4407 /********************************************************************
4408  enum_all_printers_info_1_local.
4409 *********************************************************************/
4410
4411 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4412 {
4413         DEBUG(4,("enum_all_printers_info_1_local\n"));
4414
4415         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4416 }
4417
4418 /********************************************************************
4419  enum_all_printers_info_1_name.
4420 *********************************************************************/
4421
4422 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4423 {
4424         char *s = name;
4425
4426         DEBUG(4,("enum_all_printers_info_1_name\n"));
4427
4428         if ((name[0] == '\\') && (name[1] == '\\'))
4429                 s = name + 2;
4430
4431         if (is_myname_or_ipaddr(s)) {
4432                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4433         }
4434         else
4435                 return WERR_INVALID_NAME;
4436 }
4437
4438 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4439 /********************************************************************
4440  enum_all_printers_info_1_remote.
4441 *********************************************************************/
4442
4443 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 {
4445         PRINTER_INFO_1 *printer;
4446         fstring printername;
4447         fstring desc;
4448         fstring comment;
4449         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4450         WERROR result = WERR_OK;
4451
4452         /* JFM: currently it's more a place holder than anything else.
4453          * In the spooler world there is a notion of server registration.
4454          * the print servers are registered on the PDC (in the same domain)
4455          *
4456          * We should have a TDB here. The registration is done thru an
4457          * undocumented RPC call.
4458          */
4459
4460         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4461                 return WERR_NOMEM;
4462
4463         *returned=1;
4464
4465         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4466         slprintf(desc, sizeof(desc)-1,"%s", name);
4467         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4468
4469         init_unistr(&printer->description, desc);
4470         init_unistr(&printer->name, printername);
4471         init_unistr(&printer->comment, comment);
4472         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4473
4474         /* check the required size. */
4475         *needed += spoolss_size_printer_info_1(printer);
4476
4477         if (*needed > offered) {
4478                 result = WERR_INSUFFICIENT_BUFFER;
4479                 goto out;
4480         }
4481
4482         if (!rpcbuf_alloc_size(buffer, *needed)) {
4483                 result = WERR_NOMEM;
4484                 goto out;
4485         }
4486
4487         /* fill the buffer with the structures */
4488         smb_io_printer_info_1("", buffer, printer, 0);
4489
4490 out:
4491         /* clear memory */
4492         SAFE_FREE(printer);
4493
4494         if ( !W_ERROR_IS_OK(result) )
4495                 *returned = 0;
4496
4497         return result;
4498 }
4499
4500 #endif
4501
4502 /********************************************************************
4503  enum_all_printers_info_1_network.
4504 *********************************************************************/
4505
4506 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4507 {
4508         char *s = name;
4509
4510         DEBUG(4,("enum_all_printers_info_1_network\n"));
4511
4512         /* If we respond to a enum_printers level 1 on our name with flags
4513            set to PRINTER_ENUM_REMOTE with a list of printers then these
4514            printers incorrectly appear in the APW browse list.
4515            Specifically the printers for the server appear at the workgroup
4516            level where all the other servers in the domain are
4517            listed. Windows responds to this call with a
4518            WERR_CAN_NOT_COMPLETE so we should do the same. */
4519
4520         if (name[0] == '\\' && name[1] == '\\')
4521                  s = name + 2;
4522
4523         if (is_myname_or_ipaddr(s))
4524                  return WERR_CAN_NOT_COMPLETE;
4525
4526         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4527 }
4528
4529 /********************************************************************
4530  * api_spoolss_enumprinters
4531  *
4532  * called from api_spoolss_enumprinters (see this to understand)
4533  ********************************************************************/
4534
4535 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4536 {
4537         int snum;
4538         int i;
4539         int n_services=lp_numservices();
4540         PRINTER_INFO_2 *printers=NULL;
4541         PRINTER_INFO_2 current_prt;
4542         WERROR result = WERR_OK;
4543
4544         *returned = 0;
4545
4546         for (snum=0; snum<n_services; snum++) {
4547                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4548                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4549
4550                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4551                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4552                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4553                                         *returned = 0;
4554                                         return WERR_NOMEM;
4555                                 }
4556
4557                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4558
4559                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4560
4561                                 (*returned)++;
4562                         }
4563                 }
4564         }
4565
4566         /* check the required size. */
4567         for (i=0; i<*returned; i++)
4568                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4569
4570         if (*needed > offered) {
4571                 result = WERR_INSUFFICIENT_BUFFER;
4572                 goto out;
4573         }
4574
4575         if (!rpcbuf_alloc_size(buffer, *needed)) {
4576                 result = WERR_NOMEM;
4577                 goto out;
4578         }
4579
4580         /* fill the buffer with the structures */
4581         for (i=0; i<*returned; i++)
4582                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4583
4584 out:
4585         /* clear memory */
4586
4587         for (i=0; i<*returned; i++)
4588                 free_devmode(printers[i].devmode);
4589
4590         SAFE_FREE(printers);
4591
4592         if ( !W_ERROR_IS_OK(result) )
4593                 *returned = 0;
4594
4595         return result;
4596 }
4597
4598 /********************************************************************
4599  * handle enumeration of printers at level 1
4600  ********************************************************************/
4601
4602 static WERROR enumprinters_level1( uint32 flags, fstring name,
4603                                  RPC_BUFFER *buffer, uint32 offered,
4604                                  uint32 *needed, uint32 *returned)
4605 {
4606         /* Not all the flags are equals */
4607
4608         if (flags & PRINTER_ENUM_LOCAL)
4609                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4610
4611         if (flags & PRINTER_ENUM_NAME)
4612                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4613
4614 #if 0   /* JERRY - disabled for now */
4615         if (flags & PRINTER_ENUM_REMOTE)
4616                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4617 #endif
4618
4619         if (flags & PRINTER_ENUM_NETWORK)
4620                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4621
4622         return WERR_OK; /* NT4sp5 does that */
4623 }
4624
4625 /********************************************************************
4626  * handle enumeration of printers at level 2
4627  ********************************************************************/
4628
4629 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4630                                  RPC_BUFFER *buffer, uint32 offered,
4631                                  uint32 *needed, uint32 *returned)
4632 {
4633         if (flags & PRINTER_ENUM_LOCAL) {
4634                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4635         }
4636
4637         if (flags & PRINTER_ENUM_NAME) {
4638                 if (is_myname_or_ipaddr(canon_servername(servername)))
4639                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4640                 else
4641                         return WERR_INVALID_NAME;
4642         }
4643
4644         if (flags & PRINTER_ENUM_REMOTE)
4645                 return WERR_UNKNOWN_LEVEL;
4646
4647         return WERR_OK;
4648 }
4649
4650 /********************************************************************
4651  * handle enumeration of printers at level 5
4652  ********************************************************************/
4653
4654 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4655                                  RPC_BUFFER *buffer, uint32 offered,
4656                                  uint32 *needed, uint32 *returned)
4657 {
4658 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4659         return WERR_OK;
4660 }
4661
4662 /********************************************************************
4663  * api_spoolss_enumprinters
4664  *
4665  * called from api_spoolss_enumprinters (see this to understand)
4666  ********************************************************************/
4667
4668 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4669 {
4670         uint32 flags = q_u->flags;
4671         UNISTR2 *servername = &q_u->servername;
4672         uint32 level = q_u->level;
4673         RPC_BUFFER *buffer = NULL;
4674         uint32 offered = q_u->offered;
4675         uint32 *needed = &r_u->needed;
4676         uint32 *returned = &r_u->returned;
4677
4678         fstring name;
4679
4680         /* that's an [in out] buffer */
4681
4682         if (!q_u->buffer && (offered!=0)) {
4683                 return WERR_INVALID_PARAM;
4684         }
4685
4686         rpcbuf_move(q_u->buffer, &r_u->buffer);
4687         buffer = r_u->buffer;
4688
4689         DEBUG(4,("_spoolss_enumprinters\n"));
4690
4691         *needed=0;
4692         *returned=0;
4693
4694         /*
4695          * Level 1:
4696          *          flags==PRINTER_ENUM_NAME
4697          *           if name=="" then enumerates all printers
4698          *           if name!="" then enumerate the printer
4699          *          flags==PRINTER_ENUM_REMOTE
4700          *          name is NULL, enumerate printers
4701          * Level 2: name!="" enumerates printers, name can't be NULL
4702          * Level 3: doesn't exist
4703          * Level 4: does a local registry lookup
4704          * Level 5: same as Level 2
4705          */
4706
4707         unistr2_to_ascii(name, servername, sizeof(name));
4708         strupper_m(name);
4709
4710         switch (level) {
4711         case 1:
4712                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4713         case 2:
4714                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4715         case 5:
4716                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4717         case 3:
4718         case 4:
4719                 break;
4720         }
4721         return WERR_UNKNOWN_LEVEL;
4722 }
4723
4724 /****************************************************************************
4725 ****************************************************************************/
4726
4727 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4728 {
4729         PRINTER_INFO_0 *printer=NULL;
4730         WERROR result = WERR_OK;
4731
4732         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4733                 return WERR_NOMEM;
4734
4735         construct_printer_info_0(print_hnd, printer, snum);
4736
4737         /* check the required size. */
4738         *needed += spoolss_size_printer_info_0(printer);
4739
4740         if (*needed > offered) {
4741                 result = WERR_INSUFFICIENT_BUFFER;
4742                 goto out;
4743         }
4744
4745         if (!rpcbuf_alloc_size(buffer, *needed)) {
4746                 result = WERR_NOMEM;
4747                 goto out;
4748         }
4749
4750         /* fill the buffer with the structures */
4751         smb_io_printer_info_0("", buffer, printer, 0);
4752
4753 out:
4754         /* clear memory */
4755
4756         SAFE_FREE(printer);
4757
4758         return result;
4759 }
4760
4761 /****************************************************************************
4762 ****************************************************************************/
4763
4764 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4765 {
4766         PRINTER_INFO_1 *printer=NULL;
4767         WERROR result = WERR_OK;
4768
4769         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4770                 return WERR_NOMEM;
4771
4772         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4773
4774         /* check the required size. */
4775         *needed += spoolss_size_printer_info_1(printer);
4776
4777         if (*needed > offered) {
4778                 result = WERR_INSUFFICIENT_BUFFER;
4779                 goto out;
4780         }
4781
4782         if (!rpcbuf_alloc_size(buffer, *needed)) {
4783                 result = WERR_NOMEM;
4784                 goto out;
4785         }
4786
4787         /* fill the buffer with the structures */
4788         smb_io_printer_info_1("", buffer, printer, 0);
4789
4790 out:
4791         /* clear memory */
4792         SAFE_FREE(printer);
4793
4794         return result;
4795 }
4796
4797 /****************************************************************************
4798 ****************************************************************************/
4799
4800 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 {
4802         PRINTER_INFO_2 *printer=NULL;
4803         WERROR result = WERR_OK;
4804
4805         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4806                 return WERR_NOMEM;
4807
4808         construct_printer_info_2(print_hnd, printer, snum);
4809
4810         /* check the required size. */
4811         *needed += spoolss_size_printer_info_2(printer);
4812
4813         if (*needed > offered) {
4814                 result = WERR_INSUFFICIENT_BUFFER;
4815                 goto out;
4816         }
4817
4818         if (!rpcbuf_alloc_size(buffer, *needed)) {
4819                 result = WERR_NOMEM;
4820                 goto out;
4821         }
4822
4823         /* fill the buffer with the structures */
4824         if (!smb_io_printer_info_2("", buffer, printer, 0))
4825                 result = WERR_NOMEM;
4826
4827 out:
4828         /* clear memory */
4829         free_printer_info_2(printer);
4830
4831         return result;
4832 }
4833
4834 /****************************************************************************
4835 ****************************************************************************/
4836
4837 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4838 {
4839         PRINTER_INFO_3 *printer=NULL;
4840         WERROR result = WERR_OK;
4841
4842         if (!construct_printer_info_3(print_hnd, &printer, snum))
4843                 return WERR_NOMEM;
4844
4845         /* check the required size. */
4846         *needed += spoolss_size_printer_info_3(printer);
4847
4848         if (*needed > offered) {
4849                 result = WERR_INSUFFICIENT_BUFFER;
4850                 goto out;
4851         }
4852
4853         if (!rpcbuf_alloc_size(buffer, *needed)) {
4854                 result = WERR_NOMEM;
4855                 goto out;
4856         }
4857
4858         /* fill the buffer with the structures */
4859         smb_io_printer_info_3("", buffer, printer, 0);
4860
4861 out:
4862         /* clear memory */
4863         free_printer_info_3(printer);
4864
4865         return result;
4866 }
4867
4868 /****************************************************************************
4869 ****************************************************************************/
4870
4871 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4872 {
4873         PRINTER_INFO_4 *printer=NULL;
4874         WERROR result = WERR_OK;
4875
4876         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4877                 return WERR_NOMEM;
4878
4879         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4880                 SAFE_FREE(printer);
4881                 return WERR_NOMEM;
4882         }
4883
4884         /* check the required size. */
4885         *needed += spoolss_size_printer_info_4(printer);
4886
4887         if (*needed > offered) {
4888                 result = WERR_INSUFFICIENT_BUFFER;
4889                 goto out;
4890         }
4891
4892         if (!rpcbuf_alloc_size(buffer, *needed)) {
4893                 result = WERR_NOMEM;
4894                 goto out;
4895         }
4896
4897         /* fill the buffer with the structures */
4898         smb_io_printer_info_4("", buffer, printer, 0);
4899
4900 out:
4901         /* clear memory */
4902         free_printer_info_4(printer);
4903
4904         return result;
4905 }
4906
4907 /****************************************************************************
4908 ****************************************************************************/
4909
4910 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4911 {
4912         PRINTER_INFO_5 *printer=NULL;
4913         WERROR result = WERR_OK;
4914
4915         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4916                 return WERR_NOMEM;
4917
4918         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4919                 free_printer_info_5(printer);
4920                 return WERR_NOMEM;
4921         }
4922
4923         /* check the required size. */
4924         *needed += spoolss_size_printer_info_5(printer);
4925
4926         if (*needed > offered) {
4927                 result = WERR_INSUFFICIENT_BUFFER;
4928                 goto out;
4929         }
4930
4931         if (!rpcbuf_alloc_size(buffer, *needed)) {
4932                 result = WERR_NOMEM;
4933                 goto out;
4934         }
4935
4936         /* fill the buffer with the structures */
4937         smb_io_printer_info_5("", buffer, printer, 0);
4938
4939 out:
4940         /* clear memory */
4941         free_printer_info_5(printer);
4942
4943         return result;
4944 }
4945
4946 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4947                                  int snum,
4948                                  RPC_BUFFER *buffer, uint32 offered,
4949                                  uint32 *needed)
4950 {
4951         PRINTER_INFO_6 *printer;
4952         WERROR result = WERR_OK;
4953
4954         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4955                 return WERR_NOMEM;
4956         }
4957
4958         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4959                 free_printer_info_6(printer);
4960                 return WERR_NOMEM;
4961         }
4962
4963         /* check the required size. */
4964         *needed += spoolss_size_printer_info_6(printer);
4965
4966         if (*needed > offered) {
4967                 result = WERR_INSUFFICIENT_BUFFER;
4968                 goto out;
4969         }
4970
4971         if (!rpcbuf_alloc_size(buffer, *needed)) {
4972                 result = WERR_NOMEM;
4973                 goto out;
4974         }
4975
4976         /* fill the buffer with the structures */
4977         smb_io_printer_info_6("", buffer, printer, 0);
4978
4979 out:
4980         /* clear memory */
4981         free_printer_info_6(printer);
4982
4983         return result;
4984 }
4985
4986 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4987 {
4988         PRINTER_INFO_7 *printer=NULL;
4989         WERROR result = WERR_OK;
4990
4991         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4992                 return WERR_NOMEM;
4993
4994         if (!construct_printer_info_7(print_hnd, printer, snum)) {
4995                 result = WERR_NOMEM;
4996                 goto out;
4997         }
4998
4999         /* check the required size. */
5000         *needed += spoolss_size_printer_info_7(printer);
5001
5002         if (*needed > offered) {
5003                 result = WERR_INSUFFICIENT_BUFFER;
5004                 goto out;
5005         }
5006
5007         if (!rpcbuf_alloc_size(buffer, *needed)) {
5008                 result = WERR_NOMEM;
5009                 goto out;
5010
5011         }
5012
5013         /* fill the buffer with the structures */
5014         smb_io_printer_info_7("", buffer, printer, 0);
5015
5016 out:
5017         /* clear memory */
5018         free_printer_info_7(printer);
5019
5020         return result;
5021 }
5022
5023 /****************************************************************************
5024 ****************************************************************************/
5025
5026 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5027 {
5028         POLICY_HND *handle = &q_u->handle;
5029         uint32 level = q_u->level;
5030         RPC_BUFFER *buffer = NULL;
5031         uint32 offered = q_u->offered;
5032         uint32 *needed = &r_u->needed;
5033         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5034
5035         int snum;
5036
5037         /* that's an [in out] buffer */
5038
5039         if (!q_u->buffer && (offered!=0)) {
5040                 return WERR_INVALID_PARAM;
5041         }
5042
5043         rpcbuf_move(q_u->buffer, &r_u->buffer);
5044         buffer = r_u->buffer;
5045
5046         *needed=0;
5047
5048         if (!get_printer_snum(p, handle, &snum, NULL))
5049                 return WERR_BADFID;
5050
5051         switch (level) {
5052         case 0:
5053                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5054         case 1:
5055                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5056         case 2:
5057                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5058         case 3:
5059                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5060         case 4:
5061                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5062         case 5:
5063                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5064         case 6:
5065                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5066         case 7:
5067                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5068         }
5069         return WERR_UNKNOWN_LEVEL;
5070 }
5071
5072 /********************************************************************
5073  * fill a DRIVER_INFO_1 struct
5074  ********************************************************************/
5075
5076 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5077 {
5078         init_unistr( &info->name, driver.info_3->name);
5079 }
5080
5081 /********************************************************************
5082  * construct_printer_driver_info_1
5083  ********************************************************************/
5084
5085 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5086 {
5087         NT_PRINTER_INFO_LEVEL *printer = NULL;
5088         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5089
5090         ZERO_STRUCT(driver);
5091
5092         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5093                 return WERR_INVALID_PRINTER_NAME;
5094
5095         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5096                 free_a_printer(&printer, 2);
5097                 return WERR_UNKNOWN_PRINTER_DRIVER;
5098         }
5099
5100         fill_printer_driver_info_1(info, driver, servername, architecture);
5101
5102         free_a_printer(&printer,2);
5103
5104         return WERR_OK;
5105 }
5106
5107 /********************************************************************
5108  * construct_printer_driver_info_2
5109  * fill a printer_info_2 struct
5110  ********************************************************************/
5111
5112 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5113 {
5114         TALLOC_CTX *ctx = talloc_tos();
5115         char *temp = NULL;
5116         const char *cservername = canon_servername(servername);
5117
5118         info->version=driver.info_3->cversion;
5119
5120         init_unistr( &info->name, driver.info_3->name );
5121         init_unistr( &info->architecture, driver.info_3->environment );
5122
5123         if (strlen(driver.info_3->driverpath)) {
5124                 temp = talloc_asprintf(ctx,
5125                                 "\\\\%s%s",
5126                                 cservername,
5127                                 driver.info_3->driverpath);
5128                 init_unistr( &info->driverpath, temp );
5129         } else {
5130                 init_unistr( &info->driverpath, "" );
5131         }
5132
5133         TALLOC_FREE(temp);
5134         if (strlen(driver.info_3->datafile)) {
5135                 temp = talloc_asprintf(ctx,
5136                                 "\\\\%s%s",
5137                                 cservername,
5138                                 driver.info_3->datafile);
5139                 init_unistr( &info->datafile, temp );
5140         } else
5141                 init_unistr( &info->datafile, "" );
5142
5143         TALLOC_FREE(temp);
5144         if (strlen(driver.info_3->configfile)) {
5145                 temp = talloc_asprintf(ctx,
5146                                 "\\\\%s%s",
5147                                 cservername,
5148                                 driver.info_3->configfile);
5149                 init_unistr( &info->configfile, temp );
5150         } else
5151                 init_unistr( &info->configfile, "" );
5152 }
5153
5154 /********************************************************************
5155  * construct_printer_driver_info_2
5156  * fill a printer_info_2 struct
5157  ********************************************************************/
5158
5159 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5160 {
5161         NT_PRINTER_INFO_LEVEL *printer = NULL;
5162         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5163
5164         ZERO_STRUCT(printer);
5165         ZERO_STRUCT(driver);
5166
5167         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5168                 return WERR_INVALID_PRINTER_NAME;
5169
5170         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5171                 free_a_printer(&printer, 2);
5172                 return WERR_UNKNOWN_PRINTER_DRIVER;
5173         }
5174
5175         fill_printer_driver_info_2(info, driver, servername);
5176
5177         free_a_printer(&printer,2);
5178
5179         return WERR_OK;
5180 }
5181
5182 /********************************************************************
5183  * copy a strings array and convert to UNICODE
5184  *
5185  * convert an array of ascii string to a UNICODE string
5186  ********************************************************************/
5187
5188 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5189 {
5190         int i=0;
5191         int j=0;
5192         const char *v;
5193         char *line = NULL;
5194         TALLOC_CTX *ctx = talloc_tos();
5195
5196         DEBUG(6,("init_unistr_array\n"));
5197         *uni_array=NULL;
5198
5199         while (true) {
5200                 if ( !char_array ) {
5201                         v = "";
5202                 } else {
5203                         v = char_array[i];
5204                         if (!v)
5205                                 v = ""; /* hack to handle null lists */
5206                 }
5207
5208                 /* hack to allow this to be used in places other than when generating
5209                    the list of dependent files */
5210
5211                 TALLOC_FREE(line);
5212                 if ( servername ) {
5213                         line = talloc_asprintf(ctx,
5214                                         "\\\\%s%s",
5215                                         canon_servername(servername),
5216                                         v);
5217                 } else {
5218                         line = talloc_strdup(ctx, v);
5219                 }
5220
5221                 if (!line) {
5222                         SAFE_FREE(*uni_array);
5223                         return 0;
5224                 }
5225                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5226
5227                 /* add one extra unit16 for the second terminating NULL */
5228
5229                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5230                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5231                         return 0;
5232                 }
5233
5234                 if ( !strlen(v) )
5235                         break;
5236
5237                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5238                 i++;
5239         }
5240
5241         if (*uni_array) {
5242                 /* special case for ""; we need to add both NULL's here */
5243                 if (!j)
5244                         (*uni_array)[j++]=0x0000;
5245                 (*uni_array)[j]=0x0000;
5246         }
5247
5248         DEBUGADD(6,("last one:done\n"));
5249
5250         /* return size of array in uint16's */
5251
5252         return j+1;
5253 }
5254
5255 /********************************************************************
5256  * construct_printer_info_3
5257  * fill a printer_info_3 struct
5258  ********************************************************************/
5259
5260 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5261 {
5262         char *temp = NULL;
5263         TALLOC_CTX *ctx = talloc_tos();
5264         const char *cservername = canon_servername(servername);
5265
5266         ZERO_STRUCTP(info);
5267
5268         info->version=driver.info_3->cversion;
5269
5270         init_unistr( &info->name, driver.info_3->name );
5271         init_unistr( &info->architecture, driver.info_3->environment );
5272
5273         if (strlen(driver.info_3->driverpath)) {
5274                 temp = talloc_asprintf(ctx,
5275                                 "\\\\%s%s",
5276                                 cservername,
5277                                 driver.info_3->driverpath);
5278                 init_unistr( &info->driverpath, temp );
5279         } else
5280                 init_unistr( &info->driverpath, "" );
5281
5282         TALLOC_FREE(temp);
5283         if (strlen(driver.info_3->datafile)) {
5284                 temp = talloc_asprintf(ctx,
5285                                 "\\\\%s%s",
5286                                 cservername,
5287                                 driver.info_3->datafile);
5288                 init_unistr( &info->datafile, temp );
5289         } else
5290                 init_unistr( &info->datafile, "" );
5291
5292         TALLOC_FREE(temp);
5293         if (strlen(driver.info_3->configfile)) {
5294                 temp = talloc_asprintf(ctx,
5295                                 "\\\\%s%s",
5296                                 cservername,
5297                                 driver.info_3->configfile);
5298                 init_unistr( &info->configfile, temp );
5299         } else
5300                 init_unistr( &info->configfile, "" );
5301
5302         TALLOC_FREE(temp);
5303         if (strlen(driver.info_3->helpfile)) {
5304                 temp = talloc_asprintf(ctx,
5305                                 "\\\\%s%s",
5306                                 cservername,
5307                                 driver.info_3->helpfile);
5308                 init_unistr( &info->helpfile, temp );
5309         } else
5310                 init_unistr( &info->helpfile, "" );
5311
5312         TALLOC_FREE(temp);
5313         init_unistr( &info->monitorname, driver.info_3->monitorname );
5314         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5315
5316         info->dependentfiles=NULL;
5317         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5318 }
5319
5320 /********************************************************************
5321  * construct_printer_info_3
5322  * fill a printer_info_3 struct
5323  ********************************************************************/
5324
5325 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5326 {
5327         NT_PRINTER_INFO_LEVEL *printer = NULL;
5328         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5329         WERROR status;
5330         ZERO_STRUCT(driver);
5331
5332         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5333         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5334         if (!W_ERROR_IS_OK(status))
5335                 return WERR_INVALID_PRINTER_NAME;
5336
5337         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5338         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5339
5340 #if 0   /* JERRY */
5341
5342         /*
5343          * I put this code in during testing.  Helpful when commenting out the
5344          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5345          * as win2k always queries the driver using an infor level of 6.
5346          * I've left it in (but ifdef'd out) because I'll probably
5347          * use it in experimentation again in the future.   --jerry 22/01/2002
5348          */
5349
5350         if (!W_ERROR_IS_OK(status)) {
5351                 /*
5352                  * Is this a W2k client ?
5353                  */
5354                 if (version == 3) {
5355                         /* Yes - try again with a WinNT driver. */
5356                         version = 2;
5357                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5359                 }
5360 #endif
5361
5362                 if (!W_ERROR_IS_OK(status)) {
5363                         free_a_printer(&printer,2);
5364                         return WERR_UNKNOWN_PRINTER_DRIVER;
5365                 }
5366
5367 #if 0   /* JERRY */
5368         }
5369 #endif
5370
5371
5372         fill_printer_driver_info_3(info, driver, servername);
5373
5374         free_a_printer(&printer,2);
5375
5376         return WERR_OK;
5377 }
5378
5379 /********************************************************************
5380  * construct_printer_info_6
5381  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5382  ********************************************************************/
5383
5384 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5385 {
5386         char *temp = NULL;
5387         fstring nullstr;
5388         TALLOC_CTX *ctx = talloc_tos();
5389         const char *cservername = canon_servername(servername);
5390
5391         ZERO_STRUCTP(info);
5392         memset(&nullstr, '\0', sizeof(fstring));
5393
5394         info->version=driver.info_3->cversion;
5395
5396         init_unistr( &info->name, driver.info_3->name );
5397         init_unistr( &info->architecture, driver.info_3->environment );
5398
5399         if (strlen(driver.info_3->driverpath)) {
5400                 temp = talloc_asprintf(ctx,
5401                                 "\\\\%s%s",
5402                                 cservername,
5403                                 driver.info_3->driverpath);
5404                 init_unistr( &info->driverpath, temp );
5405         } else
5406                 init_unistr( &info->driverpath, "" );
5407
5408         TALLOC_FREE(temp);
5409         if (strlen(driver.info_3->datafile)) {
5410                 temp = talloc_asprintf(ctx,
5411                                 "\\\\%s%s",
5412                                 cservername,
5413                                 driver.info_3->datafile);
5414                 init_unistr( &info->datafile, temp );
5415         } else
5416                 init_unistr( &info->datafile, "" );
5417
5418         TALLOC_FREE(temp);
5419         if (strlen(driver.info_3->configfile)) {
5420                 temp = talloc_asprintf(ctx,
5421                                 "\\\\%s%s",
5422                                 cservername,
5423                                 driver.info_3->configfile);
5424                 init_unistr( &info->configfile, temp );
5425         } else
5426                 init_unistr( &info->configfile, "" );
5427
5428         TALLOC_FREE(temp);
5429         if (strlen(driver.info_3->helpfile)) {
5430                 temp = talloc_asprintf(ctx,
5431                                 "\\\\%s%s",
5432                                 cservername,
5433                                 driver.info_3->helpfile);
5434                 init_unistr( &info->helpfile, temp );
5435         } else
5436                 init_unistr( &info->helpfile, "" );
5437
5438         TALLOC_FREE(temp);
5439         init_unistr( &info->monitorname, driver.info_3->monitorname );
5440         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5441
5442         info->dependentfiles = NULL;
5443         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5444
5445         info->previousdrivernames=NULL;
5446         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5447
5448         info->driver_date=0;
5449
5450         info->padding=0;
5451         info->driver_version_low=0;
5452         info->driver_version_high=0;
5453
5454         init_unistr( &info->mfgname, "");
5455         init_unistr( &info->oem_url, "");
5456         init_unistr( &info->hardware_id, "");
5457         init_unistr( &info->provider, "");
5458 }
5459
5460 /********************************************************************
5461  * construct_printer_info_6
5462  * fill a printer_info_6 struct
5463  ********************************************************************/
5464
5465 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5466               const char *servername, fstring architecture, uint32 version)
5467 {
5468         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5469         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5470         WERROR                          status;
5471
5472         ZERO_STRUCT(driver);
5473
5474         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5475
5476         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5477
5478         if (!W_ERROR_IS_OK(status))
5479                 return WERR_INVALID_PRINTER_NAME;
5480
5481         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5482
5483         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5484
5485         if (!W_ERROR_IS_OK(status))
5486         {
5487                 /*
5488                  * Is this a W2k client ?
5489                  */
5490
5491                 if (version < 3) {
5492                         free_a_printer(&printer,2);
5493                         return WERR_UNKNOWN_PRINTER_DRIVER;
5494                 }
5495
5496                 /* Yes - try again with a WinNT driver. */
5497                 version = 2;
5498                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5499                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5500                 if (!W_ERROR_IS_OK(status)) {
5501                         free_a_printer(&printer,2);
5502                         return WERR_UNKNOWN_PRINTER_DRIVER;
5503                 }
5504         }
5505
5506         fill_printer_driver_info_6(info, driver, servername);
5507
5508         free_a_printer(&printer,2);
5509         free_a_printer_driver(driver, 3);
5510
5511         return WERR_OK;
5512 }
5513
5514 /****************************************************************************
5515 ****************************************************************************/
5516
5517 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5518 {
5519         SAFE_FREE(info->dependentfiles);
5520 }
5521
5522 /****************************************************************************
5523 ****************************************************************************/
5524
5525 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5526 {
5527         SAFE_FREE(info->dependentfiles);
5528 }
5529
5530 /****************************************************************************
5531 ****************************************************************************/
5532
5533 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5534 {
5535         DRIVER_INFO_1 *info=NULL;
5536         WERROR result;
5537
5538         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5539                 return WERR_NOMEM;
5540
5541         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5542         if (!W_ERROR_IS_OK(result))
5543                 goto out;
5544
5545         /* check the required size. */
5546         *needed += spoolss_size_printer_driver_info_1(info);
5547
5548         if (*needed > offered) {
5549                 result = WERR_INSUFFICIENT_BUFFER;
5550                 goto out;
5551         }
5552
5553         if (!rpcbuf_alloc_size(buffer, *needed)) {
5554                 result = WERR_NOMEM;
5555                 goto out;
5556         }
5557
5558         /* fill the buffer with the structures */
5559         smb_io_printer_driver_info_1("", buffer, info, 0);
5560
5561 out:
5562         /* clear memory */
5563         SAFE_FREE(info);
5564
5565         return result;
5566 }
5567
5568 /****************************************************************************
5569 ****************************************************************************/
5570
5571 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5572 {
5573         DRIVER_INFO_2 *info=NULL;
5574         WERROR result;
5575
5576         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5577                 return WERR_NOMEM;
5578
5579         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5580         if (!W_ERROR_IS_OK(result))
5581                 goto out;
5582
5583         /* check the required size. */
5584         *needed += spoolss_size_printer_driver_info_2(info);
5585
5586         if (*needed > offered) {
5587                 result = WERR_INSUFFICIENT_BUFFER;
5588                 goto out;
5589         }
5590
5591         if (!rpcbuf_alloc_size(buffer, *needed)) {
5592                 result = WERR_NOMEM;
5593                 goto out;
5594         }
5595
5596         /* fill the buffer with the structures */
5597         smb_io_printer_driver_info_2("", buffer, info, 0);
5598
5599 out:
5600         /* clear memory */
5601         SAFE_FREE(info);
5602
5603         return result;
5604 }
5605
5606 /****************************************************************************
5607 ****************************************************************************/
5608
5609 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5610 {
5611         DRIVER_INFO_3 info;
5612         WERROR result;
5613
5614         ZERO_STRUCT(info);
5615
5616         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5617         if (!W_ERROR_IS_OK(result))
5618                 goto out;
5619
5620         /* check the required size. */
5621         *needed += spoolss_size_printer_driver_info_3(&info);
5622
5623         if (*needed > offered) {
5624                 result = WERR_INSUFFICIENT_BUFFER;
5625                 goto out;
5626         }
5627
5628         if (!rpcbuf_alloc_size(buffer, *needed)) {
5629                 result = WERR_NOMEM;
5630                 goto out;
5631         }
5632
5633         /* fill the buffer with the structures */
5634         smb_io_printer_driver_info_3("", buffer, &info, 0);
5635
5636 out:
5637         free_printer_driver_info_3(&info);
5638
5639         return result;
5640 }
5641
5642 /****************************************************************************
5643 ****************************************************************************/
5644
5645 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5646 {
5647         DRIVER_INFO_6 info;
5648         WERROR result;
5649
5650         ZERO_STRUCT(info);
5651
5652         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5653         if (!W_ERROR_IS_OK(result))
5654                 goto out;
5655
5656         /* check the required size. */
5657         *needed += spoolss_size_printer_driver_info_6(&info);
5658
5659         if (*needed > offered) {
5660                 result = WERR_INSUFFICIENT_BUFFER;
5661                 goto out;
5662         }
5663
5664         if (!rpcbuf_alloc_size(buffer, *needed)) {
5665                 result = WERR_NOMEM;
5666                 goto out;
5667         }
5668
5669         /* fill the buffer with the structures */
5670         smb_io_printer_driver_info_6("", buffer, &info, 0);
5671
5672 out:
5673         free_printer_driver_info_6(&info);
5674
5675         return result;
5676 }
5677
5678 /****************************************************************************
5679 ****************************************************************************/
5680
5681 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5682 {
5683         POLICY_HND *handle = &q_u->handle;
5684         UNISTR2 *uni_arch = &q_u->architecture;
5685         uint32 level = q_u->level;
5686         uint32 clientmajorversion = q_u->clientmajorversion;
5687         RPC_BUFFER *buffer = NULL;
5688         uint32 offered = q_u->offered;
5689         uint32 *needed = &r_u->needed;
5690         uint32 *servermajorversion = &r_u->servermajorversion;
5691         uint32 *serverminorversion = &r_u->serverminorversion;
5692         Printer_entry *printer;
5693
5694         fstring servername;
5695         fstring architecture;
5696         int snum;
5697
5698         /* that's an [in out] buffer */
5699
5700         if (!q_u->buffer && (offered!=0)) {
5701                 return WERR_INVALID_PARAM;
5702         }
5703
5704         rpcbuf_move(q_u->buffer, &r_u->buffer);
5705         buffer = r_u->buffer;
5706
5707         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5708
5709         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5710                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5711                 return WERR_INVALID_PRINTER_NAME;
5712         }
5713
5714         *needed = 0;
5715         *servermajorversion = 0;
5716         *serverminorversion = 0;
5717
5718         fstrcpy(servername, get_server_name( printer ));
5719         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5720
5721         if (!get_printer_snum(p, handle, &snum, NULL))
5722                 return WERR_BADFID;
5723
5724         switch (level) {
5725         case 1:
5726                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5727         case 2:
5728                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5729         case 3:
5730                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5731         case 6:
5732                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5733 #if 0   /* JERRY */
5734         case 101:
5735                 /* apparently this call is the equivalent of
5736                    EnumPrinterDataEx() for the DsDriver key */
5737                 break;
5738 #endif
5739         }
5740
5741         return WERR_UNKNOWN_LEVEL;
5742 }
5743
5744
5745 /****************************************************************
5746  _spoolss_StartPagePrinter
5747 ****************************************************************/
5748
5749 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5750                                  struct spoolss_StartPagePrinter *r)
5751 {
5752         POLICY_HND *handle = r->in.handle;
5753
5754         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5755
5756         if (!Printer) {
5757                 DEBUG(3,("_spoolss_StartPagePrinter: "
5758                         "Error in startpageprinter printer handle\n"));
5759                 return WERR_BADFID;
5760         }
5761
5762         Printer->page_started=True;
5763         return WERR_OK;
5764 }
5765
5766 /****************************************************************
5767  _spoolss_EndPagePrinter
5768 ****************************************************************/
5769
5770 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5771                                struct spoolss_EndPagePrinter *r)
5772 {
5773         POLICY_HND *handle = r->in.handle;
5774         int snum;
5775
5776         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5777
5778         if (!Printer) {
5779                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5780                         OUR_HANDLE(handle)));
5781                 return WERR_BADFID;
5782         }
5783
5784         if (!get_printer_snum(p, handle, &snum, NULL))
5785                 return WERR_BADFID;
5786
5787         Printer->page_started=False;
5788         print_job_endpage(snum, Printer->jobid);
5789
5790         return WERR_OK;
5791 }
5792
5793 /****************************************************************
5794  _spoolss_StartDocPrinter
5795 ****************************************************************/
5796
5797 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5798                                 struct spoolss_StartDocPrinter *r)
5799 {
5800         POLICY_HND *handle = r->in.handle;
5801         uint32_t *jobid = r->out.job_id;
5802         struct spoolss_DocumentInfo1 *info_1;
5803         int snum;
5804         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5805
5806         if (!Printer) {
5807                 DEBUG(2,("_spoolss_StartDocPrinter: "
5808                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5809                 return WERR_BADFID;
5810         }
5811
5812         if (r->in.level != 1) {
5813                 return WERR_UNKNOWN_LEVEL;
5814         }
5815
5816         info_1 = r->in.info.info1;
5817
5818         /*
5819          * a nice thing with NT is it doesn't listen to what you tell it.
5820          * when asked to send _only_ RAW datas, it tries to send datas
5821          * in EMF format.
5822          *
5823          * So I add checks like in NT Server ...
5824          */
5825
5826         if (info_1->datatype) {
5827                 if (strcmp(info_1->datatype, "RAW") != 0) {
5828                         (*jobid)=0;
5829                         return WERR_INVALID_DATATYPE;
5830                 }
5831         }
5832
5833         /* get the share number of the printer */
5834         if (!get_printer_snum(p, handle, &snum, NULL)) {
5835                 return WERR_BADFID;
5836         }
5837
5838         Printer->jobid = print_job_start(p->server_info, snum,
5839                                          CONST_DISCARD(char *,info_1->document_name),
5840                                          Printer->nt_devmode);
5841
5842         /* An error occured in print_job_start() so return an appropriate
5843            NT error code. */
5844
5845         if (Printer->jobid == -1) {
5846                 return map_werror_from_unix(errno);
5847         }
5848
5849         Printer->document_started=True;
5850         (*jobid) = Printer->jobid;
5851
5852         return WERR_OK;
5853 }
5854
5855 /****************************************************************
5856  _spoolss_EndDocPrinter
5857 ****************************************************************/
5858
5859 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5860                               struct spoolss_EndDocPrinter *r)
5861 {
5862         POLICY_HND *handle = r->in.handle;
5863
5864         return _spoolss_enddocprinter_internal(p, handle);
5865 }
5866
5867 /****************************************************************
5868  _spoolss_WritePrinter
5869 ****************************************************************/
5870
5871 WERROR _spoolss_WritePrinter(pipes_struct *p,
5872                              struct spoolss_WritePrinter *r)
5873 {
5874         POLICY_HND *handle = r->in.handle;
5875         uint32 buffer_size = r->in._data_size;
5876         uint8 *buffer = r->in.data.data;
5877         uint32 *buffer_written = &r->in._data_size;
5878         int snum;
5879         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5880
5881         if (!Printer) {
5882                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5883                         OUR_HANDLE(handle)));
5884                 *r->out.num_written = r->in._data_size;
5885                 return WERR_BADFID;
5886         }
5887
5888         if (!get_printer_snum(p, handle, &snum, NULL))
5889                 return WERR_BADFID;
5890
5891         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5892                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5893         if (*buffer_written == (uint32)-1) {
5894                 *r->out.num_written = 0;
5895                 if (errno == ENOSPC)
5896                         return WERR_NO_SPOOL_SPACE;
5897                 else
5898                         return WERR_ACCESS_DENIED;
5899         }
5900
5901         *r->out.num_written = r->in._data_size;
5902
5903         return WERR_OK;
5904 }
5905
5906 /********************************************************************
5907  * api_spoolss_getprinter
5908  * called from the spoolss dispatcher
5909  *
5910  ********************************************************************/
5911
5912 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5913                               pipes_struct *p)
5914 {
5915         int snum;
5916         WERROR errcode = WERR_BADFUNC;
5917         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5918
5919         if (!Printer) {
5920                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5921                 return WERR_BADFID;
5922         }
5923
5924         if (!get_printer_snum(p, handle, &snum, NULL))
5925                 return WERR_BADFID;
5926
5927         switch (command) {
5928         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5929                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5930                         errcode = WERR_OK;
5931                 }
5932                 break;
5933         case SPOOLSS_PRINTER_CONTROL_RESUME:
5934         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5935                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5936                         errcode = WERR_OK;
5937                 }
5938                 break;
5939         case SPOOLSS_PRINTER_CONTROL_PURGE:
5940                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5941                         errcode = WERR_OK;
5942                 }
5943                 break;
5944         default:
5945                 return WERR_UNKNOWN_LEVEL;
5946         }
5947
5948         return errcode;
5949 }
5950
5951
5952 /****************************************************************
5953  _spoolss_AbortPrinter
5954  * From MSDN: "Deletes printer's spool file if printer is configured
5955  * for spooling"
5956 ****************************************************************/
5957
5958 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5959                              struct spoolss_AbortPrinter *r)
5960 {
5961         POLICY_HND      *handle = r->in.handle;
5962         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5963         int             snum;
5964         WERROR          errcode = WERR_OK;
5965
5966         if (!Printer) {
5967                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5968                         OUR_HANDLE(handle)));
5969                 return WERR_BADFID;
5970         }
5971
5972         if (!get_printer_snum(p, handle, &snum, NULL))
5973                 return WERR_BADFID;
5974
5975         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5976
5977         return errcode;
5978 }
5979
5980 /********************************************************************
5981  * called by spoolss_api_setprinter
5982  * when updating a printer description
5983  ********************************************************************/
5984
5985 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5986                                  const SPOOL_PRINTER_INFO_LEVEL *info,
5987                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5988 {
5989         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5990         WERROR result;
5991         int snum;
5992
5993         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5994
5995         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5996                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5997                          OUR_HANDLE(handle)));
5998
5999                 result = WERR_BADFID;
6000                 goto done;
6001         }
6002
6003         if (!secdesc_ctr) {
6004                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6005                 result = WERR_INVALID_PARAM;
6006                 goto done;
6007         }
6008
6009         /* Check the user has permissions to change the security
6010            descriptor.  By experimentation with two NT machines, the user
6011            requires Full Access to the printer to change security
6012            information. */
6013
6014         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6015                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6016                 result = WERR_ACCESS_DENIED;
6017                 goto done;
6018         }
6019
6020         /* NT seems to like setting the security descriptor even though
6021            nothing may have actually changed. */
6022
6023         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6024                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6025                 result = WERR_BADFID;
6026                 goto done;
6027         }
6028
6029         if (DEBUGLEVEL >= 10) {
6030                 SEC_ACL *the_acl;
6031                 int i;
6032
6033                 the_acl = old_secdesc_ctr->sd->dacl;
6034                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6035                            PRINTERNAME(snum), the_acl->num_aces));
6036
6037                 for (i = 0; i < the_acl->num_aces; i++) {
6038                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6039                                            &the_acl->aces[i].trustee),
6040                                   the_acl->aces[i].access_mask));
6041                 }
6042
6043                 the_acl = secdesc_ctr->sd->dacl;
6044
6045                 if (the_acl) {
6046                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6047                                    PRINTERNAME(snum), the_acl->num_aces));
6048
6049                         for (i = 0; i < the_acl->num_aces; i++) {
6050                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6051                                                    &the_acl->aces[i].trustee),
6052                                            the_acl->aces[i].access_mask));
6053                         }
6054                 } else {
6055                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6056                 }
6057         }
6058
6059         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6060         if (!new_secdesc_ctr) {
6061                 result = WERR_NOMEM;
6062                 goto done;
6063         }
6064
6065         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6066                 result = WERR_OK;
6067                 goto done;
6068         }
6069
6070         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6071
6072  done:
6073
6074         return result;
6075 }
6076
6077 /********************************************************************
6078  Canonicalize printer info from a client
6079
6080  ATTN: It does not matter what we set the servername to hear
6081  since we do the necessary work in get_a_printer() to set it to
6082  the correct value based on what the client sent in the
6083  _spoolss_open_printer_ex().
6084  ********************************************************************/
6085
6086 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6087 {
6088         fstring printername;
6089         const char *p;
6090
6091         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6092                 "portname=%s drivername=%s comment=%s location=%s\n",
6093                 info->servername, info->printername, info->sharename,
6094                 info->portname, info->drivername, info->comment, info->location));
6095
6096         /* we force some elements to "correct" values */
6097         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6098         fstrcpy(info->sharename, lp_servicename(snum));
6099
6100         /* check to see if we allow printername != sharename */
6101
6102         if ( lp_force_printername(snum) ) {
6103                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6104                         global_myname(), info->sharename );
6105         } else {
6106
6107                 /* make sure printername is in \\server\printername format */
6108
6109                 fstrcpy( printername, info->printername );
6110                 p = printername;
6111                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6112                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6113                                 p++;
6114                 }
6115
6116                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6117                          global_myname(), p );
6118         }
6119
6120         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6121         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6122
6123
6124
6125         return True;
6126 }
6127
6128 /****************************************************************************
6129 ****************************************************************************/
6130
6131 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6132 {
6133         char *cmd = lp_addport_cmd();
6134         char *command = NULL;
6135         int ret;
6136         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6137         bool is_print_op = False;
6138
6139         if ( !*cmd ) {
6140                 return WERR_ACCESS_DENIED;
6141         }
6142
6143         command = talloc_asprintf(ctx,
6144                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6145         if (!command) {
6146                 return WERR_NOMEM;
6147         }
6148
6149         if ( token )
6150                 is_print_op = user_has_privileges( token, &se_printop );
6151
6152         DEBUG(10,("Running [%s]\n", command));
6153
6154         /********* BEGIN SePrintOperatorPrivilege **********/
6155
6156         if ( is_print_op )
6157                 become_root();
6158
6159         ret = smbrun(command, NULL);
6160
6161         if ( is_print_op )
6162                 unbecome_root();
6163
6164         /********* END SePrintOperatorPrivilege **********/
6165
6166         DEBUGADD(10,("returned [%d]\n", ret));
6167
6168         TALLOC_FREE(command);
6169
6170         if ( ret != 0 ) {
6171                 return WERR_ACCESS_DENIED;
6172         }
6173
6174         return WERR_OK;
6175 }
6176
6177 /****************************************************************************
6178 ****************************************************************************/
6179
6180 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6181 {
6182         char *cmd = lp_addprinter_cmd();
6183         char **qlines;
6184         char *command = NULL;
6185         int numlines;
6186         int ret;
6187         int fd;
6188         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6189         bool is_print_op = False;
6190         char *remote_machine = talloc_strdup(ctx, "%m");
6191
6192         if (!remote_machine) {
6193                 return false;
6194         }
6195         remote_machine = talloc_sub_basic(ctx,
6196                                 current_user_info.smb_name,
6197                                 current_user_info.domain,
6198                                 remote_machine);
6199         if (!remote_machine) {
6200                 return false;
6201         }
6202
6203         command = talloc_asprintf(ctx,
6204                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6205                         cmd, printer->info_2->printername, printer->info_2->sharename,
6206                         printer->info_2->portname, printer->info_2->drivername,
6207                         printer->info_2->location, printer->info_2->comment, remote_machine);
6208         if (!command) {
6209                 return false;
6210         }
6211
6212         if ( token )
6213                 is_print_op = user_has_privileges( token, &se_printop );
6214
6215         DEBUG(10,("Running [%s]\n", command));
6216
6217         /********* BEGIN SePrintOperatorPrivilege **********/
6218
6219         if ( is_print_op )
6220                 become_root();
6221
6222         if ( (ret = smbrun(command, &fd)) == 0 ) {
6223                 /* Tell everyone we updated smb.conf. */
6224                 message_send_all(smbd_messaging_context(),
6225                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6226         }
6227
6228         if ( is_print_op )
6229                 unbecome_root();
6230
6231         /********* END SePrintOperatorPrivilege **********/
6232
6233         DEBUGADD(10,("returned [%d]\n", ret));
6234
6235         TALLOC_FREE(command);
6236         TALLOC_FREE(remote_machine);
6237
6238         if ( ret != 0 ) {
6239                 if (fd != -1)
6240                         close(fd);
6241                 return False;
6242         }
6243
6244         /* reload our services immediately */
6245         reload_services( False );
6246
6247         numlines = 0;
6248         /* Get lines and convert them back to dos-codepage */
6249         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6250         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6251         close(fd);
6252
6253         /* Set the portname to what the script says the portname should be. */
6254         /* but don't require anything to be return from the script exit a good error code */
6255
6256         if (numlines) {
6257                 /* Set the portname to what the script says the portname should be. */
6258                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6259                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6260         }
6261
6262         TALLOC_FREE(qlines);
6263         return True;
6264 }
6265
6266
6267 /********************************************************************
6268  * Called by spoolss_api_setprinter
6269  * when updating a printer description.
6270  ********************************************************************/
6271
6272 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6273                            const SPOOL_PRINTER_INFO_LEVEL *info,
6274                            DEVICEMODE *devmode)
6275 {
6276         int snum;
6277         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6278         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6279         WERROR result;
6280         UNISTR2 buffer;
6281         fstring asc_buffer;
6282
6283         DEBUG(8,("update_printer\n"));
6284
6285         result = WERR_OK;
6286
6287         if (!Printer) {
6288                 result = WERR_BADFID;
6289                 goto done;
6290         }
6291
6292         if (!get_printer_snum(p, handle, &snum, NULL)) {
6293                 result = WERR_BADFID;
6294                 goto done;
6295         }
6296
6297         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6298             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6299                 result = WERR_BADFID;
6300                 goto done;
6301         }
6302
6303         DEBUGADD(8,("Converting info_2 struct\n"));
6304
6305         /*
6306          * convert_printer_info converts the incoming
6307          * info from the client and overwrites the info
6308          * just read from the tdb in the pointer 'printer'.
6309          */
6310
6311         if (!convert_printer_info(info, printer, level)) {
6312                 result =  WERR_NOMEM;
6313                 goto done;
6314         }
6315
6316         if (devmode) {
6317                 /* we have a valid devmode
6318                    convert it and link it*/
6319
6320                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6321                 if (!convert_devicemode(printer->info_2->printername, devmode,
6322                                 &printer->info_2->devmode)) {
6323                         result =  WERR_NOMEM;
6324                         goto done;
6325                 }
6326         }
6327
6328         /* Do sanity check on the requested changes for Samba */
6329
6330         if (!check_printer_ok(printer->info_2, snum)) {
6331                 result = WERR_INVALID_PARAM;
6332                 goto done;
6333         }
6334
6335         /* FIXME!!! If the driver has changed we really should verify that
6336            it is installed before doing much else   --jerry */
6337
6338         /* Check calling user has permission to update printer description */
6339
6340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6341                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6342                 result = WERR_ACCESS_DENIED;
6343                 goto done;
6344         }
6345
6346         /* Call addprinter hook */
6347         /* Check changes to see if this is really needed */
6348
6349         if ( *lp_addprinter_cmd()
6350                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6351                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6352                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6353                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6354         {
6355                 /* add_printer_hook() will call reload_services() */
6356
6357                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6358                                        printer) ) {
6359                         result = WERR_ACCESS_DENIED;
6360                         goto done;
6361                 }
6362         }
6363
6364         /*
6365          * When a *new* driver is bound to a printer, the drivername is used to
6366          * lookup previously saved driver initialization info, which is then
6367          * bound to the printer, simulating what happens in the Windows arch.
6368          */
6369         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6370         {
6371                 if (!set_driver_init(printer, 2))
6372                 {
6373                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6374                                 printer->info_2->drivername));
6375                 }
6376
6377                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6378                         printer->info_2->drivername));
6379
6380                 notify_printer_driver(snum, printer->info_2->drivername);
6381         }
6382
6383         /*
6384          * flag which changes actually occured.  This is a small subset of
6385          * all the possible changes.  We also have to update things in the
6386          * DsSpooler key.
6387          */
6388
6389         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6390                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6391                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6392                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6393
6394                 notify_printer_comment(snum, printer->info_2->comment);
6395         }
6396
6397         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6398                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6399                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6400                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6401
6402                 notify_printer_sharename(snum, printer->info_2->sharename);
6403         }
6404
6405         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6406                 char *pname;
6407
6408                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6409                         pname++;
6410                 else
6411                         pname = printer->info_2->printername;
6412
6413
6414                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6415                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6416                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6417
6418                 notify_printer_printername( snum, pname );
6419         }
6420
6421         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6422                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6423                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6424                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6425
6426                 notify_printer_port(snum, printer->info_2->portname);
6427         }
6428
6429         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6430                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6431                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6432                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6433
6434                 notify_printer_location(snum, printer->info_2->location);
6435         }
6436
6437         /* here we need to update some more DsSpooler keys */
6438         /* uNCName, serverName, shortServerName */
6439
6440         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6441         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6442                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6443         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6444                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6445
6446         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6447                  global_myname(), printer->info_2->sharename );
6448         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6449         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6450                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6451
6452         /* Update printer info */
6453         result = mod_a_printer(printer, 2);
6454
6455 done:
6456         free_a_printer(&printer, 2);
6457         free_a_printer(&old_printer, 2);
6458
6459
6460         return result;
6461 }
6462
6463 /****************************************************************************
6464 ****************************************************************************/
6465 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6466                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6467 {
6468 #ifdef HAVE_ADS
6469         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6470         int snum;
6471         Printer_entry *Printer;
6472
6473         if ( lp_security() != SEC_ADS ) {
6474                 return WERR_UNKNOWN_LEVEL;
6475         }
6476
6477         Printer = find_printer_index_by_hnd(p, handle);
6478
6479         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6480
6481         if (!Printer)
6482                 return WERR_BADFID;
6483
6484         if (!get_printer_snum(p, handle, &snum, NULL))
6485                 return WERR_BADFID;
6486
6487         nt_printer_publish(Printer, snum, info7->action);
6488
6489         return WERR_OK;
6490 #else
6491         return WERR_UNKNOWN_LEVEL;
6492 #endif
6493 }
6494 /****************************************************************************
6495 ****************************************************************************/
6496
6497 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6498 {
6499         POLICY_HND *handle = &q_u->handle;
6500         uint32 level = q_u->level;
6501         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6502         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6503         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6504         uint32 command = q_u->command;
6505         WERROR result;
6506
6507         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6508
6509         if (!Printer) {
6510                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6511                 return WERR_BADFID;
6512         }
6513
6514         /* check the level */
6515         switch (level) {
6516                 case 0:
6517                         return control_printer(handle, command, p);
6518                 case 2:
6519                         result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6520                         if (!W_ERROR_IS_OK(result))
6521                                 return result;
6522                         if (secdesc_ctr)
6523                                 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6524                         return result;
6525                 case 3:
6526                         return update_printer_sec(handle, level, info, p,
6527                                                   secdesc_ctr);
6528                 case 7:
6529                         return publish_or_unpublish_printer(p, handle, info);
6530                 default:
6531                         return WERR_UNKNOWN_LEVEL;
6532         }
6533 }
6534
6535 /****************************************************************
6536  _spoolss_FindClosePrinterNotify
6537 ****************************************************************/
6538
6539 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6540                                        struct spoolss_FindClosePrinterNotify *r)
6541 {
6542         POLICY_HND *handle = r->in.handle;
6543         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6544
6545         if (!Printer) {
6546                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6547                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6548                 return WERR_BADFID;
6549         }
6550
6551         if (Printer->notify.client_connected==True) {
6552                 int snum = -1;
6553
6554                 if ( Printer->printer_type == SPLHND_SERVER)
6555                         snum = -1;
6556                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6557                                 !get_printer_snum(p, handle, &snum, NULL) )
6558                         return WERR_BADFID;
6559
6560                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6561         }
6562
6563         Printer->notify.flags=0;
6564         Printer->notify.options=0;
6565         Printer->notify.localmachine[0]='\0';
6566         Printer->notify.printerlocal=0;
6567         if (Printer->notify.option)
6568                 free_spool_notify_option(&Printer->notify.option);
6569         Printer->notify.client_connected=False;
6570
6571         return WERR_OK;
6572 }
6573
6574 /****************************************************************
6575  _spoolss_AddJob
6576 ****************************************************************/
6577
6578 WERROR _spoolss_AddJob(pipes_struct *p,
6579                        struct spoolss_AddJob *r)
6580 {
6581         if (!r->in.buffer && (r->in.offered != 0)) {
6582                 return WERR_INVALID_PARAM;
6583         }
6584
6585         /* this is what a NT server returns for AddJob. AddJob must fail on
6586          * non-local printers */
6587
6588         return WERR_INVALID_PARAM;
6589 }
6590
6591 /****************************************************************************
6592 ****************************************************************************/
6593
6594 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6595                             int position, int snum,
6596                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6597 {
6598         struct tm *t;
6599
6600         t=gmtime(&queue->time);
6601
6602         job_info->jobid=queue->job;
6603         init_unistr(&job_info->printername, lp_servicename(snum));
6604         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6605         init_unistr(&job_info->username, queue->fs_user);
6606         init_unistr(&job_info->document, queue->fs_file);
6607         init_unistr(&job_info->datatype, "RAW");
6608         init_unistr(&job_info->text_status, "");
6609         job_info->status=nt_printj_status(queue->status);
6610         job_info->priority=queue->priority;
6611         job_info->position=position;
6612         job_info->totalpages=queue->page_count;
6613         job_info->pagesprinted=0;
6614
6615         make_systemtime(&job_info->submitted, t);
6616 }
6617
6618 /****************************************************************************
6619 ****************************************************************************/
6620
6621 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6622                             int position, int snum,
6623                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6624                             DEVICEMODE *devmode)
6625 {
6626         struct tm *t;
6627
6628         t=gmtime(&queue->time);
6629
6630         job_info->jobid=queue->job;
6631
6632         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6633
6634         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6635         init_unistr(&job_info->username, queue->fs_user);
6636         init_unistr(&job_info->document, queue->fs_file);
6637         init_unistr(&job_info->notifyname, queue->fs_user);
6638         init_unistr(&job_info->datatype, "RAW");
6639         init_unistr(&job_info->printprocessor, "winprint");
6640         init_unistr(&job_info->parameters, "");
6641         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6642         init_unistr(&job_info->text_status, "");
6643
6644 /* and here the security descriptor */
6645
6646         job_info->status=nt_printj_status(queue->status);
6647         job_info->priority=queue->priority;
6648         job_info->position=position;
6649         job_info->starttime=0;
6650         job_info->untiltime=0;
6651         job_info->totalpages=queue->page_count;
6652         job_info->size=queue->size;
6653         make_systemtime(&(job_info->submitted), t);
6654         job_info->timeelapsed=0;
6655         job_info->pagesprinted=0;
6656
6657         job_info->devmode = devmode;
6658
6659         return (True);
6660 }
6661
6662 /****************************************************************************
6663  Enumjobs at level 1.
6664 ****************************************************************************/
6665
6666 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6667                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6668                               RPC_BUFFER *buffer, uint32 offered,
6669                               uint32 *needed, uint32 *returned)
6670 {
6671         JOB_INFO_1 *info;
6672         int i;
6673         WERROR result = WERR_OK;
6674
6675         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6676         if (info==NULL) {
6677                 *returned=0;
6678                 return WERR_NOMEM;
6679         }
6680
6681         for (i=0; i<*returned; i++)
6682                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6683
6684         /* check the required size. */
6685         for (i=0; i<*returned; i++)
6686                 (*needed) += spoolss_size_job_info_1(&info[i]);
6687
6688         if (*needed > offered) {
6689                 result = WERR_INSUFFICIENT_BUFFER;
6690                 goto out;
6691         }
6692
6693         if (!rpcbuf_alloc_size(buffer, *needed)) {
6694                 result = WERR_NOMEM;
6695                 goto out;
6696         }
6697
6698         /* fill the buffer with the structures */
6699         for (i=0; i<*returned; i++)
6700                 smb_io_job_info_1("", buffer, &info[i], 0);
6701
6702 out:
6703         /* clear memory */
6704         SAFE_FREE(info);
6705
6706         if ( !W_ERROR_IS_OK(result) )
6707                 *returned = 0;
6708
6709         return result;
6710 }
6711
6712 /****************************************************************************
6713  Enumjobs at level 2.
6714 ****************************************************************************/
6715
6716 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6717                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6718                               RPC_BUFFER *buffer, uint32 offered,
6719                               uint32 *needed, uint32 *returned)
6720 {
6721         JOB_INFO_2 *info = NULL;
6722         int i;
6723         WERROR result = WERR_OK;
6724         DEVICEMODE *devmode = NULL;
6725
6726         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6727                 *returned=0;
6728                 return WERR_NOMEM;
6729         }
6730
6731         /* this should not be a failure condition if the devmode is NULL */
6732
6733         devmode = construct_dev_mode(lp_const_servicename(snum));
6734
6735         for (i=0; i<*returned; i++)
6736                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6737
6738         /* check the required size. */
6739         for (i=0; i<*returned; i++)
6740                 (*needed) += spoolss_size_job_info_2(&info[i]);
6741
6742         if (*needed > offered) {
6743                 result = WERR_INSUFFICIENT_BUFFER;
6744                 goto out;
6745         }
6746
6747         if (!rpcbuf_alloc_size(buffer, *needed)) {
6748                 result = WERR_NOMEM;
6749                 goto out;
6750         }
6751
6752         /* fill the buffer with the structures */
6753         for (i=0; i<*returned; i++)
6754                 smb_io_job_info_2("", buffer, &info[i], 0);
6755
6756 out:
6757         free_devmode(devmode);
6758         SAFE_FREE(info);
6759
6760         if ( !W_ERROR_IS_OK(result) )
6761                 *returned = 0;
6762
6763         return result;
6764
6765 }
6766
6767 /****************************************************************************
6768  Enumjobs.
6769 ****************************************************************************/
6770
6771 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6772 {
6773         POLICY_HND *handle = &q_u->handle;
6774         uint32 level = q_u->level;
6775         RPC_BUFFER *buffer = NULL;
6776         uint32 offered = q_u->offered;
6777         uint32 *needed = &r_u->needed;
6778         uint32 *returned = &r_u->returned;
6779         WERROR wret;
6780         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6781         int snum;
6782         print_status_struct prt_status;
6783         print_queue_struct *queue=NULL;
6784
6785         /* that's an [in out] buffer */
6786
6787         if (!q_u->buffer && (offered!=0)) {
6788                 return WERR_INVALID_PARAM;
6789         }
6790
6791         rpcbuf_move(q_u->buffer, &r_u->buffer);
6792         buffer = r_u->buffer;
6793
6794         DEBUG(4,("_spoolss_enumjobs\n"));
6795
6796         *needed=0;
6797         *returned=0;
6798
6799         /* lookup the printer snum and tdb entry */
6800
6801         if (!get_printer_snum(p, handle, &snum, NULL))
6802                 return WERR_BADFID;
6803
6804         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6805         if ( !W_ERROR_IS_OK(wret) )
6806                 return wret;
6807
6808         *returned = print_queue_status(snum, &queue, &prt_status);
6809         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6810
6811         if (*returned == 0) {
6812                 SAFE_FREE(queue);
6813                 free_a_printer(&ntprinter, 2);
6814                 return WERR_OK;
6815         }
6816
6817         switch (level) {
6818         case 1:
6819                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6820                 break;
6821         case 2:
6822                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6823                 break;
6824         default:
6825                 *returned=0;
6826                 wret = WERR_UNKNOWN_LEVEL;
6827                 break;
6828         }
6829
6830         SAFE_FREE(queue);
6831         free_a_printer( &ntprinter, 2 );
6832         return wret;
6833 }
6834
6835 /****************************************************************
6836  _spoolss_ScheduleJob
6837 ****************************************************************/
6838
6839 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6840                             struct spoolss_ScheduleJob *r)
6841 {
6842         return WERR_OK;
6843 }
6844
6845 /****************************************************************
6846  _spoolss_SetJob
6847 ****************************************************************/
6848
6849 WERROR _spoolss_SetJob(pipes_struct *p,
6850                        struct spoolss_SetJob *r)
6851 {
6852         POLICY_HND *handle = r->in.handle;
6853         uint32 jobid = r->in.job_id;
6854         uint32 command = r->in.command;
6855
6856         int snum;
6857         WERROR errcode = WERR_BADFUNC;
6858
6859         if (!get_printer_snum(p, handle, &snum, NULL)) {
6860                 return WERR_BADFID;
6861         }
6862
6863         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6864                 return WERR_INVALID_PRINTER_NAME;
6865         }
6866
6867         switch (command) {
6868         case SPOOLSS_JOB_CONTROL_CANCEL:
6869         case SPOOLSS_JOB_CONTROL_DELETE:
6870                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6871                         errcode = WERR_OK;
6872                 }
6873                 break;
6874         case SPOOLSS_JOB_CONTROL_PAUSE:
6875                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6876                         errcode = WERR_OK;
6877                 }
6878                 break;
6879         case SPOOLSS_JOB_CONTROL_RESTART:
6880         case SPOOLSS_JOB_CONTROL_RESUME:
6881                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6882                         errcode = WERR_OK;
6883                 }
6884                 break;
6885         default:
6886                 return WERR_UNKNOWN_LEVEL;
6887         }
6888
6889         return errcode;
6890 }
6891
6892 /****************************************************************************
6893  Enumerates all printer drivers at level 1.
6894 ****************************************************************************/
6895
6896 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6897 {
6898         int i;
6899         int ndrivers;
6900         uint32 version;
6901         fstring *list = NULL;
6902         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6903         DRIVER_INFO_1 *driver_info_1=NULL;
6904         WERROR result = WERR_OK;
6905
6906         *returned=0;
6907
6908         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6909                 list=NULL;
6910                 ndrivers=get_ntdrivers(&list, architecture, version);
6911                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6912
6913                 if(ndrivers == -1) {
6914                         SAFE_FREE(driver_info_1);
6915                         return WERR_NOMEM;
6916                 }
6917
6918                 if(ndrivers != 0) {
6919                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6920                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6921                                 SAFE_FREE(list);
6922                                 return WERR_NOMEM;
6923                         }
6924                 }
6925
6926                 for (i=0; i<ndrivers; i++) {
6927                         WERROR status;
6928                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6929                         ZERO_STRUCT(driver);
6930                         status = get_a_printer_driver(&driver, 3, list[i],
6931                                                       architecture, version);
6932                         if (!W_ERROR_IS_OK(status)) {
6933                                 SAFE_FREE(list);
6934                                 SAFE_FREE(driver_info_1);
6935                                 return status;
6936                         }
6937                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6938                         free_a_printer_driver(driver, 3);
6939                 }
6940
6941                 *returned+=ndrivers;
6942                 SAFE_FREE(list);
6943         }
6944
6945         /* check the required size. */
6946         for (i=0; i<*returned; i++) {
6947                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6948                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6949         }
6950
6951         if (*needed > offered) {
6952                 result = WERR_INSUFFICIENT_BUFFER;
6953                 goto out;
6954         }
6955
6956         if (!rpcbuf_alloc_size(buffer, *needed)) {
6957                 result = WERR_NOMEM;
6958                 goto out;
6959         }
6960
6961         /* fill the buffer with the driver structures */
6962         for (i=0; i<*returned; i++) {
6963                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6964                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6965         }
6966
6967 out:
6968         SAFE_FREE(driver_info_1);
6969
6970         if ( !W_ERROR_IS_OK(result) )
6971                 *returned = 0;
6972
6973         return result;
6974 }
6975
6976 /****************************************************************************
6977  Enumerates all printer drivers at level 2.
6978 ****************************************************************************/
6979
6980 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6981 {
6982         int i;
6983         int ndrivers;
6984         uint32 version;
6985         fstring *list = NULL;
6986         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6987         DRIVER_INFO_2 *driver_info_2=NULL;
6988         WERROR result = WERR_OK;
6989
6990         *returned=0;
6991
6992         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6993                 list=NULL;
6994                 ndrivers=get_ntdrivers(&list, architecture, version);
6995                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6996
6997                 if(ndrivers == -1) {
6998                         SAFE_FREE(driver_info_2);
6999                         return WERR_NOMEM;
7000                 }
7001
7002                 if(ndrivers != 0) {
7003                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7004                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7005                                 SAFE_FREE(list);
7006                                 return WERR_NOMEM;
7007                         }
7008                 }
7009
7010                 for (i=0; i<ndrivers; i++) {
7011                         WERROR status;
7012
7013                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7014                         ZERO_STRUCT(driver);
7015                         status = get_a_printer_driver(&driver, 3, list[i],
7016                                                       architecture, version);
7017                         if (!W_ERROR_IS_OK(status)) {
7018                                 SAFE_FREE(list);
7019                                 SAFE_FREE(driver_info_2);
7020                                 return status;
7021                         }
7022                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7023                         free_a_printer_driver(driver, 3);
7024                 }
7025
7026                 *returned+=ndrivers;
7027                 SAFE_FREE(list);
7028         }
7029
7030         /* check the required size. */
7031         for (i=0; i<*returned; i++) {
7032                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7033                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7034         }
7035
7036         if (*needed > offered) {
7037                 result = WERR_INSUFFICIENT_BUFFER;
7038                 goto out;
7039         }
7040
7041         if (!rpcbuf_alloc_size(buffer, *needed)) {
7042                 result = WERR_NOMEM;
7043                 goto out;
7044         }
7045
7046         /* fill the buffer with the form structures */
7047         for (i=0; i<*returned; i++) {
7048                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7049                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7050         }
7051
7052 out:
7053         SAFE_FREE(driver_info_2);
7054
7055         if ( !W_ERROR_IS_OK(result) )
7056                 *returned = 0;
7057
7058         return result;
7059 }
7060
7061 /****************************************************************************
7062  Enumerates all printer drivers at level 3.
7063 ****************************************************************************/
7064
7065 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7066 {
7067         int i;
7068         int ndrivers;
7069         uint32 version;
7070         fstring *list = NULL;
7071         DRIVER_INFO_3 *driver_info_3=NULL;
7072         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7073         WERROR result = WERR_OK;
7074
7075         *returned=0;
7076
7077         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7078                 list=NULL;
7079                 ndrivers=get_ntdrivers(&list, architecture, version);
7080                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7081
7082                 if(ndrivers == -1) {
7083                         SAFE_FREE(driver_info_3);
7084                         return WERR_NOMEM;
7085                 }
7086
7087                 if(ndrivers != 0) {
7088                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7089                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7090                                 SAFE_FREE(list);
7091                                 return WERR_NOMEM;
7092                         }
7093                 }
7094
7095                 for (i=0; i<ndrivers; i++) {
7096                         WERROR status;
7097
7098                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7099                         ZERO_STRUCT(driver);
7100                         status = get_a_printer_driver(&driver, 3, list[i],
7101                                                       architecture, version);
7102                         if (!W_ERROR_IS_OK(status)) {
7103                                 SAFE_FREE(list);
7104                                 SAFE_FREE(driver_info_3);
7105                                 return status;
7106                         }
7107                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7108                         free_a_printer_driver(driver, 3);
7109                 }
7110
7111                 *returned+=ndrivers;
7112                 SAFE_FREE(list);
7113         }
7114
7115         /* check the required size. */
7116         for (i=0; i<*returned; i++) {
7117                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7118                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7119         }
7120
7121         if (*needed > offered) {
7122                 result = WERR_INSUFFICIENT_BUFFER;
7123                 goto out;
7124         }
7125
7126         if (!rpcbuf_alloc_size(buffer, *needed)) {
7127                 result = WERR_NOMEM;
7128                 goto out;
7129         }
7130
7131         /* fill the buffer with the driver structures */
7132         for (i=0; i<*returned; i++) {
7133                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7134                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7135         }
7136
7137 out:
7138         for (i=0; i<*returned; i++) {
7139                 SAFE_FREE(driver_info_3[i].dependentfiles);
7140         }
7141
7142         SAFE_FREE(driver_info_3);
7143
7144         if ( !W_ERROR_IS_OK(result) )
7145                 *returned = 0;
7146
7147         return result;
7148 }
7149
7150 /****************************************************************************
7151  Enumerates all printer drivers.
7152 ****************************************************************************/
7153
7154 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7155 {
7156         uint32 level = q_u->level;
7157         RPC_BUFFER *buffer = NULL;
7158         uint32 offered = q_u->offered;
7159         uint32 *needed = &r_u->needed;
7160         uint32 *returned = &r_u->returned;
7161         const char *cservername;
7162         fstring servername;
7163         fstring architecture;
7164
7165         /* that's an [in out] buffer */
7166
7167         if (!q_u->buffer && (offered!=0)) {
7168                 return WERR_INVALID_PARAM;
7169         }
7170
7171         rpcbuf_move(q_u->buffer, &r_u->buffer);
7172         buffer = r_u->buffer;
7173
7174         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7175
7176         *needed   = 0;
7177         *returned = 0;
7178
7179         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7180         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7181
7182         cservername = canon_servername(servername);
7183
7184         if (!is_myname_or_ipaddr(cservername))
7185                 return WERR_UNKNOWN_PRINTER_DRIVER;
7186
7187         switch (level) {
7188         case 1:
7189                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7190         case 2:
7191                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7192         case 3:
7193                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7194         default:
7195                 return WERR_UNKNOWN_LEVEL;
7196         }
7197 }
7198
7199 /****************************************************************************
7200 ****************************************************************************/
7201
7202 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7203 {
7204         form->flag=list->flag;
7205         init_unistr(&form->name, list->name);
7206         form->width=list->width;
7207         form->length=list->length;
7208         form->left=list->left;
7209         form->top=list->top;
7210         form->right=list->right;
7211         form->bottom=list->bottom;
7212 }
7213
7214 /****************************************************************************
7215 ****************************************************************************/
7216
7217 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7218                                struct spoolss_FormInfo1 *form,
7219                                nt_forms_struct *list)
7220 {
7221         form->form_name         = talloc_strdup(mem_ctx, list->name);
7222         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7223
7224         form->flags             = list->flag;
7225         form->size.width        = list->width;
7226         form->size.height       = list->length;
7227         form->area.left         = list->left;
7228         form->area.top          = list->top;
7229         form->area.right        = list->right;
7230         form->area.bottom       = list->bottom;
7231
7232         return WERR_OK;
7233 }
7234
7235 /****************************************************************************
7236 ****************************************************************************/
7237
7238 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7239 {
7240         uint32 level = q_u->level;
7241         RPC_BUFFER *buffer = NULL;
7242         uint32 offered = q_u->offered;
7243         uint32 *needed = &r_u->needed;
7244         uint32 *numofforms = &r_u->numofforms;
7245         uint32 numbuiltinforms;
7246
7247         nt_forms_struct *list=NULL;
7248         nt_forms_struct *builtinlist=NULL;
7249         FORM_1 *forms_1;
7250         int buffer_size=0;
7251         int i;
7252
7253         /* that's an [in out] buffer */
7254
7255         if (!q_u->buffer && (offered!=0) ) {
7256                 return WERR_INVALID_PARAM;
7257         }
7258
7259         rpcbuf_move(q_u->buffer, &r_u->buffer);
7260         buffer = r_u->buffer;
7261
7262         DEBUG(4,("_spoolss_enumforms\n"));
7263         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7264         DEBUGADD(5,("Info level [%d]\n",          level));
7265
7266         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7267         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7268         *numofforms = get_ntforms(&list);
7269         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7270         *numofforms += numbuiltinforms;
7271
7272         if (*numofforms == 0) {
7273                 SAFE_FREE(builtinlist);
7274                 SAFE_FREE(list);
7275                 return WERR_NO_MORE_ITEMS;
7276         }
7277
7278         switch (level) {
7279         case 1:
7280                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7281                         SAFE_FREE(builtinlist);
7282                         SAFE_FREE(list);
7283                         *numofforms=0;
7284                         return WERR_NOMEM;
7285                 }
7286
7287                 /* construct the list of form structures */
7288                 for (i=0; i<numbuiltinforms; i++) {
7289                         DEBUGADD(6,("Filling form number [%d]\n",i));
7290                         fill_form_1(&forms_1[i], &builtinlist[i]);
7291                 }
7292
7293                 SAFE_FREE(builtinlist);
7294
7295                 for (; i<*numofforms; i++) {
7296                         DEBUGADD(6,("Filling form number [%d]\n",i));
7297                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7298                 }
7299
7300                 SAFE_FREE(list);
7301
7302                 /* check the required size. */
7303                 for (i=0; i<numbuiltinforms; i++) {
7304                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7305                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7306                 }
7307                 for (; i<*numofforms; i++) {
7308                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7309                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7310                 }
7311
7312                 *needed=buffer_size;
7313
7314                 if (*needed > offered) {
7315                         SAFE_FREE(forms_1);
7316                         *numofforms=0;
7317                         return WERR_INSUFFICIENT_BUFFER;
7318                 }
7319
7320                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7321                         SAFE_FREE(forms_1);
7322                         *numofforms=0;
7323                         return WERR_NOMEM;
7324                 }
7325
7326                 /* fill the buffer with the form structures */
7327                 for (i=0; i<numbuiltinforms; i++) {
7328                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7329                         smb_io_form_1("", buffer, &forms_1[i], 0);
7330                 }
7331                 for (; i<*numofforms; i++) {
7332                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7333                         smb_io_form_1("", buffer, &forms_1[i], 0);
7334                 }
7335
7336                 SAFE_FREE(forms_1);
7337
7338                 return WERR_OK;
7339
7340         default:
7341                 SAFE_FREE(list);
7342                 SAFE_FREE(builtinlist);
7343                 return WERR_UNKNOWN_LEVEL;
7344         }
7345 }
7346
7347 /****************************************************************
7348  _spoolss_GetForm
7349 ****************************************************************/
7350
7351 WERROR _spoolss_GetForm(pipes_struct *p,
7352                         struct spoolss_GetForm *r)
7353 {
7354         uint32 level = r->in.level;
7355         uint32 offered = r->in.offered;
7356         uint32 *needed = r->out.needed;
7357
7358         nt_forms_struct *list=NULL;
7359         nt_forms_struct builtin_form;
7360         bool foundBuiltin;
7361         union spoolss_FormInfo info;
7362         struct spoolss_FormInfo1 form_1;
7363         int numofforms=0, i=0;
7364
7365         /* that's an [in out] buffer */
7366
7367         if (!r->in.buffer && (offered!=0)) {
7368                 return WERR_INVALID_PARAM;
7369         }
7370
7371         DEBUG(4,("_spoolss_GetForm\n"));
7372         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7373         DEBUGADD(5,("Info level [%d]\n",          level));
7374
7375         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7376         if (!foundBuiltin) {
7377                 numofforms = get_ntforms(&list);
7378                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7379
7380                 if (numofforms == 0)
7381                         return WERR_BADFID;
7382         }
7383
7384         ZERO_STRUCT(form_1);
7385
7386         switch (level) {
7387         case 1:
7388                 if (foundBuiltin) {
7389                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7390                 } else {
7391
7392                         /* Check if the requested name is in the list of form structures */
7393                         for (i=0; i<numofforms; i++) {
7394
7395                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7396                                         list[i].name, r->in.form_name));
7397
7398                                 if (strequal(r->in.form_name, list[i].name)) {
7399                                         DEBUGADD(6,("Found form %s number [%d]\n",
7400                                                 r->in.form_name, i));
7401                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7402                                         break;
7403                                 }
7404                         }
7405
7406                         SAFE_FREE(list);
7407                         if (i == numofforms) {
7408                                 return WERR_BADFID;
7409                         }
7410                 }
7411                 /* check the required size. */
7412
7413                 info.info1 = form_1;
7414
7415                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7416
7417                 if (*needed > offered) {
7418                         r->out.info = NULL;
7419                         return WERR_INSUFFICIENT_BUFFER;
7420                 }
7421
7422                 r->out.info->info1 = form_1;
7423
7424                 /* fill the buffer with the form structures */
7425                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7426                         r->in.form_name, i));
7427
7428                 return WERR_OK;
7429
7430         default:
7431                 SAFE_FREE(list);
7432                 return WERR_UNKNOWN_LEVEL;
7433         }
7434 }
7435
7436 /****************************************************************************
7437 ****************************************************************************/
7438
7439 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7440 {
7441         init_unistr(&port->port_name, name);
7442 }
7443
7444 /****************************************************************************
7445  TODO: This probably needs distinguish between TCP/IP and Local ports
7446  somehow.
7447 ****************************************************************************/
7448
7449 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7450 {
7451         init_unistr(&port->port_name, name);
7452         init_unistr(&port->monitor_name, "Local Monitor");
7453         init_unistr(&port->description, SPL_LOCAL_PORT );
7454         port->port_type=PORT_TYPE_WRITE;
7455         port->reserved=0x0;
7456 }
7457
7458
7459 /****************************************************************************
7460  wrapper around the enumer ports command
7461 ****************************************************************************/
7462
7463 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7464 {
7465         char *cmd = lp_enumports_cmd();
7466         char **qlines = NULL;
7467         char *command = NULL;
7468         int numlines;
7469         int ret;
7470         int fd;
7471
7472         *count = 0;
7473         *lines = NULL;
7474
7475         /* if no hook then just fill in the default port */
7476
7477         if ( !*cmd ) {
7478                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7479                         return WERR_NOMEM;
7480                 }
7481                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7482                         TALLOC_FREE(qlines);
7483                         return WERR_NOMEM;
7484                 }
7485                 qlines[1] = NULL;
7486                 numlines = 1;
7487         }
7488         else {
7489                 /* we have a valid enumport command */
7490
7491                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7492                 if (!command) {
7493                         return WERR_NOMEM;
7494                 }
7495
7496                 DEBUG(10,("Running [%s]\n", command));
7497                 ret = smbrun(command, &fd);
7498                 DEBUG(10,("Returned [%d]\n", ret));
7499                 TALLOC_FREE(command);
7500                 if (ret != 0) {
7501                         if (fd != -1) {
7502                                 close(fd);
7503                         }
7504                         return WERR_ACCESS_DENIED;
7505                 }
7506
7507                 numlines = 0;
7508                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7509                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7510                 close(fd);
7511         }
7512
7513         *count = numlines;
7514         *lines = qlines;
7515
7516         return WERR_OK;
7517 }
7518
7519 /****************************************************************************
7520  enumports level 1.
7521 ****************************************************************************/
7522
7523 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7524 {
7525         PORT_INFO_1 *ports=NULL;
7526         int i=0;
7527         WERROR result = WERR_OK;
7528         char **qlines = NULL;
7529         int numlines = 0;
7530
7531         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7532         if (!W_ERROR_IS_OK(result)) {
7533                 TALLOC_FREE(qlines);
7534                 return result;
7535         }
7536
7537         if(numlines) {
7538                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7539                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7540                                   win_errstr(WERR_NOMEM)));
7541                         TALLOC_FREE(qlines);
7542                         return WERR_NOMEM;
7543                 }
7544
7545                 for (i=0; i<numlines; i++) {
7546                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7547                         fill_port_1(&ports[i], qlines[i]);
7548                 }
7549         }
7550         TALLOC_FREE(qlines);
7551
7552         *returned = numlines;
7553
7554         /* check the required size. */
7555         for (i=0; i<*returned; i++) {
7556                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7557                 *needed += spoolss_size_port_info_1(&ports[i]);
7558         }
7559
7560         if (*needed > offered) {
7561                 result = WERR_INSUFFICIENT_BUFFER;
7562                 goto out;
7563         }
7564
7565         if (!rpcbuf_alloc_size(buffer, *needed)) {
7566                 result = WERR_NOMEM;
7567                 goto out;
7568         }
7569
7570         /* fill the buffer with the ports structures */
7571         for (i=0; i<*returned; i++) {
7572                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7573                 smb_io_port_1("", buffer, &ports[i], 0);
7574         }
7575
7576 out:
7577         SAFE_FREE(ports);
7578
7579         if ( !W_ERROR_IS_OK(result) )
7580                 *returned = 0;
7581
7582         return result;
7583 }
7584
7585 /****************************************************************************
7586  enumports level 2.
7587 ****************************************************************************/
7588
7589 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7590 {
7591         PORT_INFO_2 *ports=NULL;
7592         int i=0;
7593         WERROR result = WERR_OK;
7594         char **qlines = NULL;
7595         int numlines = 0;
7596
7597         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7598         if ( !W_ERROR_IS_OK(result)) {
7599                 TALLOC_FREE(qlines);
7600                 return result;
7601         }
7602
7603         if(numlines) {
7604                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7605                         TALLOC_FREE(qlines);
7606                         return WERR_NOMEM;
7607                 }
7608
7609                 for (i=0; i<numlines; i++) {
7610                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7611                         fill_port_2(&(ports[i]), qlines[i]);
7612                 }
7613         }
7614
7615         TALLOC_FREE(qlines);
7616
7617         *returned = numlines;
7618
7619         /* check the required size. */
7620         for (i=0; i<*returned; i++) {
7621                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7622                 *needed += spoolss_size_port_info_2(&ports[i]);
7623         }
7624
7625         if (*needed > offered) {
7626                 result = WERR_INSUFFICIENT_BUFFER;
7627                 goto out;
7628         }
7629
7630         if (!rpcbuf_alloc_size(buffer, *needed)) {
7631                 result = WERR_NOMEM;
7632                 goto out;
7633         }
7634
7635         /* fill the buffer with the ports structures */
7636         for (i=0; i<*returned; i++) {
7637                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7638                 smb_io_port_2("", buffer, &ports[i], 0);
7639         }
7640
7641 out:
7642         SAFE_FREE(ports);
7643
7644         if ( !W_ERROR_IS_OK(result) )
7645                 *returned = 0;
7646
7647         return result;
7648 }
7649
7650 /****************************************************************************
7651  enumports.
7652 ****************************************************************************/
7653
7654 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7655 {
7656         uint32 level = q_u->level;
7657         RPC_BUFFER *buffer = NULL;
7658         uint32 offered = q_u->offered;
7659         uint32 *needed = &r_u->needed;
7660         uint32 *returned = &r_u->returned;
7661
7662         /* that's an [in out] buffer */
7663
7664         if (!q_u->buffer && (offered!=0)) {
7665                 return WERR_INVALID_PARAM;
7666         }
7667
7668         rpcbuf_move(q_u->buffer, &r_u->buffer);
7669         buffer = r_u->buffer;
7670
7671         DEBUG(4,("_spoolss_enumports\n"));
7672
7673         *returned=0;
7674         *needed=0;
7675
7676         switch (level) {
7677         case 1:
7678                 return enumports_level_1(buffer, offered, needed, returned);
7679         case 2:
7680                 return enumports_level_2(buffer, offered, needed, returned);
7681         default:
7682                 return WERR_UNKNOWN_LEVEL;
7683         }
7684 }
7685
7686 /****************************************************************************
7687 ****************************************************************************/
7688
7689 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7690                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7691                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7692                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7693                                 POLICY_HND *handle)
7694 {
7695         NT_PRINTER_INFO_LEVEL *printer = NULL;
7696         fstring name;
7697         int     snum;
7698         WERROR err = WERR_OK;
7699
7700         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7701                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7702                 return WERR_NOMEM;
7703         }
7704
7705         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7706         if (!convert_printer_info(info, printer, 2)) {
7707                 free_a_printer(&printer, 2);
7708                 return WERR_NOMEM;
7709         }
7710
7711         /* check to see if the printer already exists */
7712
7713         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7714                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7715                         printer->info_2->sharename));
7716                 free_a_printer(&printer, 2);
7717                 return WERR_PRINTER_ALREADY_EXISTS;
7718         }
7719
7720         /* FIXME!!!  smbd should check to see if the driver is installed before
7721            trying to add a printer like this  --jerry */
7722
7723         if (*lp_addprinter_cmd() ) {
7724                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7725                                        printer) ) {
7726                         free_a_printer(&printer,2);
7727                         return WERR_ACCESS_DENIED;
7728                 }
7729         } else {
7730                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7731                         "smb.conf parameter \"addprinter command\" is defined. This"
7732                         "parameter must exist for this call to succeed\n",
7733                         printer->info_2->sharename ));
7734         }
7735
7736         /* use our primary netbios name since get_a_printer() will convert
7737            it to what the client expects on a case by case basis */
7738
7739         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7740              printer->info_2->sharename);
7741
7742
7743         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7744                 free_a_printer(&printer,2);
7745                 return WERR_ACCESS_DENIED;
7746         }
7747
7748         /* you must be a printer admin to add a new printer */
7749         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7750                 free_a_printer(&printer,2);
7751                 return WERR_ACCESS_DENIED;
7752         }
7753
7754         /*
7755          * Do sanity check on the requested changes for Samba.
7756          */
7757
7758         if (!check_printer_ok(printer->info_2, snum)) {
7759                 free_a_printer(&printer,2);
7760                 return WERR_INVALID_PARAM;
7761         }
7762
7763         /*
7764          * When a printer is created, the drivername bound to the printer is used
7765          * to lookup previously saved driver initialization info, which is then
7766          * bound to the new printer, simulating what happens in the Windows arch.
7767          */
7768
7769         if (!devmode)
7770         {
7771                 set_driver_init(printer, 2);
7772         }
7773         else
7774         {
7775                 /* A valid devmode was included, convert and link it
7776                 */
7777                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7778
7779                 if (!convert_devicemode(printer->info_2->printername, devmode,
7780                                 &printer->info_2->devmode))
7781                         return  WERR_NOMEM;
7782         }
7783
7784         /* write the ASCII on disk */
7785         err = mod_a_printer(printer, 2);
7786         if (!W_ERROR_IS_OK(err)) {
7787                 free_a_printer(&printer,2);
7788                 return err;
7789         }
7790
7791         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7792                 /* Handle open failed - remove addition. */
7793                 del_a_printer(printer->info_2->sharename);
7794                 free_a_printer(&printer,2);
7795                 return WERR_ACCESS_DENIED;
7796         }
7797
7798         update_c_setprinter(False);
7799         free_a_printer(&printer,2);
7800
7801         return WERR_OK;
7802 }
7803
7804 /****************************************************************************
7805 ****************************************************************************/
7806
7807 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7808 {
7809         UNISTR2 *uni_srv_name = q_u->server_name;
7810         uint32 level = q_u->level;
7811         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7812         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7813         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7814         uint32 user_switch = q_u->user_switch;
7815         SPOOL_USER_CTR *user = &q_u->user_ctr;
7816         POLICY_HND *handle = &r_u->handle;
7817
7818         switch (level) {
7819                 case 1:
7820                         /* we don't handle yet */
7821                         /* but I know what to do ... */
7822                         return WERR_UNKNOWN_LEVEL;
7823                 case 2:
7824                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7825                                                             devmode, sdb,
7826                                                             user_switch, user, handle);
7827                 default:
7828                         return WERR_UNKNOWN_LEVEL;
7829         }
7830 }
7831
7832 /****************************************************************************
7833 ****************************************************************************/
7834
7835 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7836 {
7837         uint32 level = q_u->level;
7838         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7839         WERROR err = WERR_OK;
7840         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7841         fstring driver_name;
7842         uint32 version;
7843
7844         ZERO_STRUCT(driver);
7845
7846         if (!convert_printer_driver_info(info, &driver, level)) {
7847                 err = WERR_NOMEM;
7848                 goto done;
7849         }
7850
7851         DEBUG(5,("Cleaning driver's information\n"));
7852         err = clean_up_driver_struct(p, driver, level);
7853         if (!W_ERROR_IS_OK(err))
7854                 goto done;
7855
7856         DEBUG(5,("Moving driver to final destination\n"));
7857         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7858                                                               &err)) ) {
7859                 goto done;
7860         }
7861
7862         if (add_a_printer_driver(driver, level)!=0) {
7863                 err = WERR_ACCESS_DENIED;
7864                 goto done;
7865         }
7866
7867         switch(level) {
7868         case 3:
7869                 fstrcpy(driver_name,
7870                         driver.info_3->name ? driver.info_3->name : "");
7871                 break;
7872         case 6:
7873                 fstrcpy(driver_name,
7874                         driver.info_6->name ?  driver.info_6->name : "");
7875                 break;
7876         }
7877
7878         /*
7879          * I think this is where he DrvUpgradePrinter() hook would be
7880          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7881          * server.  Right now, we just need to send ourselves a message
7882          * to update each printer bound to this driver.   --jerry
7883          */
7884
7885         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7886                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7887                         driver_name));
7888         }
7889
7890         /*
7891          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7892          * decide if the driver init data should be deleted. The rules are:
7893          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7894          *  2) delete init data only if there is no 2k/Xp driver
7895          *  3) always delete init data
7896          * The generalized rule is always use init data from the highest order driver.
7897          * It is necessary to follow the driver install by an initialization step to
7898          * finish off this process.
7899         */
7900         if (level == 3)
7901                 version = driver.info_3->cversion;
7902         else if (level == 6)
7903                 version = driver.info_6->version;
7904         else
7905                 version = -1;
7906         switch (version) {
7907                 /*
7908                  * 9x printer driver - never delete init data
7909                 */
7910                 case 0:
7911                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7912                                         driver_name));
7913                         break;
7914
7915                 /*
7916                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7917                  * there is no 2k/Xp driver init data for this driver name.
7918                 */
7919                 case 2:
7920                 {
7921                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7922
7923                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7924                                 /*
7925                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7926                                 */
7927                                 if (!del_driver_init(driver_name))
7928                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7929                         } else {
7930                                 /*
7931                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7932                                 */
7933                                 free_a_printer_driver(driver1,3);
7934                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7935                                                 driver_name));
7936                         }
7937                 }
7938                 break;
7939
7940                 /*
7941                  * 2k or Xp printer driver - always delete init data
7942                 */
7943                 case 3:
7944                         if (!del_driver_init(driver_name))
7945                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7946                         break;
7947
7948                 default:
7949                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7950                         break;
7951         }
7952
7953
7954 done:
7955         free_a_printer_driver(driver, level);
7956         return err;
7957 }
7958
7959 /********************************************************************
7960  * spoolss_addprinterdriverex
7961  ********************************************************************/
7962
7963 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7964 {
7965         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7966         SPOOL_R_ADDPRINTERDRIVER r_u_local;
7967
7968         /*
7969          * we only support the semantics of AddPrinterDriver()
7970          * i.e. only copy files that are newer than existing ones
7971          */
7972
7973         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7974                 return WERR_ACCESS_DENIED;
7975
7976         ZERO_STRUCT(q_u_local);
7977         ZERO_STRUCT(r_u_local);
7978
7979         /* just pass the information off to _spoolss_addprinterdriver() */
7980         q_u_local.server_name_ptr = q_u->server_name_ptr;
7981         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7982         q_u_local.level = q_u->level;
7983         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7984
7985         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7986 }
7987
7988 /****************************************************************************
7989 ****************************************************************************/
7990
7991 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7992 {
7993         init_unistr(&info->name, name);
7994 }
7995
7996 /****************************************************************************
7997 ****************************************************************************/
7998
7999 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8000 {
8001         char *path = NULL;
8002         char *long_archi = NULL;
8003         char *servername = NULL;
8004         const char *pservername = NULL;
8005         const char *short_archi;
8006         DRIVER_DIRECTORY_1 *info=NULL;
8007         WERROR result = WERR_OK;
8008         TALLOC_CTX *ctx = talloc_tos();
8009
8010         servername = unistr2_to_ascii_talloc(ctx, name);
8011         if (!servername) {
8012                 return WERR_NOMEM;
8013         }
8014         long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8015         if (!long_archi) {
8016                 return WERR_NOMEM;
8017         }
8018
8019         pservername = canon_servername(servername);
8020
8021         if ( !is_myname_or_ipaddr(pservername))
8022                 return WERR_INVALID_PARAM;
8023
8024         if (!(short_archi = get_short_archi(long_archi)))
8025                 return WERR_INVALID_ENVIRONMENT;
8026
8027         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8028                 return WERR_NOMEM;
8029
8030         path = talloc_asprintf(ctx,
8031                         "\\\\%s\\print$\\%s", pservername, short_archi);
8032         if (!path) {
8033                 result = WERR_NOMEM;
8034                 goto out;
8035         }
8036
8037         DEBUG(4,("printer driver directory: [%s]\n", path));
8038
8039         fill_driverdir_1(info, path);
8040
8041         *needed += spoolss_size_driverdir_info_1(info);
8042
8043         if (*needed > offered) {
8044                 result = WERR_INSUFFICIENT_BUFFER;
8045                 goto out;
8046         }
8047
8048         if (!rpcbuf_alloc_size(buffer, *needed)) {
8049                 result = WERR_NOMEM;
8050                 goto out;
8051         }
8052
8053         smb_io_driverdir_1("", buffer, info, 0);
8054
8055 out:
8056         SAFE_FREE(info);
8057
8058         return result;
8059 }
8060
8061 /****************************************************************************
8062 ****************************************************************************/
8063
8064 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8065 {
8066         UNISTR2 *name = &q_u->name;
8067         UNISTR2 *uni_environment = &q_u->environment;
8068         uint32 level = q_u->level;
8069         RPC_BUFFER *buffer = NULL;
8070         uint32 offered = q_u->offered;
8071         uint32 *needed = &r_u->needed;
8072
8073         /* that's an [in out] buffer */
8074
8075         if (!q_u->buffer && (offered!=0)) {
8076                 return WERR_INVALID_PARAM;
8077         }
8078
8079         rpcbuf_move(q_u->buffer, &r_u->buffer);
8080         buffer = r_u->buffer;
8081
8082         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8083
8084         *needed=0;
8085
8086         switch(level) {
8087         case 1:
8088                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8089         default:
8090                 return WERR_UNKNOWN_LEVEL;
8091         }
8092 }
8093
8094 /****************************************************************************
8095 ****************************************************************************/
8096
8097 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8098 {
8099         POLICY_HND *handle = &q_u->handle;
8100         uint32 idx               = q_u->index;
8101         uint32 in_value_len      = q_u->valuesize;
8102         uint32 in_data_len       = q_u->datasize;
8103         uint32 *out_max_value_len = &r_u->valuesize;
8104         uint16 **out_value       = &r_u->value;
8105         uint32 *out_value_len    = &r_u->realvaluesize;
8106         uint32 *out_type         = &r_u->type;
8107         uint32 *out_max_data_len = &r_u->datasize;
8108         uint8  **data_out        = &r_u->data;
8109         uint32 *out_data_len     = &r_u->realdatasize;
8110
8111         NT_PRINTER_INFO_LEVEL *printer = NULL;
8112
8113         uint32          biggest_valuesize;
8114         uint32          biggest_datasize;
8115         uint32          data_len;
8116         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8117         int             snum;
8118         WERROR          result;
8119         REGISTRY_VALUE  *val = NULL;
8120         NT_PRINTER_DATA *p_data;
8121         int             i, key_index, num_values;
8122         int             name_length;
8123
8124         *out_type = 0;
8125
8126         *out_max_data_len = 0;
8127         *data_out         = NULL;
8128         *out_data_len     = 0;
8129
8130         DEBUG(5,("spoolss_enumprinterdata\n"));
8131
8132         if (!Printer) {
8133                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8134                 return WERR_BADFID;
8135         }
8136
8137         if (!get_printer_snum(p,handle, &snum, NULL))
8138                 return WERR_BADFID;
8139
8140         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8141         if (!W_ERROR_IS_OK(result))
8142                 return result;
8143
8144         p_data = printer->info_2->data;
8145         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8146
8147         result = WERR_OK;
8148
8149         /*
8150          * The NT machine wants to know the biggest size of value and data
8151          *
8152          * cf: MSDN EnumPrinterData remark section
8153          */
8154
8155         if ( !in_value_len && !in_data_len && (key_index != -1) )
8156         {
8157                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8158
8159                 biggest_valuesize = 0;
8160                 biggest_datasize  = 0;
8161
8162                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8163
8164                 for ( i=0; i<num_values; i++ )
8165                 {
8166                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8167
8168                         name_length = strlen(val->valuename);
8169                         if ( strlen(val->valuename) > biggest_valuesize )
8170                                 biggest_valuesize = name_length;
8171
8172                         if ( val->size > biggest_datasize )
8173                                 biggest_datasize = val->size;
8174
8175                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8176                                 biggest_datasize));
8177                 }
8178
8179                 /* the value is an UNICODE string but real_value_size is the length
8180                    in bytes including the trailing 0 */
8181
8182                 *out_value_len = 2 * (1+biggest_valuesize);
8183                 *out_data_len  = biggest_datasize;
8184
8185                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8186
8187                 goto done;
8188         }
8189
8190         /*
8191          * the value len is wrong in NT sp3
8192          * that's the number of bytes not the number of unicode chars
8193          */
8194
8195         if ( key_index != -1 )
8196                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8197
8198         if ( !val )
8199         {
8200
8201                 /* out_value should default to "" or else NT4 has
8202                    problems unmarshalling the response */
8203
8204                 *out_max_value_len=(in_value_len/sizeof(uint16));
8205
8206                 if (in_value_len) {
8207                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8208                         {
8209                                 result = WERR_NOMEM;
8210                                 goto done;
8211                         }
8212                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8213                 } else {
8214                         *out_value=NULL;
8215                         *out_value_len = 0;
8216                 }
8217
8218                 /* the data is counted in bytes */
8219
8220                 *out_max_data_len = in_data_len;
8221                 *out_data_len     = in_data_len;
8222
8223                 /* only allocate when given a non-zero data_len */
8224
8225                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8226                 {
8227                         result = WERR_NOMEM;
8228                         goto done;
8229                 }
8230
8231                 result = WERR_NO_MORE_ITEMS;
8232         }
8233         else
8234         {
8235                 /*
8236                  * the value is:
8237                  * - counted in bytes in the request
8238                  * - counted in UNICODE chars in the max reply
8239                  * - counted in bytes in the real size
8240                  *
8241                  * take a pause *before* coding not *during* coding
8242                  */
8243
8244                 /* name */
8245                 *out_max_value_len=(in_value_len/sizeof(uint16));
8246                 if (in_value_len) {
8247                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8248                         {
8249                                 result = WERR_NOMEM;
8250                                 goto done;
8251                         }
8252
8253                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8254                 } else {
8255                         *out_value = NULL;
8256                         *out_value_len = 0;
8257                 }
8258
8259                 /* type */
8260
8261                 *out_type = regval_type( val );
8262
8263                 /* data - counted in bytes */
8264
8265                 *out_max_data_len = in_data_len;
8266                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8267                 {
8268                         result = WERR_NOMEM;
8269                         goto done;
8270                 }
8271                 data_len = regval_size(val);
8272                 if ( *data_out && data_len )
8273                         memcpy( *data_out, regval_data_p(val), data_len );
8274                 *out_data_len = data_len;
8275         }
8276
8277 done:
8278         free_a_printer(&printer, 2);
8279         return result;
8280 }
8281
8282 /****************************************************************************
8283 ****************************************************************************/
8284
8285 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8286 {
8287         POLICY_HND              *handle = &q_u->handle;
8288         UNISTR2                 *value = &q_u->value;
8289         uint32                  type = q_u->type;
8290         uint8                   *data = q_u->data;
8291         uint32                  real_len = q_u->real_len;
8292
8293         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8294         int                     snum=0;
8295         WERROR                  status = WERR_OK;
8296         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8297         fstring                 valuename;
8298
8299         DEBUG(5,("spoolss_setprinterdata\n"));
8300
8301         if (!Printer) {
8302                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8303                 return WERR_BADFID;
8304         }
8305
8306         if ( Printer->printer_type == SPLHND_SERVER ) {
8307                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8308                 return WERR_INVALID_PARAM;
8309         }
8310
8311         if (!get_printer_snum(p,handle, &snum, NULL))
8312                 return WERR_BADFID;
8313
8314         /*
8315          * Access check : NT returns "access denied" if you make a
8316          * SetPrinterData call without the necessary privildge.
8317          * we were originally returning OK if nothing changed
8318          * which made Win2k issue **a lot** of SetPrinterData
8319          * when connecting to a printer  --jerry
8320          */
8321
8322         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8323         {
8324                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8325                 status = WERR_ACCESS_DENIED;
8326                 goto done;
8327         }
8328
8329         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8330         if (!W_ERROR_IS_OK(status))
8331                 return status;
8332
8333         unistr2_to_ascii(valuename, value, sizeof(valuename));
8334
8335         /*
8336          * When client side code sets a magic printer data key, detect it and save
8337          * the current printer data and the magic key's data (its the DEVMODE) for
8338          * future printer/driver initializations.
8339          */
8340         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8341         {
8342                 /* Set devmode and printer initialization info */
8343                 status = save_driver_init( printer, 2, data, real_len );
8344
8345                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8346         }
8347         else
8348         {
8349         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8350                                         type, data, real_len );
8351                 if ( W_ERROR_IS_OK(status) )
8352                         status = mod_a_printer(printer, 2);
8353         }
8354
8355 done:
8356         free_a_printer(&printer, 2);
8357
8358         return status;
8359 }
8360
8361 /****************************************************************************
8362 ****************************************************************************/
8363
8364 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8365 {
8366         POLICY_HND      *handle = &q_u->handle;
8367         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8368         int             snum;
8369
8370         DEBUG(5,("_spoolss_resetprinter\n"));
8371
8372         /*
8373          * All we do is to check to see if the handle and queue is valid.
8374          * This call really doesn't mean anything to us because we only
8375          * support RAW printing.   --jerry
8376          */
8377
8378         if (!Printer) {
8379                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8380                 return WERR_BADFID;
8381         }
8382
8383         if (!get_printer_snum(p,handle, &snum, NULL))
8384                 return WERR_BADFID;
8385
8386
8387         /* blindly return success */
8388         return WERR_OK;
8389 }
8390
8391 /****************************************************************
8392  _spoolss_DeletePrinterData
8393 ****************************************************************/
8394
8395 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8396                                   struct spoolss_DeletePrinterData *r)
8397 {
8398         POLICY_HND      *handle = r->in.handle;
8399         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8400         int             snum=0;
8401         WERROR          status = WERR_OK;
8402         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8403
8404         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8405
8406         if (!Printer) {
8407                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8408                         OUR_HANDLE(handle)));
8409                 return WERR_BADFID;
8410         }
8411
8412         if (!get_printer_snum(p, handle, &snum, NULL))
8413                 return WERR_BADFID;
8414
8415         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8416                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8417                         "printer properties change denied by handle\n"));
8418                 return WERR_ACCESS_DENIED;
8419         }
8420
8421         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8422         if (!W_ERROR_IS_OK(status))
8423                 return status;
8424
8425         if (!r->in.value_name) {
8426                 free_a_printer(&printer, 2);
8427                 return WERR_NOMEM;
8428         }
8429
8430         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8431                                         r->in.value_name );
8432
8433         if ( W_ERROR_IS_OK(status) )
8434                 mod_a_printer( printer, 2 );
8435
8436         free_a_printer(&printer, 2);
8437
8438         return status;
8439 }
8440
8441 /****************************************************************
8442  _spoolss_AddForm
8443 ****************************************************************/
8444
8445 WERROR _spoolss_AddForm(pipes_struct *p,
8446                         struct spoolss_AddForm *r)
8447 {
8448         POLICY_HND *handle = r->in.handle;
8449         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8450         nt_forms_struct tmpForm;
8451         int snum;
8452         WERROR status = WERR_OK;
8453         NT_PRINTER_INFO_LEVEL *printer = NULL;
8454
8455         int count=0;
8456         nt_forms_struct *list=NULL;
8457         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8458
8459         DEBUG(5,("_spoolss_AddForm\n"));
8460
8461         if (!Printer) {
8462                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8463                         OUR_HANDLE(handle)));
8464                 return WERR_BADFID;
8465         }
8466
8467
8468         /* forms can be added on printer of on the print server handle */
8469
8470         if ( Printer->printer_type == SPLHND_PRINTER )
8471         {
8472                 if (!get_printer_snum(p,handle, &snum, NULL))
8473                         return WERR_BADFID;
8474
8475                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8476                 if (!W_ERROR_IS_OK(status))
8477                         goto done;
8478         }
8479
8480         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8481                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8482                 status = WERR_ACCESS_DENIED;
8483                 goto done;
8484         }
8485
8486         /* can't add if builtin */
8487
8488         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8489                 status = WERR_FILE_EXISTS;
8490                 goto done;
8491         }
8492
8493         count = get_ntforms(&list);
8494
8495         if(!add_a_form(&list, form, &count)) {
8496                 status =  WERR_NOMEM;
8497                 goto done;
8498         }
8499
8500         write_ntforms(&list, count);
8501
8502         /*
8503          * ChangeID must always be set if this is a printer
8504          */
8505
8506         if ( Printer->printer_type == SPLHND_PRINTER )
8507                 status = mod_a_printer(printer, 2);
8508
8509 done:
8510         if ( printer )
8511                 free_a_printer(&printer, 2);
8512         SAFE_FREE(list);
8513
8514         return status;
8515 }
8516
8517 /****************************************************************
8518  _spoolss_DeleteForm
8519 ****************************************************************/
8520
8521 WERROR _spoolss_DeleteForm(pipes_struct *p,
8522                            struct spoolss_DeleteForm *r)
8523 {
8524         POLICY_HND *handle = r->in.handle;
8525         const char *form_name = r->in.form_name;
8526         nt_forms_struct tmpForm;
8527         int count=0;
8528         nt_forms_struct *list=NULL;
8529         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8530         int snum;
8531         WERROR status = WERR_OK;
8532         NT_PRINTER_INFO_LEVEL *printer = NULL;
8533
8534         DEBUG(5,("_spoolss_DeleteForm\n"));
8535
8536         if (!Printer) {
8537                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8538                         OUR_HANDLE(handle)));
8539                 return WERR_BADFID;
8540         }
8541
8542         /* forms can be deleted on printer of on the print server handle */
8543
8544         if ( Printer->printer_type == SPLHND_PRINTER )
8545         {
8546                 if (!get_printer_snum(p,handle, &snum, NULL))
8547                         return WERR_BADFID;
8548
8549                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8550                 if (!W_ERROR_IS_OK(status))
8551                         goto done;
8552         }
8553
8554         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8555                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8556                 status = WERR_ACCESS_DENIED;
8557                 goto done;
8558         }
8559
8560         /* can't delete if builtin */
8561
8562         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8563                 status = WERR_INVALID_PARAM;
8564                 goto done;
8565         }
8566
8567         count = get_ntforms(&list);
8568
8569         if ( !delete_a_form(&list, form_name, &count, &status ))
8570                 goto done;
8571
8572         /*
8573          * ChangeID must always be set if this is a printer
8574          */
8575
8576         if ( Printer->printer_type == SPLHND_PRINTER )
8577                 status = mod_a_printer(printer, 2);
8578
8579 done:
8580         if ( printer )
8581                 free_a_printer(&printer, 2);
8582         SAFE_FREE(list);
8583
8584         return status;
8585 }
8586
8587 /****************************************************************
8588  _spoolss_SetForm
8589 ****************************************************************/
8590
8591 WERROR _spoolss_SetForm(pipes_struct *p,
8592                         struct spoolss_SetForm *r)
8593 {
8594         POLICY_HND *handle = r->in.handle;
8595         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8596         nt_forms_struct tmpForm;
8597         int snum;
8598         WERROR status = WERR_OK;
8599         NT_PRINTER_INFO_LEVEL *printer = NULL;
8600
8601         int count=0;
8602         nt_forms_struct *list=NULL;
8603         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8604
8605         DEBUG(5,("_spoolss_SetForm\n"));
8606
8607         if (!Printer) {
8608                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8609                         OUR_HANDLE(handle)));
8610                 return WERR_BADFID;
8611         }
8612
8613         /* forms can be modified on printer of on the print server handle */
8614
8615         if ( Printer->printer_type == SPLHND_PRINTER )
8616         {
8617                 if (!get_printer_snum(p,handle, &snum, NULL))
8618                         return WERR_BADFID;
8619
8620                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8621                 if (!W_ERROR_IS_OK(status))
8622                         goto done;
8623         }
8624
8625         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8626                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8627                 status = WERR_ACCESS_DENIED;
8628                 goto done;
8629         }
8630
8631         /* can't set if builtin */
8632         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8633                 status = WERR_INVALID_PARAM;
8634                 goto done;
8635         }
8636
8637         count = get_ntforms(&list);
8638         update_a_form(&list, form, count);
8639         write_ntforms(&list, count);
8640
8641         /*
8642          * ChangeID must always be set if this is a printer
8643          */
8644
8645         if ( Printer->printer_type == SPLHND_PRINTER )
8646                 status = mod_a_printer(printer, 2);
8647
8648
8649 done:
8650         if ( printer )
8651                 free_a_printer(&printer, 2);
8652         SAFE_FREE(list);
8653
8654         return status;
8655 }
8656
8657 /****************************************************************************
8658  enumprintprocessors level 1.
8659 ****************************************************************************/
8660
8661 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8662 {
8663         PRINTPROCESSOR_1 *info_1=NULL;
8664         WERROR result = WERR_OK;
8665
8666         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8667                 return WERR_NOMEM;
8668
8669         (*returned) = 0x1;
8670
8671         init_unistr(&info_1->name, "winprint");
8672
8673         *needed += spoolss_size_printprocessor_info_1(info_1);
8674
8675         if (*needed > offered) {
8676                 result = WERR_INSUFFICIENT_BUFFER;
8677                 goto out;
8678         }
8679
8680         if (!rpcbuf_alloc_size(buffer, *needed)) {
8681                 result = WERR_NOMEM;
8682                 goto out;
8683         }
8684
8685         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8686
8687 out:
8688         SAFE_FREE(info_1);
8689
8690         if ( !W_ERROR_IS_OK(result) )
8691                 *returned = 0;
8692
8693         return result;
8694 }
8695
8696 /****************************************************************************
8697 ****************************************************************************/
8698
8699 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8700 {
8701         uint32 level = q_u->level;
8702         RPC_BUFFER *buffer = NULL;
8703         uint32 offered = q_u->offered;
8704         uint32 *needed = &r_u->needed;
8705         uint32 *returned = &r_u->returned;
8706
8707         /* that's an [in out] buffer */
8708
8709         if (!q_u->buffer && (offered!=0)) {
8710                 return WERR_INVALID_PARAM;
8711         }
8712
8713         rpcbuf_move(q_u->buffer, &r_u->buffer);
8714         buffer = r_u->buffer;
8715
8716         DEBUG(5,("spoolss_enumprintprocessors\n"));
8717
8718         /*
8719          * Enumerate the print processors ...
8720          *
8721          * Just reply with "winprint", to keep NT happy
8722          * and I can use my nice printer checker.
8723          */
8724
8725         *returned=0;
8726         *needed=0;
8727
8728         switch (level) {
8729         case 1:
8730                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8731         default:
8732                 return WERR_UNKNOWN_LEVEL;
8733         }
8734 }
8735
8736 /****************************************************************************
8737  enumprintprocdatatypes level 1.
8738 ****************************************************************************/
8739
8740 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8741 {
8742         PRINTPROCDATATYPE_1 *info_1=NULL;
8743         WERROR result = WERR_OK;
8744
8745         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8746                 return WERR_NOMEM;
8747
8748         (*returned) = 0x1;
8749
8750         init_unistr(&info_1->name, "RAW");
8751
8752         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8753
8754         if (*needed > offered) {
8755                 result = WERR_INSUFFICIENT_BUFFER;
8756                 goto out;
8757         }
8758
8759         if (!rpcbuf_alloc_size(buffer, *needed)) {
8760                 result = WERR_NOMEM;
8761                 goto out;
8762         }
8763
8764         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8765
8766 out:
8767         SAFE_FREE(info_1);
8768
8769         if ( !W_ERROR_IS_OK(result) )
8770                 *returned = 0;
8771
8772         return result;
8773 }
8774
8775 /****************************************************************************
8776 ****************************************************************************/
8777
8778 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8779 {
8780         uint32 level = q_u->level;
8781         RPC_BUFFER *buffer = NULL;
8782         uint32 offered = q_u->offered;
8783         uint32 *needed = &r_u->needed;
8784         uint32 *returned = &r_u->returned;
8785
8786         /* that's an [in out] buffer */
8787
8788         if (!q_u->buffer && (offered!=0)) {
8789                 return WERR_INVALID_PARAM;
8790         }
8791
8792         rpcbuf_move(q_u->buffer, &r_u->buffer);
8793         buffer = r_u->buffer;
8794
8795         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8796
8797         *returned=0;
8798         *needed=0;
8799
8800         switch (level) {
8801         case 1:
8802                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8803         default:
8804                 return WERR_UNKNOWN_LEVEL;
8805         }
8806 }
8807
8808 /****************************************************************************
8809  enumprintmonitors level 1.
8810 ****************************************************************************/
8811
8812 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8813 {
8814         PRINTMONITOR_1 *info_1;
8815         WERROR result = WERR_OK;
8816         int i;
8817
8818         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8819                 return WERR_NOMEM;
8820
8821         *returned = 2;
8822
8823         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8824         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8825
8826         for ( i=0; i<*returned; i++ ) {
8827                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8828         }
8829
8830         if (*needed > offered) {
8831                 result = WERR_INSUFFICIENT_BUFFER;
8832                 goto out;
8833         }
8834
8835         if (!rpcbuf_alloc_size(buffer, *needed)) {
8836                 result = WERR_NOMEM;
8837                 goto out;
8838         }
8839
8840         for ( i=0; i<*returned; i++ ) {
8841                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8842         }
8843
8844 out:
8845         SAFE_FREE(info_1);
8846
8847         if ( !W_ERROR_IS_OK(result) )
8848                 *returned = 0;
8849
8850         return result;
8851 }
8852
8853 /****************************************************************************
8854  enumprintmonitors level 2.
8855 ****************************************************************************/
8856
8857 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8858 {
8859         PRINTMONITOR_2 *info_2;
8860         WERROR result = WERR_OK;
8861         int i;
8862
8863         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8864                 return WERR_NOMEM;
8865
8866         *returned = 2;
8867
8868         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8869         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8870         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8871
8872         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8873         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8874         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8875
8876         for ( i=0; i<*returned; i++ ) {
8877                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8878         }
8879
8880         if (*needed > offered) {
8881                 result = WERR_INSUFFICIENT_BUFFER;
8882                 goto out;
8883         }
8884
8885         if (!rpcbuf_alloc_size(buffer, *needed)) {
8886                 result = WERR_NOMEM;
8887                 goto out;
8888         }
8889
8890         for ( i=0; i<*returned; i++ ) {
8891                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8892         }
8893
8894 out:
8895         SAFE_FREE(info_2);
8896
8897         if ( !W_ERROR_IS_OK(result) )
8898                 *returned = 0;
8899
8900         return result;
8901 }
8902
8903 /****************************************************************************
8904 ****************************************************************************/
8905
8906 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8907 {
8908         uint32 level = q_u->level;
8909         RPC_BUFFER *buffer = NULL;
8910         uint32 offered = q_u->offered;
8911         uint32 *needed = &r_u->needed;
8912         uint32 *returned = &r_u->returned;
8913
8914         /* that's an [in out] buffer */
8915
8916         if (!q_u->buffer && (offered!=0)) {
8917                 return WERR_INVALID_PARAM;
8918         }
8919
8920         rpcbuf_move(q_u->buffer, &r_u->buffer);
8921         buffer = r_u->buffer;
8922
8923         DEBUG(5,("spoolss_enumprintmonitors\n"));
8924
8925         /*
8926          * Enumerate the print monitors ...
8927          *
8928          * Just reply with "Local Port", to keep NT happy
8929          * and I can use my nice printer checker.
8930          */
8931
8932         *returned=0;
8933         *needed=0;
8934
8935         switch (level) {
8936         case 1:
8937                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8938         case 2:
8939                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8940         default:
8941                 return WERR_UNKNOWN_LEVEL;
8942         }
8943 }
8944
8945 /****************************************************************************
8946 ****************************************************************************/
8947
8948 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8949                              NT_PRINTER_INFO_LEVEL *ntprinter,
8950                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8951                              uint32 *needed)
8952 {
8953         int i=0;
8954         bool found=False;
8955         JOB_INFO_1 *info_1=NULL;
8956         WERROR result = WERR_OK;
8957
8958         info_1=SMB_MALLOC_P(JOB_INFO_1);
8959
8960         if (info_1 == NULL) {
8961                 return WERR_NOMEM;
8962         }
8963
8964         for (i=0; i<count && found==False; i++) {
8965                 if ((*queue)[i].job==(int)jobid)
8966                         found=True;
8967         }
8968
8969         if (found==False) {
8970                 SAFE_FREE(info_1);
8971                 /* NT treats not found as bad param... yet another bad choice */
8972                 return WERR_INVALID_PARAM;
8973         }
8974
8975         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8976
8977         *needed += spoolss_size_job_info_1(info_1);
8978
8979         if (*needed > offered) {
8980                 result = WERR_INSUFFICIENT_BUFFER;
8981                 goto out;
8982         }
8983
8984         if (!rpcbuf_alloc_size(buffer, *needed)) {
8985                 result = WERR_NOMEM;
8986                 goto out;
8987         }
8988
8989         smb_io_job_info_1("", buffer, info_1, 0);
8990
8991 out:
8992         SAFE_FREE(info_1);
8993
8994         return result;
8995 }
8996
8997 /****************************************************************************
8998 ****************************************************************************/
8999
9000 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9001                              NT_PRINTER_INFO_LEVEL *ntprinter,
9002                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9003                              uint32 *needed)
9004 {
9005         int             i = 0;
9006         bool            found = False;
9007         JOB_INFO_2      *info_2;
9008         WERROR          result;
9009         DEVICEMODE      *devmode = NULL;
9010         NT_DEVICEMODE   *nt_devmode = NULL;
9011
9012         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9013                 return WERR_NOMEM;
9014
9015         ZERO_STRUCTP(info_2);
9016
9017         for ( i=0; i<count && found==False; i++ )
9018         {
9019                 if ((*queue)[i].job == (int)jobid)
9020                         found = True;
9021         }
9022
9023         if ( !found ) {
9024                 /* NT treats not found as bad param... yet another bad
9025                    choice */
9026                 result = WERR_INVALID_PARAM;
9027                 goto done;
9028         }
9029
9030         /*
9031          * if the print job does not have a DEVMODE associated with it,
9032          * just use the one for the printer. A NULL devicemode is not
9033          *  a failure condition
9034          */
9035
9036         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9037                 devmode = construct_dev_mode(lp_const_servicename(snum));
9038         else {
9039                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9040                         ZERO_STRUCTP( devmode );
9041                         convert_nt_devicemode( devmode, nt_devmode );
9042                 }
9043         }
9044
9045         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9046
9047         *needed += spoolss_size_job_info_2(info_2);
9048
9049         if (*needed > offered) {
9050                 result = WERR_INSUFFICIENT_BUFFER;
9051                 goto done;
9052         }
9053
9054         if (!rpcbuf_alloc_size(buffer, *needed)) {
9055                 result = WERR_NOMEM;
9056                 goto done;
9057         }
9058
9059         smb_io_job_info_2("", buffer, info_2, 0);
9060
9061         result = WERR_OK;
9062
9063  done:
9064         /* Cleanup allocated memory */
9065
9066         free_job_info_2(info_2);        /* Also frees devmode */
9067         SAFE_FREE(info_2);
9068
9069         return result;
9070 }
9071
9072 /****************************************************************************
9073 ****************************************************************************/
9074
9075 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9076 {
9077         POLICY_HND *handle = &q_u->handle;
9078         uint32 jobid = q_u->jobid;
9079         uint32 level = q_u->level;
9080         RPC_BUFFER *buffer = NULL;
9081         uint32 offered = q_u->offered;
9082         uint32 *needed = &r_u->needed;
9083         WERROR          wstatus = WERR_OK;
9084         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9085         int snum;
9086         int count;
9087         print_queue_struct      *queue = NULL;
9088         print_status_struct prt_status;
9089
9090         /* that's an [in out] buffer */
9091
9092         if (!q_u->buffer && (offered!=0)) {
9093                 return WERR_INVALID_PARAM;
9094         }
9095
9096         rpcbuf_move(q_u->buffer, &r_u->buffer);
9097         buffer = r_u->buffer;
9098
9099         DEBUG(5,("spoolss_getjob\n"));
9100
9101         *needed = 0;
9102
9103         if (!get_printer_snum(p, handle, &snum, NULL))
9104                 return WERR_BADFID;
9105
9106         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9107         if ( !W_ERROR_IS_OK(wstatus) )
9108                 return wstatus;
9109
9110         count = print_queue_status(snum, &queue, &prt_status);
9111
9112         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9113                      count, prt_status.status, prt_status.message));
9114
9115         switch ( level ) {
9116         case 1:
9117                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9118                                 buffer, offered, needed);
9119                         break;
9120         case 2:
9121                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9122                                 buffer, offered, needed);
9123                         break;
9124         default:
9125                         wstatus = WERR_UNKNOWN_LEVEL;
9126                         break;
9127         }
9128
9129         SAFE_FREE(queue);
9130         free_a_printer( &ntprinter, 2 );
9131
9132         return wstatus;
9133 }
9134
9135 /****************************************************************
9136  _spoolss_GetPrinterDataEx
9137
9138  From MSDN documentation of GetPrinterDataEx: pass request
9139  to GetPrinterData if key is "PrinterDriverData".
9140 ****************************************************************/
9141
9142 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9143                                  struct spoolss_GetPrinterDataEx *r)
9144 {
9145         POLICY_HND      *handle = r->in.handle;
9146         uint8           *data = NULL;
9147         const char      *keyname = r->in.key_name;
9148         const char      *valuename = r->in.value_name;
9149
9150         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9151
9152         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9153         int                     snum = 0;
9154         WERROR                  status = WERR_OK;
9155
9156         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9157
9158         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9159                 keyname, valuename));
9160
9161         /* in case of problem, return some default values */
9162
9163         *r->out.needed  = 0;
9164         *r->out.type    = 0;
9165
9166         if (!Printer) {
9167                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9168                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9169                 status = WERR_BADFID;
9170                 goto done;
9171         }
9172
9173         /* Is the handle to a printer or to the server? */
9174
9175         if (Printer->printer_type == SPLHND_SERVER) {
9176                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9177                         "Not implemented for server handles yet\n"));
9178                 status = WERR_INVALID_PARAM;
9179                 goto done;
9180         }
9181
9182         if ( !get_printer_snum(p,handle, &snum, NULL) )
9183                 return WERR_BADFID;
9184
9185         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9186         if ( !W_ERROR_IS_OK(status) )
9187                 goto done;
9188
9189         /* check to see if the keyname is valid */
9190         if ( !strlen(keyname) ) {
9191                 status = WERR_INVALID_PARAM;
9192                 goto done;
9193         }
9194
9195         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9196                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9197                         "Invalid keyname [%s]\n", keyname ));
9198                 free_a_printer( &printer, 2 );
9199                 status = WERR_BADFILE;
9200                 goto done;
9201         }
9202
9203         /* When given a new keyname, we should just create it */
9204
9205         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9206                                      r->out.type, &data, r->out.needed,
9207                                      r->in.offered );
9208
9209         if (*r->out.needed > r->in.offered) {
9210                 status = WERR_MORE_DATA;
9211         }
9212
9213         if (W_ERROR_IS_OK(status)) {
9214                 memcpy(r->out.buffer, data, r->in.offered);
9215         }
9216
9217 done:
9218         if ( printer )
9219         free_a_printer( &printer, 2 );
9220
9221         return status;
9222 }
9223
9224 /********************************************************************
9225  * spoolss_setprinterdataex
9226  ********************************************************************/
9227
9228 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9229 {
9230         POLICY_HND              *handle = &q_u->handle;
9231         uint32                  type = q_u->type;
9232         uint8                   *data = q_u->data;
9233         uint32                  real_len = q_u->real_len;
9234
9235         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9236         int                     snum = 0;
9237         WERROR                  status = WERR_OK;
9238         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9239         fstring                 valuename;
9240         fstring                 keyname;
9241         char                    *oid_string;
9242
9243         DEBUG(4,("_spoolss_setprinterdataex\n"));
9244
9245         /* From MSDN documentation of SetPrinterDataEx: pass request to
9246            SetPrinterData if key is "PrinterDriverData" */
9247
9248         if (!Printer) {
9249                 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9250                 return WERR_BADFID;
9251         }
9252
9253         if ( Printer->printer_type == SPLHND_SERVER ) {
9254                 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9255                 return WERR_INVALID_PARAM;
9256         }
9257
9258         if ( !get_printer_snum(p,handle, &snum, NULL) )
9259                 return WERR_BADFID;
9260
9261         /*
9262          * Access check : NT returns "access denied" if you make a
9263          * SetPrinterData call without the necessary privildge.
9264          * we were originally returning OK if nothing changed
9265          * which made Win2k issue **a lot** of SetPrinterData
9266          * when connecting to a printer  --jerry
9267          */
9268
9269         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9270         {
9271                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9272                 return WERR_ACCESS_DENIED;
9273         }
9274
9275         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9276         if (!W_ERROR_IS_OK(status))
9277                 return status;
9278
9279         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9280         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9281
9282         /* check for OID in valuename */
9283
9284         if ( (oid_string = strchr( valuename, ',' )) != NULL )
9285         {
9286                 *oid_string = '\0';
9287                 oid_string++;
9288         }
9289
9290         /* save the registry data */
9291
9292         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9293
9294         if ( W_ERROR_IS_OK(status) )
9295         {
9296                 /* save the OID if one was specified */
9297                 if ( oid_string ) {
9298                         fstrcat( keyname, "\\" );
9299                         fstrcat( keyname, SPOOL_OID_KEY );
9300
9301                         /*
9302                          * I'm not checking the status here on purpose.  Don't know
9303                          * if this is right, but I'm returning the status from the
9304                          * previous set_printer_dataex() call.  I have no idea if
9305                          * this is right.    --jerry
9306                          */
9307
9308                         set_printer_dataex( printer, keyname, valuename,
9309                                             REG_SZ, (uint8 *)oid_string,
9310                                             strlen(oid_string)+1 );
9311                 }
9312
9313                 status = mod_a_printer(printer, 2);
9314         }
9315
9316         free_a_printer(&printer, 2);
9317
9318         return status;
9319 }
9320
9321 /****************************************************************
9322  _spoolss_DeletePrinterDataEx
9323 ****************************************************************/
9324
9325 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9326                                     struct spoolss_DeletePrinterDataEx *r)
9327 {
9328         POLICY_HND      *handle = r->in.handle;
9329         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9330         int             snum=0;
9331         WERROR          status = WERR_OK;
9332         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9333
9334         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9335
9336         if (!Printer) {
9337                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9338                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9339                 return WERR_BADFID;
9340         }
9341
9342         if (!get_printer_snum(p, handle, &snum, NULL))
9343                 return WERR_BADFID;
9344
9345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9346                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9347                         "printer properties change denied by handle\n"));
9348                 return WERR_ACCESS_DENIED;
9349         }
9350
9351         if (!r->in.value_name || !r->in.key_name) {
9352                 return WERR_NOMEM;
9353         }
9354
9355         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9356         if (!W_ERROR_IS_OK(status))
9357                 return status;
9358
9359         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9360
9361         if ( W_ERROR_IS_OK(status) )
9362                 mod_a_printer( printer, 2 );
9363
9364         free_a_printer(&printer, 2);
9365
9366         return status;
9367 }
9368
9369 /********************************************************************
9370  * spoolss_enumprinterkey
9371  ********************************************************************/
9372
9373
9374 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9375 {
9376         fstring         key;
9377         fstring         *keynames = NULL;
9378         uint16          *enumkeys = NULL;
9379         int             num_keys;
9380         int             printerkey_len;
9381         POLICY_HND      *handle = &q_u->handle;
9382         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9383         NT_PRINTER_DATA *data;
9384         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9385         int             snum = 0;
9386         WERROR          status = WERR_BADFILE;
9387
9388
9389         DEBUG(4,("_spoolss_enumprinterkey\n"));
9390
9391         if (!Printer) {
9392                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9393                 return WERR_BADFID;
9394         }
9395
9396         if ( !get_printer_snum(p,handle, &snum, NULL) )
9397                 return WERR_BADFID;
9398
9399         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9400         if (!W_ERROR_IS_OK(status))
9401                 return status;
9402
9403         /* get the list of subkey names */
9404
9405         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9406         data = printer->info_2->data;
9407
9408         num_keys = get_printer_subkeys( data, key, &keynames );
9409
9410         if ( num_keys == -1 ) {
9411                 status = WERR_BADFILE;
9412                 goto done;
9413         }
9414
9415         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9416
9417         r_u->needed = printerkey_len*2;
9418
9419         if ( q_u->size < r_u->needed ) {
9420                 status = WERR_MORE_DATA;
9421                 goto done;
9422         }
9423
9424         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9425                 status = WERR_NOMEM;
9426                 goto done;
9427         }
9428
9429         status = WERR_OK;
9430
9431         if ( q_u->size < r_u->needed )
9432                 status = WERR_MORE_DATA;
9433
9434 done:
9435         free_a_printer( &printer, 2 );
9436         SAFE_FREE( keynames );
9437
9438         return status;
9439 }
9440
9441 /****************************************************************
9442  _spoolss_DeletePrinterKey
9443 ****************************************************************/
9444
9445 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9446                                  struct spoolss_DeletePrinterKey *r)
9447 {
9448         POLICY_HND              *handle = r->in.handle;
9449         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9450         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9451         int                     snum=0;
9452         WERROR                  status;
9453
9454         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9455
9456         if (!Printer) {
9457                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9458                         OUR_HANDLE(handle)));
9459                 return WERR_BADFID;
9460         }
9461
9462         /* if keyname == NULL, return error */
9463
9464         if ( !r->in.key_name )
9465                 return WERR_INVALID_PARAM;
9466
9467         if (!get_printer_snum(p, handle, &snum, NULL))
9468                 return WERR_BADFID;
9469
9470         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9471                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9472                         "printer properties change denied by handle\n"));
9473                 return WERR_ACCESS_DENIED;
9474         }
9475
9476         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9477         if (!W_ERROR_IS_OK(status))
9478                 return status;
9479
9480         /* delete the key and all subneys */
9481
9482         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9483
9484         if ( W_ERROR_IS_OK(status) )
9485                 status = mod_a_printer(printer, 2);
9486
9487         free_a_printer( &printer, 2 );
9488
9489         return status;
9490 }
9491
9492
9493 /********************************************************************
9494  * spoolss_enumprinterdataex
9495  ********************************************************************/
9496
9497 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9498 {
9499         POLICY_HND      *handle = &q_u->handle;
9500         uint32          in_size = q_u->size;
9501         uint32          num_entries,
9502                         needed;
9503         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9504         PRINTER_ENUM_VALUES     *enum_values = NULL;
9505         NT_PRINTER_DATA         *p_data;
9506         fstring         key;
9507         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9508         int             snum;
9509         WERROR          result;
9510         int             key_index;
9511         int             i;
9512         REGISTRY_VALUE  *val;
9513         char            *value_name;
9514         uint32          data_len;
9515
9516
9517         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9518
9519         if (!Printer) {
9520                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9521                 return WERR_BADFID;
9522         }
9523
9524         /*
9525          * first check for a keyname of NULL or "".  Win2k seems to send
9526          * this a lot and we should send back WERR_INVALID_PARAM
9527          * no need to spend time looking up the printer in this case.
9528          * --jerry
9529          */
9530
9531         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9532         if ( !strlen(key) ) {
9533                 result = WERR_INVALID_PARAM;
9534                 goto done;
9535         }
9536
9537         /* get the printer off of disk */
9538
9539         if (!get_printer_snum(p,handle, &snum, NULL))
9540                 return WERR_BADFID;
9541
9542         ZERO_STRUCT(printer);
9543         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9544         if (!W_ERROR_IS_OK(result))
9545                 return result;
9546
9547         /* now look for a match on the key name */
9548
9549         p_data = printer->info_2->data;
9550
9551         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9552         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9553         {
9554                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9555                 result = WERR_INVALID_PARAM;
9556                 goto done;
9557         }
9558
9559         result = WERR_OK;
9560         needed = 0;
9561
9562         /* allocate the memory for the array of pointers -- if necessary */
9563
9564         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9565         if ( num_entries )
9566         {
9567                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9568                 {
9569                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9570                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9571                         result = WERR_NOMEM;
9572                         goto done;
9573                 }
9574
9575                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9576         }
9577
9578         /*
9579          * loop through all params and build the array to pass
9580          * back to the  client
9581          */
9582
9583         for ( i=0; i<num_entries; i++ )
9584         {
9585                 /* lookup the registry value */
9586
9587                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9588                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9589
9590                 /* copy the data */
9591
9592                 value_name = regval_name( val );
9593                 init_unistr( &enum_values[i].valuename, value_name );
9594                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9595                 enum_values[i].type      = regval_type( val );
9596
9597                 data_len = regval_size( val );
9598                 if ( data_len ) {
9599                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9600                         {
9601                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9602                                         data_len ));
9603                                 result = WERR_NOMEM;
9604                                 goto done;
9605                         }
9606                 }
9607                 enum_values[i].data_len = data_len;
9608
9609                 /* keep track of the size of the array in bytes */
9610
9611                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9612         }
9613
9614         /* housekeeping information in the reply */
9615
9616         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9617          * the hand marshalled container size is a multiple
9618          * of 4 bytes for RPC alignment.
9619          */
9620
9621         if (needed % 4) {
9622                 needed += 4-(needed % 4);
9623         }
9624
9625         r_u->needed     = needed;
9626         r_u->returned   = num_entries;
9627
9628         if (needed > in_size) {
9629                 result = WERR_MORE_DATA;
9630                 goto done;
9631         }
9632
9633         /* copy data into the reply */
9634
9635         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9636            response buffer size is != the offered buffer size
9637
9638                 r_u->ctr.size           = r_u->needed;
9639         */
9640         r_u->ctr.size           = in_size;
9641
9642         r_u->ctr.size_of_array  = r_u->returned;
9643         r_u->ctr.values         = enum_values;
9644
9645 done:
9646         if ( printer )
9647         free_a_printer(&printer, 2);
9648
9649         return result;
9650 }
9651
9652 /****************************************************************************
9653 ****************************************************************************/
9654
9655 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9656 {
9657         init_unistr(&info->name, name);
9658 }
9659
9660 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9661                                                  UNISTR2 *environment,
9662                                                  RPC_BUFFER *buffer,
9663                                                  uint32 offered,
9664                                                  uint32 *needed)
9665 {
9666         char *long_archi = NULL;
9667         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9668         WERROR result = WERR_OK;
9669         TALLOC_CTX *ctx = talloc_tos();
9670
9671         long_archi = unistr2_to_ascii_talloc(ctx, environment);
9672         if (!long_archi) {
9673                 return WERR_NOMEM;
9674         }
9675
9676         if (!get_short_archi(long_archi))
9677                 return WERR_INVALID_ENVIRONMENT;
9678
9679         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9680                 return WERR_NOMEM;
9681
9682         fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9683
9684         *needed += spoolss_size_printprocessordirectory_info_1(info);
9685
9686         if (*needed > offered) {
9687                 result = WERR_INSUFFICIENT_BUFFER;
9688                 goto out;
9689         }
9690
9691         if (!rpcbuf_alloc_size(buffer, *needed)) {
9692                 result = WERR_INSUFFICIENT_BUFFER;
9693                 goto out;
9694         }
9695
9696         smb_io_printprocessordirectory_1("", buffer, info, 0);
9697
9698 out:
9699         SAFE_FREE(info);
9700
9701         return result;
9702 }
9703
9704 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9705 {
9706         uint32 level = q_u->level;
9707         RPC_BUFFER *buffer = NULL;
9708         uint32 offered = q_u->offered;
9709         uint32 *needed = &r_u->needed;
9710         WERROR result;
9711
9712         /* that's an [in out] buffer */
9713
9714         if (!q_u->buffer && (offered!=0)) {
9715                 return WERR_INVALID_PARAM;
9716         }
9717
9718         rpcbuf_move(q_u->buffer, &r_u->buffer);
9719         buffer = r_u->buffer;
9720
9721         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9722
9723         *needed=0;
9724
9725         switch(level) {
9726         case 1:
9727                 result = getprintprocessordirectory_level_1
9728                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9729                 break;
9730         default:
9731                 result = WERR_UNKNOWN_LEVEL;
9732         }
9733
9734         return result;
9735 }
9736
9737 /*******************************************************************
9738  Streams the monitor UI DLL name in UNICODE
9739 *******************************************************************/
9740
9741 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9742                                 RPC_BUFFER *out, uint32 *needed )
9743 {
9744         const char *dllname = "tcpmonui.dll";
9745
9746         *needed = (strlen(dllname)+1) * 2;
9747
9748         if ( rpcbuf_get_size(out) < *needed ) {
9749                 return WERR_INSUFFICIENT_BUFFER;
9750         }
9751
9752         if ( !make_monitorui_buf( out, dllname ) ) {
9753                 return WERR_NOMEM;
9754         }
9755
9756         return WERR_OK;
9757 }
9758
9759 /*******************************************************************
9760  Create a new TCP/IP port
9761 *******************************************************************/
9762
9763 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9764                               RPC_BUFFER *out, uint32 *needed )
9765 {
9766         NT_PORT_DATA_1 port1;
9767         TALLOC_CTX *ctx = talloc_tos();
9768         char *device_uri = NULL;
9769
9770         ZERO_STRUCT( port1 );
9771
9772         /* convert to our internal port data structure */
9773
9774         if ( !convert_port_data_1( &port1, in ) ) {
9775                 return WERR_NOMEM;
9776         }
9777
9778         /* create the device URI and call the add_port_hook() */
9779
9780         switch ( port1.protocol ) {
9781         case PORT_PROTOCOL_DIRECT:
9782                 device_uri = talloc_asprintf(ctx,
9783                                 "socket://%s:%d/", port1.hostaddr, port1.port );
9784                 break;
9785
9786         case PORT_PROTOCOL_LPR:
9787                 device_uri = talloc_asprintf(ctx,
9788                         "lpr://%s/%s", port1.hostaddr, port1.queue );
9789                 break;
9790
9791         default:
9792                 return WERR_UNKNOWN_PORT;
9793         }
9794
9795         if (!device_uri) {
9796                 return WERR_NOMEM;
9797         }
9798
9799         return add_port_hook(ctx, token, port1.name, device_uri );
9800 }
9801
9802 /*******************************************************************
9803 *******************************************************************/
9804
9805 struct xcv_api_table xcvtcp_cmds[] = {
9806         { "MonitorUI",  xcvtcp_monitorui },
9807         { "AddPort",    xcvtcp_addport},
9808         { NULL,         NULL }
9809 };
9810
9811 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9812                                       RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9813                                       uint32 *needed )
9814 {
9815         int i;
9816
9817         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9818
9819         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9820                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9821                         return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9822         }
9823
9824         return WERR_BADFUNC;
9825 }
9826
9827 /*******************************************************************
9828 *******************************************************************/
9829 #if 0   /* don't support management using the "Local Port" monitor */
9830
9831 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9832                                   RPC_BUFFER *out, uint32 *needed )
9833 {
9834         const char *dllname = "localui.dll";
9835
9836         *needed = (strlen(dllname)+1) * 2;
9837
9838         if ( rpcbuf_get_size(out) < *needed ) {
9839                 return WERR_INSUFFICIENT_BUFFER;
9840         }
9841
9842         if ( !make_monitorui_buf( out, dllname )) {
9843                 return WERR_NOMEM;
9844         }
9845
9846         return WERR_OK;
9847 }
9848
9849 /*******************************************************************
9850 *******************************************************************/
9851
9852 struct xcv_api_table xcvlocal_cmds[] = {
9853         { "MonitorUI",  xcvlocal_monitorui },
9854         { NULL,         NULL }
9855 };
9856 #else
9857 struct xcv_api_table xcvlocal_cmds[] = {
9858         { NULL,         NULL }
9859 };
9860 #endif
9861
9862
9863
9864 /*******************************************************************
9865 *******************************************************************/
9866
9867 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9868                                         RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9869                                         uint32 *needed )
9870 {
9871         int i;
9872
9873         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9874
9875         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9876                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9877                         return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9878         }
9879         return WERR_BADFUNC;
9880 }
9881
9882 /*******************************************************************
9883 *******************************************************************/
9884
9885 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9886 {
9887         Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9888         fstring command;
9889
9890         if (!Printer) {
9891                 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9892                 return WERR_BADFID;
9893         }
9894
9895         /* Has to be a handle to the TCP/IP port monitor */
9896
9897         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9898                 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9899                 return WERR_BADFID;
9900         }
9901
9902         /* requires administrative access to the server */
9903
9904         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9905                 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9906                 return WERR_ACCESS_DENIED;
9907         }
9908
9909         /* Get the command name.  There's numerous commands supported by the
9910            TCPMON interface. */
9911
9912         rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9913                 q_u->dataname.uni_str_len*2, 0);
9914
9915         /* Allocate the outgoing buffer */
9916
9917         if (!rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx ))
9918                 return WERR_NOMEM;
9919
9920         switch ( Printer->printer_type ) {
9921         case SPLHND_PORTMON_TCP:
9922                 return process_xcvtcp_command( p->server_info->ptok, command,
9923                         &q_u->indata, &r_u->outdata, &r_u->needed );
9924         case SPLHND_PORTMON_LOCAL:
9925                 return process_xcvlocal_command( p->server_info->ptok, command,
9926                         &q_u->indata, &r_u->outdata, &r_u->needed );
9927         }
9928
9929         return WERR_INVALID_PRINT_MONITOR;
9930 }
9931
9932 /****************************************************************
9933  _spoolss_AddPrintProcessor
9934 ****************************************************************/
9935
9936 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9937                                   struct spoolss_AddPrintProcessor *r)
9938 {
9939         /* for now, just indicate success and ignore the add.  We'll
9940            automatically set the winprint processor for printer
9941            entries later.  Used to debug the LexMark Optra S 1855 PCL
9942            driver --jerry */
9943
9944         return WERR_OK;
9945 }
9946
9947 /****************************************************************
9948  _spoolss_EnumPrinters
9949 ****************************************************************/
9950
9951 WERROR _spoolss_EnumPrinters(pipes_struct *p,
9952                              struct spoolss_EnumPrinters *r)
9953 {
9954         p->rng_fault_state = true;
9955         return WERR_NOT_SUPPORTED;
9956 }
9957
9958 /****************************************************************
9959  _spoolss_GetJob
9960 ****************************************************************/
9961
9962 WERROR _spoolss_GetJob(pipes_struct *p,
9963                        struct spoolss_GetJob *r)
9964 {
9965         p->rng_fault_state = true;
9966         return WERR_NOT_SUPPORTED;
9967 }
9968
9969 /****************************************************************
9970  _spoolss_EnumJobs
9971 ****************************************************************/
9972
9973 WERROR _spoolss_EnumJobs(pipes_struct *p,
9974                          struct spoolss_EnumJobs *r)
9975 {
9976         p->rng_fault_state = true;
9977         return WERR_NOT_SUPPORTED;
9978 }
9979
9980 /****************************************************************
9981  _spoolss_AddPrinter
9982 ****************************************************************/
9983
9984 WERROR _spoolss_AddPrinter(pipes_struct *p,
9985                            struct spoolss_AddPrinter *r)
9986 {
9987         p->rng_fault_state = true;
9988         return WERR_NOT_SUPPORTED;
9989 }
9990
9991 /****************************************************************
9992  _spoolss_SetPrinter
9993 ****************************************************************/
9994
9995 WERROR _spoolss_SetPrinter(pipes_struct *p,
9996                            struct spoolss_SetPrinter *r)
9997 {
9998         p->rng_fault_state = true;
9999         return WERR_NOT_SUPPORTED;
10000 }
10001
10002 /****************************************************************
10003  _spoolss_GetPrinter
10004 ****************************************************************/
10005
10006 WERROR _spoolss_GetPrinter(pipes_struct *p,
10007                            struct spoolss_GetPrinter *r)
10008 {
10009         p->rng_fault_state = true;
10010         return WERR_NOT_SUPPORTED;
10011 }
10012
10013 /****************************************************************
10014  _spoolss_AddPrinterDriver
10015 ****************************************************************/
10016
10017 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
10018                                  struct spoolss_AddPrinterDriver *r)
10019 {
10020         p->rng_fault_state = true;
10021         return WERR_NOT_SUPPORTED;
10022 }
10023
10024 /****************************************************************
10025  _spoolss_EnumPrinterDrivers
10026 ****************************************************************/
10027
10028 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10029                                    struct spoolss_EnumPrinterDrivers *r)
10030 {
10031         p->rng_fault_state = true;
10032         return WERR_NOT_SUPPORTED;
10033 }
10034
10035 /****************************************************************
10036  _spoolss_GetPrinterDriver
10037 ****************************************************************/
10038
10039 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10040                                  struct spoolss_GetPrinterDriver *r)
10041 {
10042         p->rng_fault_state = true;
10043         return WERR_NOT_SUPPORTED;
10044 }
10045
10046 /****************************************************************
10047  _spoolss_GetPrinterDriverDirectory
10048 ****************************************************************/
10049
10050 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
10051                                           struct spoolss_GetPrinterDriverDirectory *r)
10052 {
10053         p->rng_fault_state = true;
10054         return WERR_NOT_SUPPORTED;
10055 }
10056
10057 /****************************************************************
10058  _spoolss_EnumPrintProcessors
10059 ****************************************************************/
10060
10061 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10062                                     struct spoolss_EnumPrintProcessors *r)
10063 {
10064         p->rng_fault_state = true;
10065         return WERR_NOT_SUPPORTED;
10066 }
10067
10068 /****************************************************************
10069  _spoolss_GetPrintProcessorDirectory
10070 ****************************************************************/
10071
10072 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
10073                                            struct spoolss_GetPrintProcessorDirectory *r)
10074 {
10075         p->rng_fault_state = true;
10076         return WERR_NOT_SUPPORTED;
10077 }
10078
10079 /****************************************************************
10080  _spoolss_ReadPrinter
10081 ****************************************************************/
10082
10083 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10084                             struct spoolss_ReadPrinter *r)
10085 {
10086         p->rng_fault_state = true;
10087         return WERR_NOT_SUPPORTED;
10088 }
10089
10090 /****************************************************************
10091  _spoolss_GetPrinterData
10092 ****************************************************************/
10093
10094 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10095                                struct spoolss_GetPrinterData *r)
10096 {
10097         p->rng_fault_state = true;
10098         return WERR_NOT_SUPPORTED;
10099 }
10100
10101 /****************************************************************
10102  _spoolss_SetPrinterData
10103 ****************************************************************/
10104
10105 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10106                                struct spoolss_SetPrinterData *r)
10107 {
10108         p->rng_fault_state = true;
10109         return WERR_NOT_SUPPORTED;
10110 }
10111
10112 /****************************************************************
10113  _spoolss_WaitForPrinterChange
10114 ****************************************************************/
10115
10116 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10117                                      struct spoolss_WaitForPrinterChange *r)
10118 {
10119         p->rng_fault_state = true;
10120         return WERR_NOT_SUPPORTED;
10121 }
10122
10123 /****************************************************************
10124  _spoolss_EnumForms
10125 ****************************************************************/
10126
10127 WERROR _spoolss_EnumForms(pipes_struct *p,
10128                           struct spoolss_EnumForms *r)
10129 {
10130         p->rng_fault_state = true;
10131         return WERR_NOT_SUPPORTED;
10132 }
10133
10134 /****************************************************************
10135  _spoolss_EnumPorts
10136 ****************************************************************/
10137
10138 WERROR _spoolss_EnumPorts(pipes_struct *p,
10139                           struct spoolss_EnumPorts *r)
10140 {
10141         p->rng_fault_state = true;
10142         return WERR_NOT_SUPPORTED;
10143 }
10144
10145 /****************************************************************
10146  _spoolss_EnumMonitors
10147 ****************************************************************/
10148
10149 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10150                              struct spoolss_EnumMonitors *r)
10151 {
10152         p->rng_fault_state = true;
10153         return WERR_NOT_SUPPORTED;
10154 }
10155
10156 /****************************************************************
10157  _spoolss_AddPort
10158 ****************************************************************/
10159
10160 WERROR _spoolss_AddPort(pipes_struct *p,
10161                         struct spoolss_AddPort *r)
10162 {
10163         p->rng_fault_state = true;
10164         return WERR_NOT_SUPPORTED;
10165 }
10166
10167 /****************************************************************
10168  _spoolss_ConfigurePort
10169 ****************************************************************/
10170
10171 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10172                               struct spoolss_ConfigurePort *r)
10173 {
10174         p->rng_fault_state = true;
10175         return WERR_NOT_SUPPORTED;
10176 }
10177
10178 /****************************************************************
10179  _spoolss_DeletePort
10180 ****************************************************************/
10181
10182 WERROR _spoolss_DeletePort(pipes_struct *p,
10183                            struct spoolss_DeletePort *r)
10184 {
10185         p->rng_fault_state = true;
10186         return WERR_NOT_SUPPORTED;
10187 }
10188
10189 /****************************************************************
10190  _spoolss_CreatePrinterIC
10191 ****************************************************************/
10192
10193 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10194                                 struct spoolss_CreatePrinterIC *r)
10195 {
10196         p->rng_fault_state = true;
10197         return WERR_NOT_SUPPORTED;
10198 }
10199
10200 /****************************************************************
10201  _spoolss_PlayGDIScriptOnPrinterIC
10202 ****************************************************************/
10203
10204 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10205                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10206 {
10207         p->rng_fault_state = true;
10208         return WERR_NOT_SUPPORTED;
10209 }
10210
10211 /****************************************************************
10212  _spoolss_DeletePrinterIC
10213 ****************************************************************/
10214
10215 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10216                                 struct spoolss_DeletePrinterIC *r)
10217 {
10218         p->rng_fault_state = true;
10219         return WERR_NOT_SUPPORTED;
10220 }
10221
10222 /****************************************************************
10223  _spoolss_AddPrinterConnection
10224 ****************************************************************/
10225
10226 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10227                                      struct spoolss_AddPrinterConnection *r)
10228 {
10229         p->rng_fault_state = true;
10230         return WERR_NOT_SUPPORTED;
10231 }
10232
10233 /****************************************************************
10234  _spoolss_DeletePrinterConnection
10235 ****************************************************************/
10236
10237 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10238                                         struct spoolss_DeletePrinterConnection *r)
10239 {
10240         p->rng_fault_state = true;
10241         return WERR_NOT_SUPPORTED;
10242 }
10243
10244 /****************************************************************
10245  _spoolss_PrinterMessageBox
10246 ****************************************************************/
10247
10248 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10249                                   struct spoolss_PrinterMessageBox *r)
10250 {
10251         p->rng_fault_state = true;
10252         return WERR_NOT_SUPPORTED;
10253 }
10254
10255 /****************************************************************
10256  _spoolss_AddMonitor
10257 ****************************************************************/
10258
10259 WERROR _spoolss_AddMonitor(pipes_struct *p,
10260                            struct spoolss_AddMonitor *r)
10261 {
10262         p->rng_fault_state = true;
10263         return WERR_NOT_SUPPORTED;
10264 }
10265
10266 /****************************************************************
10267  _spoolss_DeleteMonitor
10268 ****************************************************************/
10269
10270 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10271                               struct spoolss_DeleteMonitor *r)
10272 {
10273         p->rng_fault_state = true;
10274         return WERR_NOT_SUPPORTED;
10275 }
10276
10277 /****************************************************************
10278  _spoolss_DeletePrintProcessor
10279 ****************************************************************/
10280
10281 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10282                                      struct spoolss_DeletePrintProcessor *r)
10283 {
10284         p->rng_fault_state = true;
10285         return WERR_NOT_SUPPORTED;
10286 }
10287
10288 /****************************************************************
10289  _spoolss_AddPrintProvidor
10290 ****************************************************************/
10291
10292 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10293                                  struct spoolss_AddPrintProvidor *r)
10294 {
10295         p->rng_fault_state = true;
10296         return WERR_NOT_SUPPORTED;
10297 }
10298
10299 /****************************************************************
10300  _spoolss_DeletePrintProvidor
10301 ****************************************************************/
10302
10303 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10304                                     struct spoolss_DeletePrintProvidor *r)
10305 {
10306         p->rng_fault_state = true;
10307         return WERR_NOT_SUPPORTED;
10308 }
10309
10310 /****************************************************************
10311  _spoolss_EnumPrintProcDataTypes
10312 ****************************************************************/
10313
10314 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10315                                        struct spoolss_EnumPrintProcDataTypes *r)
10316 {
10317         p->rng_fault_state = true;
10318         return WERR_NOT_SUPPORTED;
10319 }
10320
10321 /****************************************************************
10322  _spoolss_ResetPrinter
10323 ****************************************************************/
10324
10325 WERROR _spoolss_ResetPrinter(pipes_struct *p,
10326                              struct spoolss_ResetPrinter *r)
10327 {
10328         p->rng_fault_state = true;
10329         return WERR_NOT_SUPPORTED;
10330 }
10331
10332 /****************************************************************
10333  _spoolss_GetPrinterDriver2
10334 ****************************************************************/
10335
10336 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10337                                   struct spoolss_GetPrinterDriver2 *r)
10338 {
10339         p->rng_fault_state = true;
10340         return WERR_NOT_SUPPORTED;
10341 }
10342
10343 /****************************************************************
10344  _spoolss_FindFirstPrinterChangeNotification
10345 ****************************************************************/
10346
10347 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10348                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10349 {
10350         p->rng_fault_state = true;
10351         return WERR_NOT_SUPPORTED;
10352 }
10353
10354 /****************************************************************
10355  _spoolss_FindNextPrinterChangeNotification
10356 ****************************************************************/
10357
10358 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10359                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10360 {
10361         p->rng_fault_state = true;
10362         return WERR_NOT_SUPPORTED;
10363 }
10364
10365 /****************************************************************
10366  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10367 ****************************************************************/
10368
10369 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10370                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10371 {
10372         p->rng_fault_state = true;
10373         return WERR_NOT_SUPPORTED;
10374 }
10375
10376 /****************************************************************
10377  _spoolss_ReplyOpenPrinter
10378 ****************************************************************/
10379
10380 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10381                                  struct spoolss_ReplyOpenPrinter *r)
10382 {
10383         p->rng_fault_state = true;
10384         return WERR_NOT_SUPPORTED;
10385 }
10386
10387 /****************************************************************
10388  _spoolss_RouterReplyPrinter
10389 ****************************************************************/
10390
10391 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10392                                    struct spoolss_RouterReplyPrinter *r)
10393 {
10394         p->rng_fault_state = true;
10395         return WERR_NOT_SUPPORTED;
10396 }
10397
10398 /****************************************************************
10399  _spoolss_ReplyClosePrinter
10400 ****************************************************************/
10401
10402 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10403                                   struct spoolss_ReplyClosePrinter *r)
10404 {
10405         p->rng_fault_state = true;
10406         return WERR_NOT_SUPPORTED;
10407 }
10408
10409 /****************************************************************
10410  _spoolss_AddPortEx
10411 ****************************************************************/
10412
10413 WERROR _spoolss_AddPortEx(pipes_struct *p,
10414                           struct spoolss_AddPortEx *r)
10415 {
10416         p->rng_fault_state = true;
10417         return WERR_NOT_SUPPORTED;
10418 }
10419
10420 /****************************************************************
10421  _spoolss_RouterFindFirstPrinterChangeNotification
10422 ****************************************************************/
10423
10424 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10425                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10426 {
10427         p->rng_fault_state = true;
10428         return WERR_NOT_SUPPORTED;
10429 }
10430
10431 /****************************************************************
10432  _spoolss_SpoolerInit
10433 ****************************************************************/
10434
10435 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10436                             struct spoolss_SpoolerInit *r)
10437 {
10438         p->rng_fault_state = true;
10439         return WERR_NOT_SUPPORTED;
10440 }
10441
10442 /****************************************************************
10443  _spoolss_ResetPrinterEx
10444 ****************************************************************/
10445
10446 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10447                                struct spoolss_ResetPrinterEx *r)
10448 {
10449         p->rng_fault_state = true;
10450         return WERR_NOT_SUPPORTED;
10451 }
10452
10453 /****************************************************************
10454  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10455 ****************************************************************/
10456
10457 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10458                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10459 {
10460         p->rng_fault_state = true;
10461         return WERR_NOT_SUPPORTED;
10462 }
10463
10464 /****************************************************************
10465  _spoolss_RouterReplyPrinterEx
10466 ****************************************************************/
10467
10468 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10469                                      struct spoolss_RouterReplyPrinterEx *r)
10470 {
10471         p->rng_fault_state = true;
10472         return WERR_NOT_SUPPORTED;
10473 }
10474
10475 /****************************************************************
10476  _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
10477 ****************************************************************/
10478
10479 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
10480                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
10481 {
10482         p->rng_fault_state = true;
10483         return WERR_NOT_SUPPORTED;
10484 }
10485
10486 /****************************************************************
10487  _spoolss_44
10488 ****************************************************************/
10489
10490 WERROR _spoolss_44(pipes_struct *p,
10491                    struct spoolss_44 *r)
10492 {
10493         p->rng_fault_state = true;
10494         return WERR_NOT_SUPPORTED;
10495 }
10496
10497 /****************************************************************
10498  _spoolss_AddPrinterEx
10499 ****************************************************************/
10500
10501 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
10502                              struct spoolss_AddPrinterEx *r)
10503 {
10504         p->rng_fault_state = true;
10505         return WERR_NOT_SUPPORTED;
10506 }
10507
10508 /****************************************************************
10509  _spoolss_47
10510 ****************************************************************/
10511
10512 WERROR _spoolss_47(pipes_struct *p,
10513                    struct spoolss_47 *r)
10514 {
10515         p->rng_fault_state = true;
10516         return WERR_NOT_SUPPORTED;
10517 }
10518
10519 /****************************************************************
10520  _spoolss_EnumPrinterData
10521 ****************************************************************/
10522
10523 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10524                                 struct spoolss_EnumPrinterData *r)
10525 {
10526         p->rng_fault_state = true;
10527         return WERR_NOT_SUPPORTED;
10528 }
10529
10530 /****************************************************************
10531  _spoolss_4a
10532 ****************************************************************/
10533
10534 WERROR _spoolss_4a(pipes_struct *p,
10535                    struct spoolss_4a *r)
10536 {
10537         p->rng_fault_state = true;
10538         return WERR_NOT_SUPPORTED;
10539 }
10540
10541 /****************************************************************
10542  _spoolss_4b
10543 ****************************************************************/
10544
10545 WERROR _spoolss_4b(pipes_struct *p,
10546                    struct spoolss_4b *r)
10547 {
10548         p->rng_fault_state = true;
10549         return WERR_NOT_SUPPORTED;
10550 }
10551
10552 /****************************************************************
10553  _spoolss_4c
10554 ****************************************************************/
10555
10556 WERROR _spoolss_4c(pipes_struct *p,
10557                    struct spoolss_4c *r)
10558 {
10559         p->rng_fault_state = true;
10560         return WERR_NOT_SUPPORTED;
10561 }
10562
10563 /****************************************************************
10564  _spoolss_SetPrinterDataEx
10565 ****************************************************************/
10566
10567 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
10568                                  struct spoolss_SetPrinterDataEx *r)
10569 {
10570         p->rng_fault_state = true;
10571         return WERR_NOT_SUPPORTED;
10572 }
10573
10574 /****************************************************************
10575  _spoolss_EnumPrinterDataEx
10576 ****************************************************************/
10577
10578 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10579                                   struct spoolss_EnumPrinterDataEx *r)
10580 {
10581         p->rng_fault_state = true;
10582         return WERR_NOT_SUPPORTED;
10583 }
10584
10585 /****************************************************************
10586  _spoolss_EnumPrinterKey
10587 ****************************************************************/
10588
10589 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10590                                struct spoolss_EnumPrinterKey *r)
10591 {
10592         p->rng_fault_state = true;
10593         return WERR_NOT_SUPPORTED;
10594 }
10595
10596 /****************************************************************
10597  _spoolss_53
10598 ****************************************************************/
10599
10600 WERROR _spoolss_53(pipes_struct *p,
10601                    struct spoolss_53 *r)
10602 {
10603         p->rng_fault_state = true;
10604         return WERR_NOT_SUPPORTED;
10605 }
10606
10607 /****************************************************************
10608  _spoolss_55
10609 ****************************************************************/
10610
10611 WERROR _spoolss_55(pipes_struct *p,
10612                    struct spoolss_55 *r)
10613 {
10614         p->rng_fault_state = true;
10615         return WERR_NOT_SUPPORTED;
10616 }
10617
10618 /****************************************************************
10619  _spoolss_56
10620 ****************************************************************/
10621
10622 WERROR _spoolss_56(pipes_struct *p,
10623                    struct spoolss_56 *r)
10624 {
10625         p->rng_fault_state = true;
10626         return WERR_NOT_SUPPORTED;
10627 }
10628
10629 /****************************************************************
10630  _spoolss_57
10631 ****************************************************************/
10632
10633 WERROR _spoolss_57(pipes_struct *p,
10634                    struct spoolss_57 *r)
10635 {
10636         p->rng_fault_state = true;
10637         return WERR_NOT_SUPPORTED;
10638 }
10639
10640 /****************************************************************
10641  _spoolss_XcvData
10642 ****************************************************************/
10643
10644 WERROR _spoolss_XcvData(pipes_struct *p,
10645                         struct spoolss_XcvData *r)
10646 {
10647         p->rng_fault_state = true;
10648         return WERR_NOT_SUPPORTED;
10649 }
10650
10651 /****************************************************************
10652  _spoolss_AddPrinterDriverEx
10653 ****************************************************************/
10654
10655 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
10656                                    struct spoolss_AddPrinterDriverEx *r)
10657 {
10658         p->rng_fault_state = true;
10659         return WERR_NOT_SUPPORTED;
10660 }
10661
10662 /****************************************************************
10663  _spoolss_5a
10664 ****************************************************************/
10665
10666 WERROR _spoolss_5a(pipes_struct *p,
10667                    struct spoolss_5a *r)
10668 {
10669         p->rng_fault_state = true;
10670         return WERR_NOT_SUPPORTED;
10671 }
10672
10673 /****************************************************************
10674  _spoolss_5b
10675 ****************************************************************/
10676
10677 WERROR _spoolss_5b(pipes_struct *p,
10678                    struct spoolss_5b *r)
10679 {
10680         p->rng_fault_state = true;
10681         return WERR_NOT_SUPPORTED;
10682 }
10683
10684 /****************************************************************
10685  _spoolss_5c
10686 ****************************************************************/
10687
10688 WERROR _spoolss_5c(pipes_struct *p,
10689                    struct spoolss_5c *r)
10690 {
10691         p->rng_fault_state = true;
10692         return WERR_NOT_SUPPORTED;
10693 }
10694
10695 /****************************************************************
10696  _spoolss_5d
10697 ****************************************************************/
10698
10699 WERROR _spoolss_5d(pipes_struct *p,
10700                    struct spoolss_5d *r)
10701 {
10702         p->rng_fault_state = true;
10703         return WERR_NOT_SUPPORTED;
10704 }
10705
10706 /****************************************************************
10707  _spoolss_5e
10708 ****************************************************************/
10709
10710 WERROR _spoolss_5e(pipes_struct *p,
10711                    struct spoolss_5e *r)
10712 {
10713         p->rng_fault_state = true;
10714         return WERR_NOT_SUPPORTED;
10715 }
10716
10717 /****************************************************************
10718  _spoolss_5f
10719 ****************************************************************/
10720
10721 WERROR _spoolss_5f(pipes_struct *p,
10722                    struct spoolss_5f *r)
10723 {
10724         p->rng_fault_state = true;
10725         return WERR_NOT_SUPPORTED;
10726 }
10727