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