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