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