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