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