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