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