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