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