Added 3 params to manipulate shares. "add share command/change share command/
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-2000,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7  *  Copyright (C) Jean François Micouleau      1998-2000.
8  *  Copyright (C) Jeremy Allison                                        2001.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include "includes.h"
26
27 extern int DEBUGLEVEL;
28 extern pstring global_myname;
29
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
32 #endif
33
34 #define PRINTER_HANDLE_IS_PRINTER       0
35 #define PRINTER_HANDLE_IS_PRINTSERVER   1
36
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer{
42         BOOL document_started;
43         BOOL page_started;
44     int jobid; /* jobid in printing backend */
45         BOOL printer_type;
46         union {
47                 fstring handlename;
48                 fstring printerservername;
49         } dev;
50         uint32 type;
51         uint32 access;
52         struct {
53                 uint32 flags;
54                 uint32 options;
55                 fstring localmachine;
56                 uint32 printerlocal;
57                 SPOOL_NOTIFY_OPTION *option;
58                 POLICY_HND client_hnd;
59                 uint32 client_connected;
60         } notify;
61         struct {
62                 fstring machine;
63                 fstring user;
64         } client;
65 } Printer_entry;
66
67 typedef struct _counter_printer_0 {
68         ubi_dlNode Next;
69         ubi_dlNode Prev;
70         
71         int snum;
72         uint32 counter;
73 } counter_printer_0;
74
75 static ubi_dlList counter_list;
76
77 static struct cli_state cli;
78 static uint32 smb_connections=0;
79
80 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
81
82 /* translate between internal status numbers and NT status numbers */
83 static int nt_printj_status(int v)
84 {
85         switch (v) {
86         case LPQ_QUEUED:
87                 return 0;
88         case LPQ_PAUSED:
89                 return JOB_STATUS_PAUSED;
90         case LPQ_SPOOLING:
91                 return JOB_STATUS_SPOOLING;
92         case LPQ_PRINTING:
93                 return JOB_STATUS_PRINTING;
94         case LPQ_ERROR:
95                 return JOB_STATUS_ERROR;
96         case LPQ_DELETING:
97                 return JOB_STATUS_DELETING;
98         case LPQ_OFFLINE:
99                 return JOB_STATUS_OFFLINE;
100         case LPQ_PAPEROUT:
101                 return JOB_STATUS_PAPEROUT;
102         case LPQ_PRINTED:
103                 return JOB_STATUS_PRINTED;
104         case LPQ_DELETED:
105                 return JOB_STATUS_DELETED;
106         case LPQ_BLOCKED:
107                 return JOB_STATUS_BLOCKED;
108         case LPQ_USER_INTERVENTION:
109                 return JOB_STATUS_USER_INTERVENTION;
110         }
111         return 0;
112 }
113
114 static int nt_printq_status(int v)
115 {
116         switch (v) {
117         case LPQ_PAUSED:
118                 return PRINTER_STATUS_PAUSED;
119         case LPQ_QUEUED:
120         case LPQ_SPOOLING:
121         case LPQ_PRINTING:
122                 return 0;
123         }
124         return 0;
125 }
126
127 /****************************************************************************
128  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
129 ****************************************************************************/
130
131 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
132 {
133         SPOOL_NOTIFY_OPTION *sp = *pp;
134
135         *pp = NULL;
136
137         if (!sp)
138                 return;
139
140         if (sp->ctr.type)
141                 safe_free(sp->ctr.type);
142
143         free(sp);
144 }
145
146 /***************************************************************************
147  Disconnect from the client
148 ****************************************************************************/
149
150 static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
151 {
152         uint32 status;
153
154         /* weird if the test succeds !!! */
155         if (smb_connections==0) {
156                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157                 return;
158         }
159
160         if(!cli_spoolss_reply_close_printer(&cli, handle, &status))
161                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
162
163         /* if it's the last connection, deconnect the IPC$ share */
164         if (smb_connections==1) {
165                 if(!spoolss_disconnect_from_client(&cli))
166                         return;
167
168                 message_deregister(MSG_PRINTER_NOTIFY);
169         }
170
171         smb_connections--;
172 }
173
174 /****************************************************************************
175  Functions to free a printer entry datastruct.
176 ****************************************************************************/
177
178 static void free_printer_entry(void *ptr)
179 {
180         Printer_entry *Printer = (Printer_entry *)ptr;
181
182         if (Printer->notify.client_connected==True)
183                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
184
185         Printer->notify.flags=0;
186         Printer->notify.options=0;
187         Printer->notify.localmachine[0]='\0';
188         Printer->notify.printerlocal=0;
189         free_spool_notify_option(&Printer->notify.option);
190         Printer->notify.option=NULL;
191         Printer->notify.client_connected=False;
192
193         safe_free(Printer);
194 }
195
196 /****************************************************************************
197  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
198 ****************************************************************************/
199
200 SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
201 {
202         SPOOL_NOTIFY_OPTION *new_sp = NULL;
203
204         if (!sp)
205                 return NULL;
206
207         new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
208         if (!new_sp)
209                 return NULL;
210
211         *new_sp = *sp;
212
213         if (sp->ctr.count) {
214                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
215
216                 if (!new_sp->ctr.type) {
217                         safe_free(new_sp);
218                         return NULL;
219                 }
220         }
221
222         return new_sp;
223 }
224
225 /****************************************************************************
226   find printer index by handle
227 ****************************************************************************/
228
229 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
230 {
231         Printer_entry *find_printer = NULL;
232
233         if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
234                 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
235                 return NULL;
236         }
237
238         return find_printer;
239 }
240
241 /****************************************************************************
242   close printer index by handle
243 ****************************************************************************/
244
245 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
246 {
247         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
248
249         if (!Printer) {
250                 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
251                 return False;
252         }
253
254         close_policy_hnd(p, hnd);
255
256         return True;
257 }       
258
259 /****************************************************************************
260   delete a printer given a handle
261 ****************************************************************************/
262 static uint32 delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
263 {
264         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
265
266         if (!Printer) {
267                 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
268                 return ERROR_INVALID_HANDLE;
269         }
270
271         if (del_a_printer(Printer->dev.handlename) != 0) {
272                 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
273                 return ERROR_INVALID_HANDLE;
274         }
275
276         /* Check calling user has permission to delete printer.  Note that
277            since we set the snum parameter to -1 only administrators can
278            delete the printer.  This stops people with the Full Control
279            permission from deleting the printer. */
280
281         if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
282                 DEBUG(3, ("printer delete denied by security descriptor\n"));
283                 return ERROR_ACCESS_DENIED;
284         }
285
286         if (*lp_deleteprinter_cmd()) {
287
288                 pid_t local_pid = sys_getpid();
289                 char *cmd = lp_deleteprinter_cmd();
290                 char *path;
291                 pstring tmp_file;
292                 pstring command;
293                 int ret;
294                 int i;
295
296                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
297                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
298                 else
299                         path = tmpdir();
300                 
301                 /* Printer->dev.handlename equals portname equals sharename */
302                 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
303                                         Printer->dev.handlename);
304                 dos_to_unix(command, True);  /* Convert printername to unix-codepage */
305         slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
306
307                 unlink(tmp_file);
308                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
309                 ret = smbrun(command, tmp_file, False);
310                 if (ret != 0) {
311                         unlink(tmp_file);
312                         return ERROR_INVALID_HANDLE; /* What to return here? */
313                 }
314                 DEBUGADD(10,("returned [%d]\n", ret));
315                 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
316                 unlink(tmp_file);
317
318                 /* Send SIGHUP to process group... is there a better way? */
319                 kill(0, SIGHUP);
320
321                 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
322                         lp_killservice( i );
323                         return ERROR_SUCCESS;
324                 } else
325                         return ERROR_ACCESS_DENIED;
326         }
327
328         return ERROR_SUCCESS;
329 }       
330
331 /****************************************************************************
332   return the snum of a printer corresponding to an handle
333 ****************************************************************************/
334 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
335 {
336         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
337                 
338         if (!Printer) {
339                 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
340                 return False;
341         }
342         
343         switch (Printer->printer_type) {
344         case PRINTER_HANDLE_IS_PRINTER:         
345                 DEBUG(4,("short name:%s\n", Printer->dev.handlename));                  
346                 *number = print_queue_snum(Printer->dev.handlename);
347                 return (*number != -1);
348         case PRINTER_HANDLE_IS_PRINTSERVER:
349                 return False;
350         default:
351                 return False;
352         }
353 }
354
355 /****************************************************************************
356   set printer handle type.
357 ****************************************************************************/
358 static BOOL set_printer_hnd_accesstype(pipes_struct *p, POLICY_HND *hnd, uint32 access_required)
359 {
360         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
361
362         if (!Printer) {
363                 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
364                 return False;
365         }
366
367         DEBUG(4,("Setting printer access=%x\n", access_required));
368         Printer->access = access_required;
369         return True;            
370 }
371
372 /****************************************************************************
373  Set printer handle type.
374  Check if it's \\server or \\server\printer
375 ****************************************************************************/
376
377 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
378 {
379         DEBUG(3,("Setting printer type=%s\n", handlename));
380
381         if ( strlen(handlename) < 3 ) {
382                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
383                 return False;
384         }
385
386         /* it's a print server */
387         if (!strchr(handlename+2, '\\')) {
388                 DEBUGADD(4,("Printer is a print server\n"));
389                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;          
390         }
391         /* it's a printer */
392         else {
393                 DEBUGADD(4,("Printer is a printer\n"));
394                 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
395         }
396
397         return True;
398 }
399
400 /****************************************************************************
401  Set printer handle name.
402 ****************************************************************************/
403
404 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
405 {
406         NT_PRINTER_INFO_LEVEL *printer = NULL;
407         int snum;
408         int n_services=lp_numservices();
409         char *aprinter;
410         BOOL found=False;
411         
412         DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
413
414         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
415                 ZERO_STRUCT(Printer->dev.printerservername);
416                 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
417                 return True;
418         }
419
420         if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
421                 return False;
422         
423         aprinter=strchr(handlename+2, '\\');
424         aprinter++;
425
426         DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
427
428         /*
429          * store the Samba share name in it
430          * in back we have the long printer name
431          * need to iterate all the snum and do a
432          * get_a_printer each time to find the printer
433          * faster to do it here than later.
434          */
435
436         for (snum=0;snum<n_services && found==False;snum++) {
437                 char *printername;
438         
439                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
440                         continue;
441                 
442                 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
443
444                 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
445                         continue;
446
447                 printername=strchr(printer->info_2->printername+2, '\\');
448                 printername++;
449
450                 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
451                                 printer->info_2->printername, aprinter ));
452
453                 if ( strlen(printername) != strlen(aprinter) ) {
454                         free_a_printer(&printer, 2);
455                         continue;
456                 }
457                 
458                 if ( strncasecmp(printername, aprinter, strlen(aprinter)))  {
459                         free_a_printer(&printer, 2);
460                         continue;
461                 }
462                 
463                 found=True;
464         }
465
466         /*
467          * if we haven't found a printer with the given handlename
468          * then it can be a share name as you can open both \\server\printer and
469          * \\server\share
470          */
471
472         /*
473          * we still check if the printer description file exists as NT won't be happy
474          * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
475          */
476
477         if (found==False) {
478                 DEBUGADD(5,("Printer not found, checking for share now\n"));
479         
480                 for (snum=0;snum<n_services && found==False;snum++) {
481         
482                         if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
483                                 continue;
484                 
485                         DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
486
487                         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
488                                 continue;
489
490                         DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
491                                         printer->info_2->printername, aprinter ));
492
493                         if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
494                                 free_a_printer(&printer, 2);
495                                 continue;
496                         }
497                 
498                         if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter)))  {
499                                 free_a_printer(&printer, 2);
500                                 continue;
501                         }
502                 
503                         found=True;
504                 }
505         }
506                 
507         if (found==False) {
508                 DEBUGADD(4,("Printer not found\n"));
509                 return False;
510         }
511         
512         snum--;
513         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
514                         printer->info_2->printername, lp_servicename(snum),snum));
515
516         ZERO_STRUCT(Printer->dev.handlename);
517         strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
518         
519         free_a_printer(&printer, 2);
520
521         return True;
522 }
523
524 /****************************************************************************
525   find first available printer slot. creates a printer handle for you.
526  ****************************************************************************/
527
528 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name)
529 {
530         Printer_entry *new_printer;
531
532         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
533
534         if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
535                 return False;
536
537         ZERO_STRUCTP(new_printer);
538         
539         new_printer->notify.option=NULL;
540                                 
541         if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
542                 safe_free(new_printer);
543                 return False;
544         }
545
546         if (!set_printer_hnd_printertype(new_printer, name)) {
547                 close_printer_handle(p, hnd);
548                 return False;
549         }
550         
551         if (!set_printer_hnd_name(new_printer, name)) {
552                 close_printer_handle(p, hnd);
553                 return False;
554         }
555
556         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
557
558         return True;
559 }
560
561 /********************************************************************
562  Return True is the handle is a print server.
563  ********************************************************************/
564
565 static BOOL handle_is_printserver(pipes_struct *p, POLICY_HND *handle)
566 {
567         Printer_entry *Printer=find_printer_index_by_hnd(p,handle);
568
569         if (!Printer)
570                 return False;
571                 
572         if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
573                 return False;
574         
575         return True;
576 }
577
578 /****************************************************************************
579  allocate more memory for a BUFFER.
580 ****************************************************************************/
581 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
582 {
583         prs_struct *ps;
584         uint32 extra_space;
585         uint32 old_offset;
586         
587         ps= &buffer->prs;
588
589         /* damn, I'm doing the reverse operation of prs_grow() :) */
590         if (buffer_size < prs_data_size(ps))
591                 extra_space=0;
592         else    
593                 extra_space = buffer_size - prs_data_size(ps);
594
595         /*
596          * save the offset and move to the end of the buffer
597          * prs_grow() checks the extra_space against the offset
598          */
599         old_offset=prs_offset(ps);      
600         prs_set_offset(ps, prs_data_size(ps));
601         
602         if (!prs_grow(ps, extra_space))
603                 return False;
604
605         prs_set_offset(ps, old_offset);
606
607         buffer->string_at_end=prs_data_size(ps);
608
609         return True;
610 }
611
612 /***************************************************************************
613  receive the notify message
614 ****************************************************************************/
615
616 void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
617 {
618         fstring printer;
619         uint32 status;
620         struct pipes_struct *p;
621         struct policy *pol;
622         struct handle_list *hl;
623
624         *printer = '\0';
625         fstrcpy(printer,buf);
626
627         if (len == 0) {
628                 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
629                 return;
630         }
631
632         DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer ));
633
634         /*
635          * We need to enumerate all printers. The handle list is shared
636          * across pipes of the same name, so just find the first open
637          * spoolss pipe.
638          */
639
640         hl = NULL;      
641         for ( p = get_first_pipe(); p; get_next_pipe(p)) {
642                 if (strequal(p->name, "spoolss")) {
643                         hl = p->pipe_handles;
644                         break;
645                 }
646         }
647
648         if (!hl) {
649                 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
650                 return;
651         }
652
653         /* Iterate the printer list on this pipe. */
654         for (pol = hl->Policy; pol; pol = pol->next ) {
655                 Printer_entry *find_printer = (Printer_entry *)pol->data_ptr;
656
657                 if (!find_printer)
658                         continue;
659
660                 /*
661                  * if the entry is the given printer or if it's a printerserver
662                  * we send the message
663                  */
664
665                 if (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
666                         if (strcmp(find_printer->dev.handlename, printer))
667                                 continue;
668
669                 if (find_printer->notify.client_connected==True)
670                         cli_spoolss_reply_rrpcn(&cli, &find_printer->notify.client_hnd, PRINTER_CHANGE_ALL, 0x0, &status);
671         }
672 }
673
674 /***************************************************************************
675  send a notify event
676 ****************************************************************************/
677 static BOOL srv_spoolss_sendnotify(pipes_struct *p, POLICY_HND *handle)
678 {
679         fstring printer;
680
681         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
682
683         if (!Printer) {
684                 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle)));
685                 return False;
686         }
687
688         if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
689                 fstrcpy(printer, Printer->dev.handlename);
690         else
691                 fstrcpy(printer, "");
692
693         /*srv_spoolss_receive_message(printer);*/
694         DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer ));
695
696         message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, printer, strlen(printer) + 1, False); /* Null terminate... */
697
698         return True;
699 }       
700
701 /********************************************************************
702  * spoolss_open_printer
703  *
704  * called from the spoolss dispatcher
705  ********************************************************************/
706
707 uint32 _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
708 {
709 #if 0
710         uint32 result = NT_STATUS_NO_PROBLEMO;
711 #endif
712
713         UNISTR2 *printername = NULL;
714         PRINTER_DEFAULT *printer_default = &q_u->printer_default;
715 /*      uint32 user_switch = q_u->user_switch; - notused */
716 /*      SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
717         POLICY_HND *handle = &r_u->handle;
718
719         fstring name;
720         int snum;
721         struct current_user user;
722
723         if (q_u->printername_ptr != 0)
724                 printername = &q_u->printername;
725
726         if (printername == NULL)
727                 return ERROR_INVALID_PRINTER_NAME;
728
729         /* some sanity check because you can open a printer or a print server */
730         /* aka: \\server\printer or \\server */
731         unistr2_to_ascii(name, printername, sizeof(name)-1);
732
733         DEBUGADD(3,("checking name: %s\n",name));
734
735         if (!open_printer_hnd(p, handle, name))
736                 return ERROR_INVALID_PRINTER_NAME;
737         
738 /*
739         if (printer_default->datatype_ptr != NULL)
740         {
741                 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
742                 set_printer_hnd_datatype(handle, datatype);
743         }
744         else
745                 set_printer_hnd_datatype(handle, "");
746 */
747         
748         if (!set_printer_hnd_accesstype(p, handle, printer_default->access_required)) {
749                 close_printer_handle(p, handle);
750                 return ERROR_ACCESS_DENIED;
751         }
752                 
753         /*
754            First case: the user is opening the print server:
755
756            Disallow MS AddPrinterWizard if parameter disables it. A Win2k
757            client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
758
759            Then both Win2k and WinNT clients try an OpenPrinterEx with
760            SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
761            or if the user is listed in the smb.conf printer admin parameter.
762
763            Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
764            client view printer folder, but does not show the MSAPW.
765
766            Note: this test needs code to check access rights here too. Jeremy
767            could you look at this?
768            
769            
770            Second case: the user is opening a printer:
771            NT doesn't let us connect to a printer if the connecting user
772            doesn't have print permission.
773
774         */
775
776         get_current_user(&user, p);
777
778         if (handle_is_printserver(p, handle)) {
779                 if (printer_default->access_required == 0) {
780                         return NT_STATUS_NO_PROBLEMO;
781                 }
782                 else if ((printer_default->access_required & SERVER_ACCESS_ADMINISTER ) == SERVER_ACCESS_ADMINISTER) {
783
784                         /* Printserver handles use global struct... */
785                         snum = -1;
786
787                         if (!lp_ms_add_printer_wizard()) {
788                                 close_printer_handle(p, handle);
789                                 return ERROR_ACCESS_DENIED;
790                         }
791                         else if (user.uid == 0 || user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) {
792                                 return NT_STATUS_NO_PROBLEMO;
793                         } 
794                         else {
795                                 close_printer_handle(p, handle);
796                                 return ERROR_ACCESS_DENIED;
797                         }
798                 }
799         }
800         else
801         {
802                 /* NT doesn't let us connect to a printer if the connecting user
803                    doesn't have print permission.  */
804
805                 if (!get_printer_snum(p, handle, &snum))
806                         return ERROR_INVALID_HANDLE;
807
808                 /* map an empty access mask to the minimum access mask */
809                 if (printer_default->access_required == 0x0)
810                         printer_default->access_required = PRINTER_ACCESS_USE;
811
812                 if (!print_access_check(&user, snum, printer_default->access_required)) {
813                         DEBUG(3, ("access DENIED for printer open\n"));
814                         close_printer_handle(p, handle);
815                         return ERROR_ACCESS_DENIED;
816                 }
817
818                 /*
819                  * If we have a default device pointer in the
820                  * printer_default struct, then we need to get
821                  * the printer info from the tdb and if there is
822                  * no default devicemode there then we do a *SET*
823                  * here ! This is insanity.... JRA.
824                  */
825
826                 /*
827                  * If the openprinterex rpc call contains a devmode,
828                  * it's a per-user one. This per-user devmode is derivated
829                  * from the global devmode. Openprinterex() contains a per-user 
830                  * devmode for when you do EMF printing and spooling.
831                  * In the EMF case, the NT workstation is only doing half the job
832                  * of rendering the page. The other half is done by running the printer
833                  * driver on the server.
834                  * The EMF file doesn't contain the page description (paper size, orientation, ...).
835                  * The EMF file only contains what is to be printed on the page.
836                  * So in order for the server to know how to print, the NT client sends
837                  * a devicemode attached to the openprinterex call.
838                  * But this devicemode is short lived, it's only valid for the current print job.
839                  *
840                  * If Samba would have supported EMF spooling, this devicemode would
841                  * have been attached to the handle, to sent it to the driver to correctly
842                  * rasterize the EMF file.
843                  *
844                  * As Samba only supports RAW spooling, we only receive a ready-to-print file,
845                  * we just act as a pass-thru between windows and the printer.
846                  *
847                  * In order to know that Samba supports only RAW spooling, NT has to call
848                  * getprinter() at level 2 (attribute field) or NT has to call startdoc()
849                  * and until NT sends a RAW job, we refuse it.
850                  *
851                  * But to call getprinter() or startdoc(), you first need a valid handle,
852                  * and to get an handle you have to call openprintex(). Hence why you have
853                  * a devicemode in the openprinterex() call.
854                  *
855                  *
856                  * Differences between NT4 and NT 2000.
857                  * NT4:
858                  * ---
859                  * On NT4, you only have a global devicemode. This global devicemode can be changed
860                  * by the administrator (or by a user with enough privs). Everytime a user
861                  * wants to print, the devicemode is resetted to the default. In Word, everytime
862                  * you print, the printer's characteristics are always reset to the global devicemode.
863                  *
864                  * NT 2000:
865                  * -------
866                  * In W2K, there is the notion of per-user devicemode. The first time you use
867                  * a printer, a per-user devicemode is build from the global devicemode.
868                  * If you change your per-user devicemode, it is saved in the registry, under the
869                  * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
870                  * printer preferences available.
871                  *
872                  * To change the per-user devicemode: it's the "Printing Preferences ..." button
873                  * on the General Tab of the printer properties windows.
874                  *
875                  * To change the global devicemode: it's the "Printing Defaults..." button
876                  * on the Advanced Tab of the printer properties window.
877                  *
878                  * JFM.
879                  */
880
881
882
883 #if 0
884                 if (printer_default->devmode_cont.devmode != NULL) {
885                         result = printer_write_default_dev( snum, printer_default);
886                         if (result != 0) {
887                                 close_printer_handle(p, handle);
888                                 return result;
889                         }
890                 }
891 #endif
892         }
893
894         return NT_STATUS_NO_PROBLEMO;
895 }
896
897 /****************************************************************************
898 ****************************************************************************/
899 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
900                                 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
901 {
902         switch (level) {
903                 case 2:
904                         uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
905                         break;
906                 default:
907                         break;
908         }
909
910         return True;
911 }
912
913 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
914                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
915 {
916         switch (level) {
917                 case 3:
918                         printer->info_3=NULL;
919                         uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
920                         break;
921                 case 6:
922                         printer->info_6=NULL;
923                         uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
924                         break;
925                 default:
926                         break;
927         }
928
929         return True;
930 }
931
932 BOOL convert_devicemode(char *printername, const DEVICEMODE *devmode,
933                                 NT_DEVICEMODE **pp_nt_devmode)
934 {
935         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
936
937         /*
938          * Ensure nt_devmode is a valid pointer
939          * as we will be overwriting it.
940          */
941                 
942         if (nt_devmode == NULL) {
943                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
944                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
945                         return False;
946         }
947
948         unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
949         unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
950
951         nt_devmode->specversion=devmode->specversion;
952         nt_devmode->driverversion=devmode->driverversion;
953         nt_devmode->size=devmode->size;
954         nt_devmode->fields=devmode->fields;
955         nt_devmode->orientation=devmode->orientation;
956         nt_devmode->papersize=devmode->papersize;
957         nt_devmode->paperlength=devmode->paperlength;
958         nt_devmode->paperwidth=devmode->paperwidth;
959         nt_devmode->scale=devmode->scale;
960         nt_devmode->copies=devmode->copies;
961         nt_devmode->defaultsource=devmode->defaultsource;
962         nt_devmode->printquality=devmode->printquality;
963         nt_devmode->color=devmode->color;
964         nt_devmode->duplex=devmode->duplex;
965         nt_devmode->yresolution=devmode->yresolution;
966         nt_devmode->ttoption=devmode->ttoption;
967         nt_devmode->collate=devmode->collate;
968
969         nt_devmode->logpixels=devmode->logpixels;
970         nt_devmode->bitsperpel=devmode->bitsperpel;
971         nt_devmode->pelswidth=devmode->pelswidth;
972         nt_devmode->pelsheight=devmode->pelsheight;
973         nt_devmode->displayflags=devmode->displayflags;
974         nt_devmode->displayfrequency=devmode->displayfrequency;
975         nt_devmode->icmmethod=devmode->icmmethod;
976         nt_devmode->icmintent=devmode->icmintent;
977         nt_devmode->mediatype=devmode->mediatype;
978         nt_devmode->dithertype=devmode->dithertype;
979         nt_devmode->reserved1=devmode->reserved1;
980         nt_devmode->reserved2=devmode->reserved2;
981         nt_devmode->panningwidth=devmode->panningwidth;
982         nt_devmode->panningheight=devmode->panningheight;
983
984         /*
985          * Only change private and driverextra if the incoming devmode
986          * has a new one. JRA.
987          */
988
989         if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
990                 safe_free(nt_devmode->private);
991                 nt_devmode->driverextra=devmode->driverextra;
992                 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
993                         return False;
994                 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
995         }
996
997         *pp_nt_devmode = nt_devmode;
998
999         return True;
1000 }
1001
1002 /********************************************************************
1003  * _spoolss_enddocprinter_internal.
1004  ********************************************************************/
1005
1006 static uint32 _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1007 {
1008         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1009         
1010         if (!Printer) {
1011                 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle)));
1012                 return ERROR_INVALID_HANDLE;
1013         }
1014         
1015         Printer->document_started=False;
1016         print_job_end(Printer->jobid,True);
1017         /* error codes unhandled so far ... */
1018
1019         return 0x0;
1020 }
1021
1022 /********************************************************************
1023  * api_spoolss_closeprinter
1024  ********************************************************************/
1025
1026 uint32 _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1027 {
1028         POLICY_HND *handle = &q_u->handle;
1029
1030         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1031
1032         if (Printer && Printer->document_started)
1033                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
1034
1035         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1036
1037         if (!close_printer_handle(p, handle))
1038                 return ERROR_INVALID_HANDLE;    
1039                 
1040         return NT_STATUS_NO_PROBLEMO;
1041 }
1042
1043 /********************************************************************
1044  * api_spoolss_deleteprinter
1045
1046  ********************************************************************/
1047
1048 uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1049 {
1050         POLICY_HND *handle = &q_u->handle;
1051
1052         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1053         uint32 result;
1054
1055         if (Printer && Printer->document_started)
1056                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
1057
1058         memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1059
1060         result = delete_printer_handle(p, handle);
1061
1062         if (result == ERROR_SUCCESS) {
1063                 srv_spoolss_sendnotify(p, handle);
1064         }
1065                 
1066         return result;
1067 }
1068
1069 /********************************************************************
1070  GetPrinterData on a printer server Handle.
1071 ********************************************************************/
1072 static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
1073 {               
1074         int i;
1075         
1076         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
1077                 
1078         if (!strcmp(value, "BeepEnabled")) {
1079                 *type = 0x4;
1080                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1081                         return False;
1082                 SIVAL(*data, 0, 0x01);
1083                 *needed = 0x4;                  
1084                 return True;
1085         }
1086
1087         if (!strcmp(value, "EventLog")) {
1088                 *type = 0x4;
1089                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1090                         return False;
1091                 SIVAL(*data, 0, 0x1B);
1092                 *needed = 0x4;                  
1093                 return True;
1094         }
1095
1096         if (!strcmp(value, "NetPopup")) {
1097                 *type = 0x4;
1098                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1099                         return False;
1100                 SIVAL(*data, 0, 0x01);
1101                 *needed = 0x4;
1102                 return True;
1103         }
1104
1105         if (!strcmp(value, "MajorVersion")) {
1106                 *type = 0x4;
1107                 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
1108                         return False;
1109                 SIVAL(*data, 0, 0x02);
1110                 *needed = 0x4;
1111                 return True;
1112         }
1113
1114    if (!strcmp(value, "DefaultSpoolDirectory")) {
1115                 pstring string="You are using a Samba server";
1116                 *type = 0x1;                    
1117                 *needed = 2*(strlen(string)+1);         
1118                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1119                         return False;
1120                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1121                 
1122                 /* it's done by hand ready to go on the wire */
1123                 for (i=0; i<strlen(string); i++) {
1124                         (*data)[2*i]=string[i];
1125                         (*data)[2*i+1]='\0';
1126                 }                       
1127                 return True;
1128         }
1129
1130         if (!strcmp(value, "Architecture")) {                   
1131                 pstring string="Windows NT x86";
1132                 *type = 0x1;                    
1133                 *needed = 2*(strlen(string)+1); 
1134                 if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
1135                         return False;
1136                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
1137                 for (i=0; i<strlen(string); i++) {
1138                         (*data)[2*i]=string[i];
1139                         (*data)[2*i+1]='\0';
1140                 }                       
1141                 return True;
1142         }
1143         
1144         return False;
1145 }
1146
1147 /********************************************************************
1148  GetPrinterData on a printer Handle.
1149 ********************************************************************/
1150 static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
1151                                 fstring value, uint32 *type,
1152                                 uint8 **data, uint32 *needed, uint32 in_size )
1153 {
1154         NT_PRINTER_INFO_LEVEL *printer = NULL;
1155         int snum=0;
1156         uint8 *idata=NULL;
1157         uint32 len;
1158         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1159         
1160         DEBUG(5,("getprinterdata_printer\n"));
1161
1162         if (!Printer) {
1163                 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1164                 return False;
1165         }
1166
1167         if(!get_printer_snum(p, handle, &snum))
1168                 return False;
1169
1170         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1171                 return False;
1172
1173         if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
1174                 free_a_printer(&printer, 2);
1175                 return False;
1176         }
1177
1178         free_a_printer(&printer, 2);
1179
1180         DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
1181
1182         if (in_size) {
1183                 if((*data  = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
1184                         return False;
1185                 }
1186
1187                 memset(*data, 0, in_size *sizeof(uint8));
1188                 /* copy the min(in_size, len) */
1189                 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
1190         } else {
1191                 *data = NULL;
1192         }
1193
1194         *needed = len;
1195         
1196         DEBUG(5,("getprinterdata_printer:copy done\n"));
1197                         
1198         safe_free(idata);
1199         
1200         return True;
1201 }       
1202
1203 /********************************************************************
1204  * spoolss_getprinterdata
1205  ********************************************************************/
1206
1207 uint32 _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
1208 {
1209         POLICY_HND *handle = &q_u->handle;
1210         UNISTR2 *valuename = &q_u->valuename;
1211         uint32 in_size = q_u->size;
1212         uint32 *type = &r_u->type;
1213         uint32 *out_size = &r_u->size;
1214         uint8 **data = &r_u->data;
1215         uint32 *needed = &r_u->needed;
1216
1217         fstring value;
1218         BOOL found=False;
1219         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
1220         
1221         /*
1222          * Reminder: when it's a string, the length is in BYTES
1223          * even if UNICODE is negociated.
1224          *
1225          * JFM, 4/19/1999
1226          */
1227
1228         *out_size=in_size;
1229
1230         /* in case of problem, return some default values */
1231         *needed=0;
1232         *type=0;
1233         
1234         DEBUG(4,("_spoolss_getprinterdata\n"));
1235         
1236         if (!Printer) {
1237                 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
1238                         return ERROR_NOT_ENOUGH_MEMORY;
1239                 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1240                 return ERROR_INVALID_HANDLE;
1241         }
1242         
1243         unistr2_to_ascii(value, valuename, sizeof(value)-1);
1244         
1245         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1246                 found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
1247         else
1248                 found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
1249
1250         if (found==False) {
1251                 DEBUG(5, ("value not found, allocating %d\n", *out_size));
1252                 /* reply this param doesn't exist */
1253                 if (*out_size) {
1254                         if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
1255                                 return ERROR_NOT_ENOUGH_MEMORY;
1256                 } else {
1257                         *data = NULL;
1258                 }
1259
1260                 return ERROR_INVALID_PARAMETER;
1261         }
1262         
1263         if (*needed > *out_size)
1264                 return ERROR_MORE_DATA;
1265         else {
1266                 return NT_STATUS_NO_PROBLEMO;
1267     }
1268 }
1269
1270 /***************************************************************************
1271  connect to the client
1272 ****************************************************************************/
1273 static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
1274 {
1275         uint32 status;
1276
1277         /*
1278          * If it's the first connection, contact the client
1279          * and connect to the IPC$ share anonumously
1280          */
1281         if (smb_connections==0) {
1282                 if(!spoolss_connect_to_client(&cli, printer+2)) /* the +2 is to strip the leading 2 backslashs */
1283                         return False;
1284                 message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
1285
1286         }
1287
1288         smb_connections++;
1289
1290         if(!cli_spoolss_reply_open_printer(&cli, printer, localprinter, type, &status, handle))
1291                 return False;
1292
1293         return True;
1294 }
1295
1296 /********************************************************************
1297  * _spoolss_rffpcnex
1298  * ReplyFindFirstPrinterChangeNotifyEx
1299  *
1300  * jfmxxxx: before replying OK: status=0
1301  * should do a rpc call to the workstation asking ReplyOpenPrinter
1302  * have to code it, later.
1303  *
1304  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1305  * called from api_spoolss_rffpcnex
1306  ********************************************************************/
1307
1308 uint32 _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
1309 {
1310         POLICY_HND *handle = &q_u->handle;
1311         uint32 flags = q_u->flags;
1312         uint32 options = q_u->options;
1313         UNISTR2 *localmachine = &q_u->localmachine;
1314         uint32 printerlocal = q_u->printerlocal;
1315         SPOOL_NOTIFY_OPTION *option = q_u->option;
1316
1317         /* store the notify value in the printer struct */
1318
1319         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1320
1321         if (!Printer) {
1322                 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
1323                 return ERROR_INVALID_HANDLE;
1324         }
1325
1326         Printer->notify.flags=flags;
1327         Printer->notify.options=options;
1328         Printer->notify.printerlocal=printerlocal;
1329
1330         if (Printer->notify.option)
1331                 free_spool_notify_option(&Printer->notify.option);
1332
1333         Printer->notify.option=dup_spool_notify_option(option);
1334
1335         unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
1336
1337         /* connect to the client machine and send a ReplyOpenPrinter */
1338         if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
1339                                         Printer->notify.printerlocal, 1,
1340                                         &Printer->notify.client_hnd))
1341                 Printer->notify.client_connected=True;
1342
1343         return NT_STATUS_NO_PROBLEMO;
1344 }
1345
1346 /*******************************************************************
1347  * fill a notify_info_data with the servername
1348  ********************************************************************/
1349
1350 static void spoolss_notify_server_name(int snum, 
1351                                        SPOOL_NOTIFY_INFO_DATA *data, 
1352                                        print_queue_struct *queue,
1353                                        NT_PRINTER_INFO_LEVEL *printer,
1354                                        TALLOC_CTX *mem_ctx) 
1355 {
1356         pstring temp_name, temp;
1357         uint32 len;
1358
1359         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
1360
1361         len = (uint32)dos_PutUniCode(temp, temp_name, sizeof(temp) - 2, True);
1362
1363         data->notify_data.data.length = len / 2 - 1;
1364         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1365
1366         if (!data->notify_data.data.string) {
1367                 data->notify_data.data.length = 0;
1368                 return;
1369         }
1370         
1371         memcpy(data->notify_data.data.string, temp, len);
1372 }
1373
1374 /*******************************************************************
1375  * fill a notify_info_data with the printername (not including the servername).
1376  ********************************************************************/
1377 static void spoolss_notify_printer_name(int snum, 
1378                                         SPOOL_NOTIFY_INFO_DATA *data, 
1379                                         print_queue_struct *queue,
1380                                         NT_PRINTER_INFO_LEVEL *printer,
1381                                         TALLOC_CTX *mem_ctx)
1382 {
1383         pstring temp;
1384         uint32 len;
1385                 
1386         /* the notify name should not contain the \\server\ part */
1387         char *p = strrchr(printer->info_2->printername, '\\');
1388
1389         if (!p) {
1390                 p = printer->info_2->printername;
1391         } else {
1392                 p++;
1393         }
1394
1395         len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1396
1397         data->notify_data.data.length = len / 2 - 1;
1398         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1399         
1400         if (!data->notify_data.data.string) {
1401                 data->notify_data.data.length = 0;
1402                 return;
1403         }
1404         
1405         memcpy(data->notify_data.data.string, temp, len);
1406 }
1407
1408 /*******************************************************************
1409  * fill a notify_info_data with the servicename
1410  ********************************************************************/
1411 static void spoolss_notify_share_name(int snum, 
1412                                       SPOOL_NOTIFY_INFO_DATA *data, 
1413                                       print_queue_struct *queue,
1414                                       NT_PRINTER_INFO_LEVEL *printer,
1415                                       TALLOC_CTX *mem_ctx)
1416 {
1417         pstring temp;
1418         uint32 len;
1419
1420         len = (uint32)dos_PutUniCode(temp, lp_servicename(snum), 
1421                                      sizeof(temp) - 2, True);
1422
1423         data->notify_data.data.length = len / 2 - 1;
1424         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1425         
1426         if (!data->notify_data.data.string) {
1427                 data->notify_data.data.length = 0;
1428                 return;
1429         }
1430         
1431         memcpy(data->notify_data.data.string, temp, len);
1432 }
1433
1434 /*******************************************************************
1435  * fill a notify_info_data with the port name
1436  ********************************************************************/
1437 static void spoolss_notify_port_name(int snum, 
1438                                      SPOOL_NOTIFY_INFO_DATA *data, 
1439                                      print_queue_struct *queue,
1440                                      NT_PRINTER_INFO_LEVEL *printer,
1441                                      TALLOC_CTX *mem_ctx)
1442 {
1443         pstring temp;
1444         uint32 len;
1445
1446         /* even if it's strange, that's consistant in all the code */
1447
1448         len = (uint32)dos_PutUniCode(temp, printer->info_2->portname, 
1449                                      sizeof(temp) - 2, True);
1450
1451         data->notify_data.data.length = len / 2 - 1;
1452         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1453         
1454         if (!data->notify_data.data.string) {
1455                 data->notify_data.data.length = 0;
1456                 return;
1457         }
1458         
1459         memcpy(data->notify_data.data.string, temp, len);
1460 }
1461
1462 /*******************************************************************
1463  * fill a notify_info_data with the printername
1464  * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1465  * but it doesn't exist, have to see what to do
1466  ********************************************************************/
1467 static void spoolss_notify_driver_name(int snum, 
1468                                        SPOOL_NOTIFY_INFO_DATA *data,
1469                                        print_queue_struct *queue,
1470                                        NT_PRINTER_INFO_LEVEL *printer,
1471                                        TALLOC_CTX *mem_ctx)
1472 {
1473         pstring temp;
1474         uint32 len;
1475
1476         len = (uint32)dos_PutUniCode(temp, printer->info_2->drivername, 
1477                                      sizeof(temp) - 2, True);
1478
1479         data->notify_data.data.length = len / 2 - 1;
1480         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1481         
1482         if (!data->notify_data.data.string) {
1483                 data->notify_data.data.length = 0;
1484                 return;
1485         }
1486         
1487         memcpy(data->notify_data.data.string, temp, len);
1488 }
1489
1490 /*******************************************************************
1491  * fill a notify_info_data with the comment
1492  ********************************************************************/
1493 static void spoolss_notify_comment(int snum, 
1494                                    SPOOL_NOTIFY_INFO_DATA *data,
1495                                    print_queue_struct *queue,
1496                                    NT_PRINTER_INFO_LEVEL *printer,
1497                                    TALLOC_CTX *mem_ctx)
1498 {
1499         pstring temp;
1500         uint32 len;
1501
1502         if (*printer->info_2->comment == '\0')
1503                 len = (uint32)dos_PutUniCode(temp, lp_comment(snum), 
1504                                              sizeof(temp) - 2, True);
1505         else
1506                 len = (uint32)dos_PutUniCode(temp, printer->info_2->comment, 
1507                                              sizeof(temp) - 2, True);
1508
1509         data->notify_data.data.length = len / 2 - 1;
1510         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1511         
1512         if (!data->notify_data.data.string) {
1513                 data->notify_data.data.length = 0;
1514                 return;
1515         }
1516         
1517         memcpy(data->notify_data.data.string, temp, len);
1518 }
1519
1520 /*******************************************************************
1521  * fill a notify_info_data with the comment
1522  * jfm:xxxx incorrect, have to create a new smb.conf option
1523  * location = "Room 1, floor 2, building 3"
1524  ********************************************************************/
1525 static void spoolss_notify_location(int snum, 
1526                                     SPOOL_NOTIFY_INFO_DATA *data,
1527                                     print_queue_struct *queue,
1528                                     NT_PRINTER_INFO_LEVEL *printer,
1529                                     TALLOC_CTX *mem_ctx)
1530 {
1531         pstring temp;
1532         uint32 len;
1533
1534         len = (uint32)dos_PutUniCode(temp, printer->info_2->location, 
1535                                      sizeof(temp) - 2, True);
1536
1537         data->notify_data.data.length = len / 2 - 1;
1538         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1539         
1540         if (!data->notify_data.data.string) {
1541                 data->notify_data.data.length = 0;
1542                 return;
1543         }
1544         
1545         memcpy(data->notify_data.data.string, temp, len);
1546 }
1547
1548 /*******************************************************************
1549  * fill a notify_info_data with the device mode
1550  * jfm:xxxx don't to it for know but that's a real problem !!!
1551  ********************************************************************/
1552 static void spoolss_notify_devmode(int snum, 
1553                                    SPOOL_NOTIFY_INFO_DATA *data,
1554                                    print_queue_struct *queue,
1555                                    NT_PRINTER_INFO_LEVEL *printer,
1556                                    TALLOC_CTX *mem_ctx)
1557 {
1558 }
1559
1560 /*******************************************************************
1561  * fill a notify_info_data with the separator file name
1562  * jfm:xxxx just return no file could add an option to smb.conf
1563  * separator file = "separator.txt"
1564  ********************************************************************/
1565 static void spoolss_notify_sepfile(int snum, 
1566                                    SPOOL_NOTIFY_INFO_DATA *data, 
1567                                    print_queue_struct *queue,
1568                                    NT_PRINTER_INFO_LEVEL *printer,
1569                                    TALLOC_CTX *mem_ctx)
1570 {
1571         pstring temp;
1572         uint32 len;
1573
1574         len = (uint32)dos_PutUniCode(temp, printer->info_2->sepfile, 
1575                                      sizeof(temp) - 2, True);
1576
1577         data->notify_data.data.length = len / 2 - 1;
1578         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1579         
1580         if (!data->notify_data.data.string) {
1581                 data->notify_data.data.length = 0;
1582                 return;
1583         }
1584         
1585         memcpy(data->notify_data.data.string, temp, len);
1586 }
1587
1588 /*******************************************************************
1589  * fill a notify_info_data with the print processor
1590  * jfm:xxxx return always winprint to indicate we don't do anything to it
1591  ********************************************************************/
1592 static void spoolss_notify_print_processor(int snum, 
1593                                            SPOOL_NOTIFY_INFO_DATA *data,
1594                                            print_queue_struct *queue,
1595                                            NT_PRINTER_INFO_LEVEL *printer,
1596                                            TALLOC_CTX *mem_ctx)
1597 {
1598         pstring temp;
1599         uint32 len;
1600
1601         len = (uint32)dos_PutUniCode(temp, printer->info_2->printprocessor, 
1602                                      sizeof(temp) - 2, True);
1603
1604         data->notify_data.data.length = len / 2 - 1;
1605         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1606         
1607         if (!data->notify_data.data.string) {
1608                 data->notify_data.data.length = 0;
1609                 return;
1610         }
1611         
1612         memcpy(data->notify_data.data.string, temp, len);
1613 }
1614
1615 /*******************************************************************
1616  * fill a notify_info_data with the print processor options
1617  * jfm:xxxx send an empty string
1618  ********************************************************************/
1619 static void spoolss_notify_parameters(int snum, 
1620                                       SPOOL_NOTIFY_INFO_DATA *data,
1621                                       print_queue_struct *queue,
1622                                       NT_PRINTER_INFO_LEVEL *printer,
1623                                       TALLOC_CTX *mem_ctx)
1624 {
1625         pstring temp;
1626         uint32 len;
1627
1628         len = (uint32)dos_PutUniCode(temp, printer->info_2->parameters, 
1629                                      sizeof(temp) - 2, True);
1630
1631         data->notify_data.data.length = len / 2 - 1;
1632         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1633         
1634         if (!data->notify_data.data.string) {
1635                 data->notify_data.data.length = 0;
1636                 return;
1637         }
1638         
1639         memcpy(data->notify_data.data.string, temp, len);
1640 }
1641
1642 /*******************************************************************
1643  * fill a notify_info_data with the data type
1644  * jfm:xxxx always send RAW as data type
1645  ********************************************************************/
1646 static void spoolss_notify_datatype(int snum, 
1647                                     SPOOL_NOTIFY_INFO_DATA *data,
1648                                     print_queue_struct *queue,
1649                                     NT_PRINTER_INFO_LEVEL *printer,
1650                                     TALLOC_CTX *mem_ctx)
1651 {
1652         pstring temp;
1653         uint32 len;
1654
1655         len = (uint32)dos_PutUniCode(temp, printer->info_2->datatype, 
1656                                      sizeof(pstring) - 2, True);
1657
1658         data->notify_data.data.length = len / 2 - 1;
1659         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1660         
1661         if (!data->notify_data.data.string) {
1662                 data->notify_data.data.length = 0;
1663                 return;
1664         }
1665         
1666         memcpy(data->notify_data.data.string, temp, len);
1667 }
1668
1669 /*******************************************************************
1670  * fill a notify_info_data with the security descriptor
1671  * jfm:xxxx send an null pointer to say no security desc
1672  * have to implement security before !
1673  ********************************************************************/
1674 static void spoolss_notify_security_desc(int snum, 
1675                                          SPOOL_NOTIFY_INFO_DATA *data,
1676                                          print_queue_struct *queue,
1677                                          NT_PRINTER_INFO_LEVEL *printer,
1678                                          TALLOC_CTX *mem_ctx)
1679 {
1680         data->notify_data.data.length=0;
1681         data->notify_data.data.string = NULL;
1682 }
1683
1684 /*******************************************************************
1685  * fill a notify_info_data with the attributes
1686  * jfm:xxxx a samba printer is always shared
1687  ********************************************************************/
1688 static void spoolss_notify_attributes(int snum, 
1689                                       SPOOL_NOTIFY_INFO_DATA *data,
1690                                       print_queue_struct *queue,
1691                                       NT_PRINTER_INFO_LEVEL *printer,
1692                                       TALLOC_CTX *mem_ctx)
1693 {
1694         data->notify_data.value[0] = printer->info_2->attributes;
1695 }
1696
1697 /*******************************************************************
1698  * fill a notify_info_data with the priority
1699  ********************************************************************/
1700 static void spoolss_notify_priority(int snum, 
1701                                     SPOOL_NOTIFY_INFO_DATA *data,
1702                                     print_queue_struct *queue,
1703                                     NT_PRINTER_INFO_LEVEL *printer,
1704                                     TALLOC_CTX *mem_ctx)
1705 {
1706         data->notify_data.value[0] = printer->info_2->priority;
1707 }
1708
1709 /*******************************************************************
1710  * fill a notify_info_data with the default priority
1711  ********************************************************************/
1712 static void spoolss_notify_default_priority(int snum, 
1713                                             SPOOL_NOTIFY_INFO_DATA *data,
1714                                             print_queue_struct *queue,
1715                                             NT_PRINTER_INFO_LEVEL *printer,
1716                                             TALLOC_CTX *mem_ctx)
1717 {
1718         data->notify_data.value[0] = printer->info_2->default_priority;
1719 }
1720
1721 /*******************************************************************
1722  * fill a notify_info_data with the start time
1723  ********************************************************************/
1724 static void spoolss_notify_start_time(int snum, 
1725                                       SPOOL_NOTIFY_INFO_DATA *data,
1726                                       print_queue_struct *queue,
1727                                       NT_PRINTER_INFO_LEVEL *printer,
1728                                       TALLOC_CTX *mem_ctx)
1729 {
1730         data->notify_data.value[0] = printer->info_2->starttime;
1731 }
1732
1733 /*******************************************************************
1734  * fill a notify_info_data with the until time
1735  ********************************************************************/
1736 static void spoolss_notify_until_time(int snum, 
1737                                       SPOOL_NOTIFY_INFO_DATA *data,
1738                                       print_queue_struct *queue,
1739                                       NT_PRINTER_INFO_LEVEL *printer,
1740                                       TALLOC_CTX *mem_ctx)
1741 {
1742         data->notify_data.value[0] = printer->info_2->untiltime;
1743 }
1744
1745 /*******************************************************************
1746  * fill a notify_info_data with the status
1747  ********************************************************************/
1748 static void spoolss_notify_status(int snum, 
1749                                   SPOOL_NOTIFY_INFO_DATA *data,
1750                                   print_queue_struct *queue,
1751                                   NT_PRINTER_INFO_LEVEL *printer,
1752                                   TALLOC_CTX *mem_ctx)
1753 {
1754         print_queue_struct *q=NULL;
1755         print_status_struct status;
1756
1757         memset(&status, 0, sizeof(status));
1758         print_queue_status(snum, &q, &status);
1759         data->notify_data.value[0]=(uint32) status.status;
1760         safe_free(q);
1761 }
1762
1763 /*******************************************************************
1764  * fill a notify_info_data with the number of jobs queued
1765  ********************************************************************/
1766 static void spoolss_notify_cjobs(int snum, 
1767                                  SPOOL_NOTIFY_INFO_DATA *data,
1768                                  print_queue_struct *queue,
1769                                  NT_PRINTER_INFO_LEVEL *printer, 
1770                                  TALLOC_CTX *mem_ctx)
1771 {
1772         print_queue_struct *q=NULL;
1773         print_status_struct status;
1774
1775         memset(&status, 0, sizeof(status));
1776         data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1777         safe_free(q);
1778 }
1779
1780 /*******************************************************************
1781  * fill a notify_info_data with the average ppm
1782  ********************************************************************/
1783 static void spoolss_notify_average_ppm(int snum, 
1784                                        SPOOL_NOTIFY_INFO_DATA *data,
1785                                        print_queue_struct *queue,
1786                                        NT_PRINTER_INFO_LEVEL *printer,
1787                                        TALLOC_CTX *mem_ctx)
1788 {
1789         /* always respond 8 pages per minutes */
1790         /* a little hard ! */
1791         data->notify_data.value[0] = printer->info_2->averageppm;
1792 }
1793
1794 /*******************************************************************
1795  * fill a notify_info_data with username
1796  ********************************************************************/
1797 static void spoolss_notify_username(int snum, 
1798                                     SPOOL_NOTIFY_INFO_DATA *data,
1799                                     print_queue_struct *queue,
1800                                     NT_PRINTER_INFO_LEVEL *printer,
1801                                     TALLOC_CTX *mem_ctx)
1802 {
1803         pstring temp;
1804         uint32 len;
1805
1806         len = (uint32)dos_PutUniCode(temp, queue->user, 
1807                                      sizeof(temp) - 2, True);
1808
1809         data->notify_data.data.length = len / 2 - 1;
1810         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1811         
1812         if (!data->notify_data.data.string) {
1813                 data->notify_data.data.length = 0;
1814                 return;
1815         }
1816         
1817         memcpy(data->notify_data.data.string, temp, len);
1818 }
1819
1820 /*******************************************************************
1821  * fill a notify_info_data with job status
1822  ********************************************************************/
1823 static void spoolss_notify_job_status(int snum, 
1824                                       SPOOL_NOTIFY_INFO_DATA *data,
1825                                       print_queue_struct *queue,
1826                                       NT_PRINTER_INFO_LEVEL *printer,
1827                                       TALLOC_CTX *mem_ctx)
1828 {
1829         data->notify_data.value[0]=nt_printj_status(queue->status);
1830 }
1831
1832 /*******************************************************************
1833  * fill a notify_info_data with job name
1834  ********************************************************************/
1835 static void spoolss_notify_job_name(int snum, 
1836                                     SPOOL_NOTIFY_INFO_DATA *data,
1837                                     print_queue_struct *queue,
1838                                     NT_PRINTER_INFO_LEVEL *printer,
1839                                     TALLOC_CTX *mem_ctx)
1840 {
1841         pstring temp;
1842         uint32 len;
1843
1844         len = (uint32)dos_PutUniCode(temp, queue->file, sizeof(temp) - 2, 
1845                                      True);
1846
1847         data->notify_data.data.length = len / 2 - 1;
1848         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1849         
1850         if (!data->notify_data.data.string) {
1851                 data->notify_data.data.length = 0;
1852                 return;
1853         }
1854         
1855         memcpy(data->notify_data.data.string, temp, len);
1856 }
1857
1858 /*******************************************************************
1859  * fill a notify_info_data with job status
1860  ********************************************************************/
1861 static void spoolss_notify_job_status_string(int snum, 
1862                                              SPOOL_NOTIFY_INFO_DATA *data,
1863                                              print_queue_struct *queue,
1864                                              NT_PRINTER_INFO_LEVEL *printer, 
1865                                              TALLOC_CTX *mem_ctx)
1866 {
1867         /*
1868          * Now we're returning job status codes we just return a "" here. JRA.
1869          */
1870
1871         char *p = "";
1872         pstring temp;
1873         uint32 len;
1874
1875 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1876         p = "unknown";
1877
1878         switch (queue->status) {
1879         case LPQ_QUEUED:
1880                 p = "Queued";
1881                 break;
1882         case LPQ_PAUSED:
1883                 p = "";    /* NT provides the paused string */
1884                 break;
1885         case LPQ_SPOOLING:
1886                 p = "Spooling";
1887                 break;
1888         case LPQ_PRINTING:
1889                 p = "Printing";
1890                 break;
1891         }
1892 #endif /* NO LONGER NEEDED. */
1893
1894         len = (uint32)dos_PutUniCode(temp, p, sizeof(temp) - 2, True);
1895
1896         data->notify_data.data.length = len / 2 - 1;
1897         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1898         
1899         if (!data->notify_data.data.string) {
1900                 data->notify_data.data.length = 0;
1901                 return;
1902         }
1903         
1904         memcpy(data->notify_data.data.string, temp, len);
1905 }
1906
1907 /*******************************************************************
1908  * fill a notify_info_data with job time
1909  ********************************************************************/
1910 static void spoolss_notify_job_time(int snum, 
1911                                     SPOOL_NOTIFY_INFO_DATA *data,
1912                                     print_queue_struct *queue,
1913                                     NT_PRINTER_INFO_LEVEL *printer,
1914                                     TALLOC_CTX *mem_ctx)
1915 {
1916         data->notify_data.value[0]=0x0;
1917 }
1918
1919 /*******************************************************************
1920  * fill a notify_info_data with job size
1921  ********************************************************************/
1922 static void spoolss_notify_job_size(int snum, 
1923                                     SPOOL_NOTIFY_INFO_DATA *data,
1924                                     print_queue_struct *queue,
1925                                     NT_PRINTER_INFO_LEVEL *printer,
1926                                     TALLOC_CTX *mem_ctx)
1927 {
1928         data->notify_data.value[0]=queue->size;
1929 }
1930
1931 /*******************************************************************
1932  * fill a notify_info_data with job position
1933  ********************************************************************/
1934 static void spoolss_notify_job_position(int snum, 
1935                                         SPOOL_NOTIFY_INFO_DATA *data,
1936                                         print_queue_struct *queue,
1937                                         NT_PRINTER_INFO_LEVEL *printer,
1938                                         TALLOC_CTX *mem_ctx)
1939 {
1940         data->notify_data.value[0]=queue->job;
1941 }
1942
1943 /*******************************************************************
1944  * fill a notify_info_data with submitted time
1945  ********************************************************************/
1946 static void spoolss_notify_submitted_time(int snum, 
1947                                           SPOOL_NOTIFY_INFO_DATA *data,
1948                                           print_queue_struct *queue,
1949                                           NT_PRINTER_INFO_LEVEL *printer,
1950                                           TALLOC_CTX *mem_ctx)
1951 {
1952         struct tm *t;
1953         uint32 len;
1954         SYSTEMTIME st;
1955
1956         t=gmtime(&queue->time);
1957
1958         len = sizeof(SYSTEMTIME);
1959
1960         data->notify_data.data.length = len/2 - 1;
1961         data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
1962
1963         if (!data->notify_data.data.string) {
1964                 data->notify_data.data.length = 0;
1965                 return;
1966         }
1967         
1968         make_systemtime(&st, t);
1969         memcpy(data->notify_data.data.string,&st,len);
1970 }
1971
1972 #define END 65535
1973
1974 struct s_notify_info_data_table
1975 {
1976         uint16 type;
1977         uint16 field;
1978         char *name;
1979         uint32 size;
1980         void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1981                     print_queue_struct *queue,
1982                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
1983 };
1984
1985 struct s_notify_info_data_table notify_info_data_table[] =
1986 {
1987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         POINTER,   spoolss_notify_server_name },
1988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        POINTER,   spoolss_notify_printer_name },
1989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          POINTER,   spoolss_notify_share_name },
1990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           POINTER,   spoolss_notify_port_name },
1991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         POINTER,   spoolss_notify_driver_name },
1992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             POINTER,   spoolss_notify_comment },
1993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            POINTER,   spoolss_notify_location },
1994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             POINTER,   spoolss_notify_devmode },
1995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             POINTER,   spoolss_notify_sepfile },
1996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     POINTER,   spoolss_notify_print_processor },
1997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          POINTER,   spoolss_notify_parameters },
1998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            POINTER,   spoolss_notify_datatype },
1999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER,   spoolss_notify_security_desc },
2000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          ONE_VALUE, spoolss_notify_attributes },
2001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            ONE_VALUE, spoolss_notify_priority },
2002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    ONE_VALUE, spoolss_notify_default_priority },
2003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          ONE_VALUE, spoolss_notify_start_time },
2004 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          ONE_VALUE, spoolss_notify_until_time },
2005 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              ONE_VALUE, spoolss_notify_status },
2006 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       POINTER,   NULL },
2007 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               ONE_VALUE, spoolss_notify_cjobs },
2008 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         ONE_VALUE, spoolss_notify_average_ppm },
2009 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         POINTER,   NULL },
2010 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       POINTER,   NULL },
2011 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         POINTER,   NULL },
2012 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       POINTER,   NULL },
2013 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            POINTER,   spoolss_notify_printer_name },
2014 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            POINTER,   spoolss_notify_server_name },
2015 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               POINTER,   spoolss_notify_port_name },
2016 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               POINTER,   spoolss_notify_username },
2017 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             POINTER,   spoolss_notify_username },
2018 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                POINTER,   spoolss_notify_datatype },
2019 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         POINTER,   spoolss_notify_print_processor },
2020 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              POINTER,   spoolss_notify_parameters },
2021 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             POINTER,   spoolss_notify_driver_name },
2022 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 POINTER,   spoolss_notify_devmode },
2023 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  ONE_VALUE, spoolss_notify_job_status },
2024 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           POINTER,   spoolss_notify_job_status_string },
2025 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     POINTER,   NULL },
2026 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                POINTER,   spoolss_notify_job_name },
2027 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                ONE_VALUE, spoolss_notify_priority },
2028 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                ONE_VALUE, spoolss_notify_job_position },
2029 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               POINTER,   spoolss_notify_submitted_time },
2030 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              ONE_VALUE, spoolss_notify_start_time },
2031 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              ONE_VALUE, spoolss_notify_until_time },
2032 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    ONE_VALUE, spoolss_notify_job_time },
2033 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             ONE_VALUE, NULL },
2034 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           ONE_VALUE, NULL },
2035 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             ONE_VALUE, spoolss_notify_job_size },
2036 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_BYTES_PRINTED,           "JOB_NOTIFY_BYTES_PRINTED",           ONE_VALUE, NULL },
2037 { END,                 END,                                "",                                   END,       NULL }
2038 };
2039
2040 /*******************************************************************
2041 return the size of info_data structure
2042 ********************************************************************/
2043 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
2044 {
2045         int i=0;
2046
2047         while (notify_info_data_table[i].type != END)
2048         {
2049                 if ( (notify_info_data_table[i].type == type ) &&
2050                      (notify_info_data_table[i].field == field ) )
2051                 {
2052                         return (notify_info_data_table[i].size);
2053                 }
2054                 i++;
2055         }
2056         return (65535);
2057 }
2058
2059 /*******************************************************************
2060 return the type of notify_info_data
2061 ********************************************************************/
2062 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
2063 {
2064         int i=0;
2065
2066         while (notify_info_data_table[i].type != END)
2067         {
2068                 if ( (notify_info_data_table[i].type == type ) &&
2069                      (notify_info_data_table[i].field == field ) )
2070                 {
2071                         if (notify_info_data_table[i].size == POINTER)
2072                         {
2073                                 return (False);
2074                         }
2075                         else
2076                         {
2077                                 return (True);
2078                         }
2079                 }
2080                 i++;
2081         }
2082         return (False);
2083 }
2084
2085 /****************************************************************************
2086 ****************************************************************************/
2087 static int search_notify(uint16 type, uint16 field, int *value)
2088 {       
2089         int j;
2090         BOOL found;
2091
2092         for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
2093         {
2094                 if ( (notify_info_data_table[j].type  == type  ) &&
2095                      (notify_info_data_table[j].field == field ) )
2096                         found=True;
2097         }
2098         *value=--j;
2099
2100         if ( found && (notify_info_data_table[j].fn != NULL) )
2101                 return True;
2102         else
2103                 return False;   
2104 }
2105
2106 /****************************************************************************
2107 ****************************************************************************/
2108 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
2109 {
2110         info_data->type     = type;
2111         info_data->field    = field;
2112         info_data->reserved = 0;
2113         info_data->id       = id;
2114         info_data->size     = size_of_notify_info_data(type, field);
2115         info_data->enc_type = type_of_notify_info_data(type, field);
2116 }
2117
2118
2119 /*******************************************************************
2120  *
2121  * fill a notify_info struct with info asked
2122  *
2123  ********************************************************************/
2124 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
2125                                           snum, SPOOL_NOTIFY_OPTION_TYPE
2126                                           *option_type, uint32 id,
2127                                           TALLOC_CTX *mem_ctx) 
2128 {
2129         int field_num,j;
2130         uint16 type;
2131         uint16 field;
2132
2133         SPOOL_NOTIFY_INFO_DATA *current_data;
2134         NT_PRINTER_INFO_LEVEL *printer = NULL;
2135         print_queue_struct *queue=NULL;
2136
2137         type=option_type->type;
2138
2139         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2140                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2141                 option_type->count, lp_servicename(snum)));
2142         
2143         if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2144                 return False;
2145
2146         for(field_num=0; field_num<option_type->count; field_num++) {
2147                 field = option_type->fields[field_num];
2148                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
2149
2150                 if (!search_notify(type, field, &j) )
2151                         continue;
2152                 
2153                 if((info->data=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2154                         return False;
2155                 }
2156                 current_data=&info->data[info->count];
2157
2158                 construct_info_data(current_data, type, field, id);             
2159
2160                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
2161                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
2162
2163                 notify_info_data_table[j].fn(snum, current_data, queue,
2164                                              printer, mem_ctx);
2165
2166                 info->count++;
2167         }
2168
2169         free_a_printer(&printer, 2);
2170         return True;
2171 }
2172
2173 /*******************************************************************
2174  *
2175  * fill a notify_info struct with info asked
2176  *
2177  ********************************************************************/
2178 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
2179                                        SPOOL_NOTIFY_INFO *info,
2180                                        NT_PRINTER_INFO_LEVEL *printer,
2181                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
2182                                        *option_type, uint32 id,
2183                                        TALLOC_CTX *mem_ctx) 
2184 {
2185         int field_num,j;
2186         uint16 type;
2187         uint16 field;
2188
2189         SPOOL_NOTIFY_INFO_DATA *current_data;
2190         
2191         DEBUG(4,("construct_notify_jobs_info\n"));
2192         
2193         type = option_type->type;
2194
2195         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2196                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2197                 option_type->count));
2198
2199         for(field_num=0; field_num<option_type->count; field_num++) {
2200                 field = option_type->fields[field_num];
2201
2202                 if (!search_notify(type, field, &j) )
2203                         continue;
2204
2205                 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
2206                         return False;
2207                 }
2208
2209                 current_data=&(info->data[info->count]);
2210
2211                 construct_info_data(current_data, type, field, id);
2212                 notify_info_data_table[j].fn(snum, current_data, queue,
2213                                              printer, mem_ctx);
2214                 info->count++;
2215         }
2216
2217         return True;
2218 }
2219
2220 /*
2221  * JFM: The enumeration is not that simple, it's even non obvious.
2222  *
2223  * let's take an example: I want to monitor the PRINTER SERVER for
2224  * the printer's name and the number of jobs currently queued.
2225  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2226  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2227  *
2228  * I have 3 printers on the back of my server.
2229  *
2230  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2231  * structures.
2232  *   Number     Data                    Id
2233  *      1       printer 1 name          1
2234  *      2       printer 1 cjob          1
2235  *      3       printer 2 name          2
2236  *      4       printer 2 cjob          2
2237  *      5       printer 3 name          3
2238  *      6       printer 3 name          3
2239  *
2240  * that's the print server case, the printer case is even worse.
2241  */
2242
2243 /*******************************************************************
2244  *
2245  * enumerate all printers on the printserver
2246  * fill a notify_info struct with info asked
2247  *
2248  ********************************************************************/
2249
2250 static uint32 printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, 
2251                                       SPOOL_NOTIFY_INFO *info,
2252                                       TALLOC_CTX *mem_ctx)
2253 {
2254         int snum;
2255         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2256         int n_services=lp_numservices();
2257         int i;
2258         uint32 id;
2259         SPOOL_NOTIFY_OPTION *option;
2260         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2261
2262         DEBUG(4,("printserver_notify_info\n"));
2263         
2264         option=Printer->notify.option;
2265         id=1;
2266         info->version=2;
2267         info->data=NULL;
2268         info->count=0;
2269
2270         for (i=0; i<option->count; i++) {
2271                 option_type=&(option->ctr.type[i]);
2272                 
2273                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
2274                         continue;
2275                 
2276                 for (snum=0; snum<n_services; snum++)
2277                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
2278                                 if (construct_notify_printer_info
2279                                     (info, snum, option_type, id, mem_ctx))
2280                                         id++;
2281         }
2282                         
2283         /*
2284          * Debugging information, don't delete.
2285          */
2286         /*
2287         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2288         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2289         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2290         
2291         for (i=0; i<info->count; i++) {
2292                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2293                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2294                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2295         }
2296         */
2297         
2298         return NT_STATUS_NO_PROBLEMO;
2299 }
2300
2301 /*******************************************************************
2302  *
2303  * fill a notify_info struct with info asked
2304  *
2305  ********************************************************************/
2306 static uint32 printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
2307                                   TALLOC_CTX *mem_ctx)
2308 {
2309         int snum;
2310         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
2311         int i;
2312         uint32 id;
2313         SPOOL_NOTIFY_OPTION *option;
2314         SPOOL_NOTIFY_OPTION_TYPE *option_type;
2315         int count,j;
2316         print_queue_struct *queue=NULL;
2317         print_status_struct status;
2318         
2319         DEBUG(4,("printer_notify_info\n"));
2320
2321         option=Printer->notify.option;
2322         id=0xffffffff;
2323         info->version=2;
2324         info->data=NULL;
2325         info->count=0;
2326
2327         get_printer_snum(p, hnd, &snum);
2328
2329         for (i=0; i<option->count; i++) {
2330                 option_type=&option->ctr.type[i];
2331                 
2332                 switch ( option_type->type ) {
2333                 case PRINTER_NOTIFY_TYPE:
2334                         if(construct_notify_printer_info(info, snum, 
2335                                                          option_type, id,
2336                                                          mem_ctx))  
2337                                 id--;
2338                         break;
2339                         
2340                 case JOB_NOTIFY_TYPE: {
2341                         NT_PRINTER_INFO_LEVEL *printer = NULL;
2342
2343                         memset(&status, 0, sizeof(status));     
2344                         count = print_queue_status(snum, &queue, &status);
2345
2346                         if (get_a_printer(&printer, 2, 
2347                                           lp_servicename(snum)) != 0)
2348                                 goto done;
2349
2350                         for (j=0; j<count; j++) {
2351                                 construct_notify_jobs_info(&queue[j], info,
2352                                                            printer, snum,
2353                                                            option_type,
2354                                                            queue[j].job,
2355                                                            mem_ctx); 
2356                         }
2357
2358                         free_a_printer(&printer, 2);
2359                         
2360                 done:
2361                         safe_free(queue);
2362                         break;
2363                 }
2364                 }
2365         }
2366         
2367         /*
2368          * Debugging information, don't delete.
2369          */
2370         /*
2371         DEBUG(1,("dumping the NOTIFY_INFO\n"));
2372         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2373         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2374         
2375         for (i=0; i<info->count; i++) {
2376                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2377                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2378                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2379         }
2380         */
2381         return NT_STATUS_NO_PROBLEMO;
2382 }
2383
2384 /********************************************************************
2385  * spoolss_rfnpcnex
2386  ********************************************************************/
2387
2388 uint32 _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
2389 {
2390         POLICY_HND *handle = &q_u->handle;
2391 /*      uint32 change = q_u->change; - notused. */
2392 /*      SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2393         SPOOL_NOTIFY_INFO *info = &r_u->info;
2394
2395         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2396         uint32 result = ERROR_INVALID_HANDLE;
2397
2398         /* we always have a NOTIFY_INFO struct */
2399         r_u->info_ptr=0x1;
2400
2401         if (!Printer) {
2402                 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2403                          OUR_HANDLE(handle)));
2404                 goto done;
2405         }
2406
2407         DEBUG(4,("Printer type %x\n",Printer->printer_type));
2408
2409         /* jfm: the change value isn't used right now.
2410          *      we will honour it when
2411          *      a) we'll be able to send notification to the client
2412          *      b) we'll have a way to communicate between the spoolss process.
2413          *
2414          *      same thing for option->flags
2415          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2416          *      I don't have a global notification system, I'm sending back all the
2417          *      informations even when _NOTHING_ has changed.
2418          */
2419
2420         /* just ignore the SPOOL_NOTIFY_OPTION */
2421         
2422         switch (Printer->printer_type) {
2423                 case PRINTER_HANDLE_IS_PRINTSERVER:
2424                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
2425                         break;
2426                         
2427                 case PRINTER_HANDLE_IS_PRINTER:
2428                         result = printer_notify_info(p, handle, info, p->mem_ctx);
2429                         break;
2430         }
2431         
2432  done:
2433         return result;
2434 }
2435
2436 /********************************************************************
2437  * construct_printer_info_0
2438  * fill a printer_info_0 struct
2439  ********************************************************************/
2440 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
2441 {
2442         pstring chaine;
2443         int count;
2444         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2445         counter_printer_0 *session_counter;
2446         uint32 global_counter;
2447         struct tm *t;
2448         time_t setuptime;
2449
2450         print_queue_struct *queue=NULL;
2451         print_status_struct status;
2452         
2453         memset(&status, 0, sizeof(status));     
2454
2455         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2456                 return False;
2457
2458         count = print_queue_status(snum, &queue, &status);
2459
2460         /* check if we already have a counter for this printer */       
2461         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
2462
2463         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
2464                 if (session_counter->snum == snum)
2465                         break;
2466         }
2467
2468         /* it's the first time, add it to the list */
2469         if (session_counter==NULL) {
2470                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
2471                         free_a_printer(&ntprinter, 2);
2472                         return False;
2473                 }
2474                 ZERO_STRUCTP(session_counter);
2475                 session_counter->snum=snum;
2476                 session_counter->counter=0;
2477                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
2478         }
2479         
2480         /* increment it */
2481         session_counter->counter++;
2482         
2483         /* JFM:
2484          * the global_counter should be stored in a TDB as it's common to all the clients
2485          * and should be zeroed on samba startup
2486          */
2487         global_counter=session_counter->counter;
2488         
2489         pstrcpy(chaine,ntprinter->info_2->printername);
2490
2491         init_unistr(&printer->printername, chaine);
2492         
2493         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", global_myname);
2494         init_unistr(&printer->servername, chaine);
2495         
2496         printer->cjobs = count;
2497         printer->total_jobs = 0;
2498         printer->total_bytes = 0;
2499
2500         setuptime = (time_t)ntprinter->info_2->setuptime;
2501         t=gmtime(&setuptime);
2502
2503         printer->year = t->tm_year+1900;
2504         printer->month = t->tm_mon+1;
2505         printer->dayofweek = t->tm_wday;
2506         printer->day = t->tm_mday;
2507         printer->hour = t->tm_hour;
2508         printer->minute = t->tm_min;
2509         printer->second = t->tm_sec;
2510         printer->milliseconds = 0;
2511
2512         printer->global_counter = global_counter;
2513         printer->total_pages = 0;
2514         printer->major_version = 0x0004;        /* NT 4 */
2515         printer->build_version = 0x0565;        /* build 1381 */
2516         printer->unknown7 = 0x1;
2517         printer->unknown8 = 0x0;
2518         printer->unknown9 = 0x0;
2519         printer->session_counter = session_counter->counter;
2520         printer->unknown11 = 0x0;
2521         printer->printer_errors = 0x0;          /* number of print failure */
2522         printer->unknown13 = 0x0;
2523         printer->unknown14 = 0x1;
2524         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
2525         printer->unknown16 =  0x0;
2526         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
2527         printer->unknown18 =  0x0;
2528         printer->status = nt_printq_status(status.status);
2529         printer->unknown20 =  0x0;
2530         printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
2531         printer->unknown22 = 0x0;
2532         printer->unknown23 = 0x6;               /* 6  ???*/
2533         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
2534         printer->unknown25 = 0;
2535         printer->unknown26 = 0;
2536         printer->unknown27 = 0;
2537         printer->unknown28 = 0;
2538         printer->unknown29 = 0;
2539         
2540         safe_free(queue);
2541         free_a_printer(&ntprinter,2);
2542         return (True);  
2543 }
2544
2545 /********************************************************************
2546  * construct_printer_info_1
2547  * fill a printer_info_1 struct
2548  ********************************************************************/
2549 static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
2550 {
2551         pstring chaine;
2552         pstring chaine2;
2553         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2554
2555         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
2556                 return False;
2557
2558         printer->flags=flags;
2559
2560         if (*ntprinter->info_2->comment == '\0') {
2561                 init_unistr(&printer->comment, lp_comment(snum));
2562                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2563                         ntprinter->info_2->drivername, lp_comment(snum));
2564         }
2565         else {
2566                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2567                 slprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",global_myname, ntprinter->info_2->printername,
2568                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
2569         }
2570                 
2571         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
2572
2573         init_unistr(&printer->description, chaine);
2574         init_unistr(&printer->name, chaine2);   
2575         
2576         free_a_printer(&ntprinter,2);
2577
2578         return True;
2579 }
2580
2581 /****************************************************************************
2582  Free a DEVMODE struct.
2583 ****************************************************************************/
2584
2585 static void free_dev_mode(DEVICEMODE *dev)
2586 {
2587         if (dev == NULL)
2588                 return;
2589
2590         if (dev->private)
2591                 safe_free(dev->private);
2592
2593         safe_free(dev); 
2594 }
2595
2596 /****************************************************************************
2597  Create a DEVMODE struct. Returns malloced memory.
2598 ****************************************************************************/
2599
2600 static DEVICEMODE *construct_dev_mode(int snum)
2601 {
2602         char adevice[32];
2603         char aform[32];
2604         NT_PRINTER_INFO_LEVEL *printer = NULL;
2605         NT_DEVICEMODE *ntdevmode = NULL;
2606         DEVICEMODE *devmode = NULL;
2607
2608         DEBUG(7,("construct_dev_mode\n"));
2609         
2610         DEBUGADD(8,("getting printer characteristics\n"));
2611
2612         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
2613                 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2614                 return NULL;
2615         }
2616
2617         ZERO_STRUCTP(devmode);  
2618
2619         if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2620                 goto fail;
2621
2622         if (printer->info_2->devmode)
2623                 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
2624
2625         if (ntdevmode == NULL)
2626                 goto fail;
2627
2628         DEBUGADD(8,("loading DEVICEMODE\n"));
2629
2630         slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
2631         init_unistr(&devmode->devicename, adevice);
2632
2633         slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
2634         init_unistr(&devmode->formname, aform);
2635
2636         devmode->specversion      = ntdevmode->specversion;
2637         devmode->driverversion    = ntdevmode->driverversion;
2638         devmode->size             = ntdevmode->size;
2639         devmode->driverextra      = ntdevmode->driverextra;
2640         devmode->fields           = ntdevmode->fields;
2641                                 
2642         devmode->orientation      = ntdevmode->orientation;     
2643         devmode->papersize        = ntdevmode->papersize;
2644         devmode->paperlength      = ntdevmode->paperlength;
2645         devmode->paperwidth       = ntdevmode->paperwidth;
2646         devmode->scale            = ntdevmode->scale;
2647         devmode->copies           = ntdevmode->copies;
2648         devmode->defaultsource    = ntdevmode->defaultsource;
2649         devmode->printquality     = ntdevmode->printquality;
2650         devmode->color            = ntdevmode->color;
2651         devmode->duplex           = ntdevmode->duplex;
2652         devmode->yresolution      = ntdevmode->yresolution;
2653         devmode->ttoption         = ntdevmode->ttoption;
2654         devmode->collate          = ntdevmode->collate;
2655         devmode->icmmethod        = ntdevmode->icmmethod;
2656         devmode->icmintent        = ntdevmode->icmintent;
2657         devmode->mediatype        = ntdevmode->mediatype;
2658         devmode->dithertype       = ntdevmode->dithertype;
2659
2660         if (ntdevmode->private != NULL) {
2661                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
2662                         goto fail;
2663         }
2664
2665         free_nt_devicemode(&ntdevmode);
2666         free_a_printer(&printer,2);
2667
2668         return devmode;
2669
2670   fail:
2671
2672         if (ntdevmode)
2673                 free_nt_devicemode(&ntdevmode);
2674         if (printer)
2675                 free_a_printer(&printer,2);
2676         free_dev_mode(devmode);
2677
2678         return NULL;
2679 }
2680
2681 /********************************************************************
2682  * construct_printer_info_2
2683  * fill a printer_info_2 struct
2684  ********************************************************************/
2685
2686 static BOOL construct_printer_info_2(PRINTER_INFO_2 *printer, int snum)
2687 {
2688         int count;
2689         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2690
2691         print_queue_struct *queue=NULL;
2692         print_status_struct status;
2693         memset(&status, 0, sizeof(status));     
2694
2695         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2696                 return False;
2697                 
2698         memset(&status, 0, sizeof(status));             
2699         count = print_queue_status(snum, &queue, &status);
2700
2701         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
2702         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
2703         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
2704         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
2705         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
2706
2707         if (*ntprinter->info_2->comment == '\0')
2708                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
2709         else
2710                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
2711
2712         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
2713         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
2714         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
2715         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
2716         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
2717
2718         printer->attributes = ntprinter->info_2->attributes;
2719
2720         printer->priority = ntprinter->info_2->priority;                                /* priority */  
2721         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
2722         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
2723         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
2724         printer->status = nt_printq_status(status.status);                      /* status */
2725         printer->cjobs = count;                                                 /* jobs */
2726         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
2727                         
2728         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
2729                 DEBUG(8, ("Returning NULL Devicemode!\n"));
2730         }
2731
2732         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2733                 /* steal the printer info sec_desc structure.  [badly done]. */
2734                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2735                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
2736                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
2737                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
2738         }
2739         else {
2740                 printer->secdesc = NULL;
2741         }
2742
2743         free_a_printer(&ntprinter, 2);
2744         safe_free(queue);
2745         return True;
2746 }
2747
2748 /********************************************************************
2749  * construct_printer_info_3
2750  * fill a printer_info_3 struct
2751  ********************************************************************/
2752 static BOOL construct_printer_info_3(PRINTER_INFO_3 **pp_printer, int snum)
2753 {
2754         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
2755         PRINTER_INFO_3 *printer = NULL;
2756
2757         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
2758                 return False;
2759
2760         *pp_printer = NULL;
2761         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
2762                 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2763                 return False;
2764         }
2765
2766         ZERO_STRUCTP(printer);
2767         
2768         printer->flags = 4; /* These are the components of the SD we are returning. */
2769         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2770                 /* steal the printer info sec_desc structure.  [badly done]. */
2771                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2772
2773 #if 0
2774                 /*
2775                  * Set the flags for the components we are returning.
2776                  */
2777
2778                 if (printer->secdesc->owner_sid)
2779                         printer->flags |= OWNER_SECURITY_INFORMATION;
2780
2781                 if (printer->secdesc->grp_sid)
2782                         printer->flags |= GROUP_SECURITY_INFORMATION;
2783
2784                 if (printer->secdesc->dacl)
2785                         printer->flags |= DACL_SECURITY_INFORMATION;
2786
2787                 if (printer->secdesc->sacl)
2788                         printer->flags |= SACL_SECURITY_INFORMATION;
2789 #endif
2790
2791                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2792                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2793                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2794         }
2795
2796         free_a_printer(&ntprinter, 2);
2797
2798         *pp_printer = printer;
2799         return True;
2800 }
2801
2802 /********************************************************************
2803  Spoolss_enumprinters.
2804 ********************************************************************/
2805 static BOOL enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2806 {
2807         int snum;
2808         int i;
2809         int n_services=lp_numservices();
2810         PRINTER_INFO_1 *printers=NULL;
2811         PRINTER_INFO_1 current_prt;
2812         
2813         DEBUG(4,("enum_all_printers_info_1\n"));        
2814
2815         for (snum=0; snum<n_services; snum++) {
2816                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2817                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2818                                 
2819                         if (construct_printer_info_1(flags, &current_prt, snum)) {
2820                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2821                                         *returned=0;
2822                                         return ERROR_NOT_ENOUGH_MEMORY;
2823                                 }
2824                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
2825                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
2826                                 (*returned)++;
2827                         }
2828                 }
2829         }
2830                 
2831         /* check the required size. */  
2832         for (i=0; i<*returned; i++)
2833                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
2834
2835         if (!alloc_buffer_size(buffer, *needed))
2836                 return ERROR_INSUFFICIENT_BUFFER;
2837
2838         /* fill the buffer with the structures */
2839         for (i=0; i<*returned; i++)
2840                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
2841
2842         /* clear memory */
2843         safe_free(printers);
2844
2845         if (*needed > offered) {
2846                 *returned=0;
2847                 return ERROR_INSUFFICIENT_BUFFER;
2848         }
2849         else
2850                 return NT_STATUS_NO_PROBLEMO;
2851 }
2852
2853 /********************************************************************
2854  enum_all_printers_info_1_local.
2855 *********************************************************************/
2856 static BOOL enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2857 {
2858         DEBUG(4,("enum_all_printers_info_1_local\n"));  
2859         
2860         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2861 }
2862
2863 /********************************************************************
2864  enum_all_printers_info_1_name.
2865 *********************************************************************/
2866 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2867 {
2868         fstring temp;
2869         DEBUG(4,("enum_all_printers_info_1_name\n"));   
2870         
2871         fstrcpy(temp, "\\\\");
2872         fstrcat(temp, global_myname);
2873
2874         if (strequal(name, temp)) {
2875                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2876         }
2877         else
2878                 return ERROR_INVALID_NAME;
2879 }
2880
2881 /********************************************************************
2882  enum_all_printers_info_1_remote.
2883 *********************************************************************/
2884 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2885 {
2886         PRINTER_INFO_1 *printer;
2887         fstring printername;
2888         fstring desc;
2889         fstring comment;
2890         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
2891
2892         /* JFM: currently it's more a place holder than anything else.
2893          * In the spooler world there is a notion of server registration.
2894          * the print servers are registring (sp ?) on the PDC (in the same domain)
2895          *
2896          * We should have a TDB here. The registration is done thru an undocumented RPC call.
2897          */
2898         
2899         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2900                 return ERROR_NOT_ENOUGH_MEMORY;
2901
2902         *returned=1;
2903         
2904         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);               
2905         slprintf(desc, sizeof(desc)-1,"%s", global_myname);
2906         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
2907
2908         init_unistr(&printer->description, desc);
2909         init_unistr(&printer->name, printername);       
2910         init_unistr(&printer->comment, comment);
2911         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2912                 
2913         /* check the required size. */  
2914         *needed += spoolss_size_printer_info_1(printer);
2915
2916         if (!alloc_buffer_size(buffer, *needed)) {
2917                 safe_free(printer);
2918                 return ERROR_INSUFFICIENT_BUFFER;
2919         }
2920
2921         /* fill the buffer with the structures */
2922         smb_io_printer_info_1("", buffer, printer, 0);  
2923
2924         /* clear memory */
2925         safe_free(printer);
2926
2927         if (*needed > offered) {
2928                 *returned=0;
2929                 return ERROR_INSUFFICIENT_BUFFER;
2930         }
2931         else
2932                 return NT_STATUS_NO_PROBLEMO;
2933 }
2934
2935 /********************************************************************
2936  enum_all_printers_info_1_network.
2937 *********************************************************************/
2938
2939 static BOOL enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2940 {
2941         DEBUG(4,("enum_all_printers_info_1_network\n"));        
2942         
2943         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2944 }
2945
2946 /********************************************************************
2947  * api_spoolss_enumprinters
2948  *
2949  * called from api_spoolss_enumprinters (see this to understand)
2950  ********************************************************************/
2951
2952 static BOOL enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2953 {
2954         int snum;
2955         int i;
2956         int n_services=lp_numservices();
2957         PRINTER_INFO_2 *printers=NULL;
2958         PRINTER_INFO_2 current_prt;
2959
2960         for (snum=0; snum<n_services; snum++) {
2961                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2962                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2963                                 
2964                         if (construct_printer_info_2(&current_prt, snum)) {
2965                                 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2966                                         return ERROR_NOT_ENOUGH_MEMORY;
2967                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
2968                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
2969                                 (*returned)++;
2970                         }
2971                 }
2972         }
2973         
2974         /* check the required size. */  
2975         for (i=0; i<*returned; i++)
2976                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2977
2978         if (!alloc_buffer_size(buffer, *needed)) {
2979                 for (i=0; i<*returned; i++) {
2980                         free_devmode(printers[i].devmode);
2981                 }
2982                 safe_free(printers);
2983                 return ERROR_INSUFFICIENT_BUFFER;
2984         }
2985
2986         /* fill the buffer with the structures */
2987         for (i=0; i<*returned; i++)
2988                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
2989         
2990         /* clear memory */
2991         for (i=0; i<*returned; i++) {
2992                 free_devmode(printers[i].devmode);
2993         }
2994         safe_free(printers);
2995
2996         if (*needed > offered) {
2997                 *returned=0;
2998                 return ERROR_INSUFFICIENT_BUFFER;
2999         }
3000         else
3001                 return NT_STATUS_NO_PROBLEMO;
3002 }
3003
3004 /********************************************************************
3005  * handle enumeration of printers at level 1
3006  ********************************************************************/
3007 static uint32 enumprinters_level1( uint32 flags, fstring name,
3008                                  NEW_BUFFER *buffer, uint32 offered,
3009                                  uint32 *needed, uint32 *returned)
3010 {
3011         /* Not all the flags are equals */
3012
3013         if (flags & PRINTER_ENUM_LOCAL)
3014                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
3015
3016         if (flags & PRINTER_ENUM_NAME)
3017                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
3018
3019         if (flags & PRINTER_ENUM_REMOTE)
3020                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
3021
3022         if (flags & PRINTER_ENUM_NETWORK)
3023                 return enum_all_printers_info_1_network(buffer, offered, needed, returned);
3024
3025         return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
3026 }
3027
3028 /********************************************************************
3029  * handle enumeration of printers at level 2
3030  ********************************************************************/
3031 static uint32 enumprinters_level2( uint32 flags, fstring servername,
3032                                  NEW_BUFFER *buffer, uint32 offered,
3033                                  uint32 *needed, uint32 *returned)
3034 {
3035         fstring temp;
3036         
3037         fstrcpy(temp, "\\\\");
3038         fstrcat(temp, global_myname);
3039
3040         if (flags & PRINTER_ENUM_LOCAL) {
3041                 if (strequal(servername, temp))
3042                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3043                 else
3044                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3045         }
3046
3047         if (flags & PRINTER_ENUM_NAME) {
3048                 if (strequal(servername, temp))
3049                         return enum_all_printers_info_2(buffer, offered, needed, returned);
3050                 else
3051                         return ERROR_INVALID_NAME;
3052         }
3053
3054         if (flags & PRINTER_ENUM_REMOTE)
3055                 return ERROR_INVALID_LEVEL;
3056
3057         return NT_STATUS_NO_PROBLEMO;
3058 }
3059
3060 /********************************************************************
3061  * handle enumeration of printers at level 5
3062  ********************************************************************/
3063 static uint32 enumprinters_level5( uint32 flags, fstring servername,
3064                                  NEW_BUFFER *buffer, uint32 offered,
3065                                  uint32 *needed, uint32 *returned)
3066 {
3067 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3068         return NT_STATUS_NO_PROBLEMO;
3069 }
3070
3071 /********************************************************************
3072  * api_spoolss_enumprinters
3073  *
3074  * called from api_spoolss_enumprinters (see this to understand)
3075  ********************************************************************/
3076
3077 uint32 _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
3078 {
3079         uint32 flags = q_u->flags;
3080         UNISTR2 *servername = &q_u->servername;
3081         uint32 level = q_u->level;
3082         NEW_BUFFER *buffer = NULL;
3083         uint32 offered = q_u->offered;
3084         uint32 *needed = &r_u->needed;
3085         uint32 *returned = &r_u->returned;
3086
3087         fstring name;
3088         
3089         /* that's an [in out] buffer */
3090         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3091         buffer = r_u->buffer;
3092
3093         DEBUG(4,("_spoolss_enumprinters\n"));
3094
3095         *needed=0;
3096         *returned=0;
3097         
3098         /*
3099          * Level 1:
3100          *          flags==PRINTER_ENUM_NAME
3101          *           if name=="" then enumerates all printers
3102          *           if name!="" then enumerate the printer
3103          *          flags==PRINTER_ENUM_REMOTE
3104          *          name is NULL, enumerate printers
3105          * Level 2: name!="" enumerates printers, name can't be NULL
3106          * Level 3: doesn't exist
3107          * Level 4: does a local registry lookup
3108          * Level 5: same as Level 2
3109          */
3110
3111         unistr2_to_ascii(name, servername, sizeof(name)-1);
3112         strupper(name);
3113
3114         switch (level) {
3115         case 1:
3116                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
3117         case 2:
3118                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
3119         case 5:
3120                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
3121         case 3:
3122         case 4:
3123         default:
3124                 return ERROR_INVALID_LEVEL;
3125         }
3126 }
3127
3128 /****************************************************************************
3129 ****************************************************************************/
3130 static uint32 getprinter_level_0(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3131 {
3132         PRINTER_INFO_0 *printer=NULL;
3133
3134         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
3135                 return ERROR_NOT_ENOUGH_MEMORY;
3136
3137         construct_printer_info_0(printer, snum);
3138         
3139         /* check the required size. */  
3140         *needed += spoolss_size_printer_info_0(printer);
3141
3142         if (!alloc_buffer_size(buffer, *needed)) {
3143                 safe_free(printer);
3144                 return ERROR_INSUFFICIENT_BUFFER;
3145         }
3146
3147         /* fill the buffer with the structures */
3148         smb_io_printer_info_0("", buffer, printer, 0);  
3149         
3150         /* clear memory */
3151         safe_free(printer);
3152
3153         if (*needed > offered) {
3154                 return ERROR_INSUFFICIENT_BUFFER;
3155         }
3156         else
3157                 return NT_STATUS_NO_PROBLEMO;   
3158 }
3159
3160 /****************************************************************************
3161 ****************************************************************************/
3162 static uint32 getprinter_level_1(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3163 {
3164         PRINTER_INFO_1 *printer=NULL;
3165
3166         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
3167                 return ERROR_NOT_ENOUGH_MEMORY;
3168
3169         construct_printer_info_1(PRINTER_ENUM_ICON8, printer, snum);
3170         
3171         /* check the required size. */  
3172         *needed += spoolss_size_printer_info_1(printer);
3173
3174         if (!alloc_buffer_size(buffer, *needed)) {
3175                 safe_free(printer);
3176                 return ERROR_INSUFFICIENT_BUFFER;
3177         }
3178
3179         /* fill the buffer with the structures */
3180         smb_io_printer_info_1("", buffer, printer, 0);  
3181         
3182         /* clear memory */
3183         safe_free(printer);
3184
3185         if (*needed > offered) {
3186                 return ERROR_INSUFFICIENT_BUFFER;
3187         }
3188         else
3189                 return NT_STATUS_NO_PROBLEMO;   
3190 }
3191
3192 /****************************************************************************
3193 ****************************************************************************/
3194 static uint32 getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3195 {
3196         PRINTER_INFO_2 *printer=NULL;
3197
3198         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
3199                 return ERROR_NOT_ENOUGH_MEMORY;
3200         
3201         construct_printer_info_2(printer, snum);
3202         
3203         /* check the required size. */  
3204         *needed += spoolss_size_printer_info_2(printer);
3205
3206         if (!alloc_buffer_size(buffer, *needed)) {
3207                 free_printer_info_2(printer);
3208                 return ERROR_INSUFFICIENT_BUFFER;
3209         }
3210
3211         /* fill the buffer with the structures */
3212         if (!smb_io_printer_info_2("", buffer, printer, 0)) {
3213                 free_printer_info_2(printer);
3214                 return ERROR_NOT_ENOUGH_MEMORY;
3215         }
3216         
3217         /* clear memory */
3218         free_printer_info_2(printer);
3219
3220         if (*needed > offered) {
3221                 return ERROR_INSUFFICIENT_BUFFER;
3222         }
3223         else
3224                 return NT_STATUS_NO_PROBLEMO;   
3225 }
3226
3227 /****************************************************************************
3228 ****************************************************************************/
3229 static uint32 getprinter_level_3(int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3230 {
3231         PRINTER_INFO_3 *printer=NULL;
3232
3233         if (!construct_printer_info_3(&printer, snum))
3234                 return ERROR_NOT_ENOUGH_MEMORY;
3235         
3236         /* check the required size. */  
3237         *needed += spoolss_size_printer_info_3(printer);
3238
3239         if (!alloc_buffer_size(buffer, *needed)) {
3240                 free_printer_info_3(printer);
3241                 return ERROR_INSUFFICIENT_BUFFER;
3242         }
3243
3244         /* fill the buffer with the structures */
3245         smb_io_printer_info_3("", buffer, printer, 0);  
3246         
3247         /* clear memory */
3248         free_printer_info_3(printer);
3249         
3250         if (*needed > offered) {
3251                 return ERROR_INSUFFICIENT_BUFFER;
3252         }
3253         else
3254                 return NT_STATUS_NO_PROBLEMO;   
3255 }
3256
3257 /****************************************************************************
3258 ****************************************************************************/
3259
3260 uint32 _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
3261 {
3262         POLICY_HND *handle = &q_u->handle;
3263         uint32 level = q_u->level;
3264         NEW_BUFFER *buffer = NULL;
3265         uint32 offered = q_u->offered;
3266         uint32 *needed = &r_u->needed;
3267
3268         int snum;
3269
3270         /* that's an [in out] buffer */
3271         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3272         buffer = r_u->buffer;
3273
3274         *needed=0;
3275
3276         if (!get_printer_snum(p, handle, &snum))
3277                 return ERROR_INVALID_HANDLE;
3278
3279         switch (level) {
3280         case 0:
3281                 return getprinter_level_0(snum, buffer, offered, needed);
3282         case 1:
3283                 return getprinter_level_1(snum, buffer, offered, needed);
3284         case 2:         
3285                 return getprinter_level_2(snum, buffer, offered, needed);
3286         case 3:         
3287                 return getprinter_level_3(snum, buffer, offered, needed);
3288         default:
3289                 return ERROR_INVALID_LEVEL;
3290         }
3291 }       
3292                 
3293 /********************************************************************
3294  * fill a DRIVER_INFO_1 struct
3295  ********************************************************************/
3296 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
3297 {
3298         init_unistr( &info->name, driver.info_3->name);
3299 }
3300
3301 /********************************************************************
3302  * construct_printer_driver_info_1
3303  ********************************************************************/
3304 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
3305 {       
3306         NT_PRINTER_INFO_LEVEL *printer = NULL;
3307         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3308
3309         ZERO_STRUCT(driver);
3310
3311         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3312                 return ERROR_INVALID_PRINTER_NAME;
3313
3314         if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3315                 return ERROR_UNKNOWN_PRINTER_DRIVER;
3316
3317         fill_printer_driver_info_1(info, driver, servername, architecture);
3318
3319         free_a_printer(&printer,2);
3320
3321         return NT_STATUS_NO_PROBLEMO;
3322 }
3323
3324 /********************************************************************
3325  * construct_printer_driver_info_2
3326  * fill a printer_info_2 struct
3327  ********************************************************************/
3328 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3329 {
3330         pstring temp;
3331
3332         info->version=driver.info_3->cversion;
3333
3334         init_unistr( &info->name, driver.info_3->name );
3335         init_unistr( &info->architecture, driver.info_3->environment );
3336
3337
3338     if (strlen(driver.info_3->driverpath)) {
3339                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
3340                 init_unistr( &info->driverpath, temp );
3341     } else
3342         init_unistr( &info->driverpath, "" );
3343
3344         if (strlen(driver.info_3->datafile)) {
3345                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3346                 init_unistr( &info->datafile, temp );
3347         } else
3348                 init_unistr( &info->datafile, "" );
3349         
3350         if (strlen(driver.info_3->configfile)) {
3351                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3352                 init_unistr( &info->configfile, temp ); 
3353         } else
3354                 init_unistr( &info->configfile, "" );
3355 }
3356
3357 /********************************************************************
3358  * construct_printer_driver_info_2
3359  * fill a printer_info_2 struct
3360  ********************************************************************/
3361 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
3362 {
3363         NT_PRINTER_INFO_LEVEL *printer = NULL;
3364         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3365
3366         ZERO_STRUCT(printer);
3367         ZERO_STRUCT(driver);
3368
3369         if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
3370                 return ERROR_INVALID_PRINTER_NAME;
3371
3372         if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
3373                 return ERROR_UNKNOWN_PRINTER_DRIVER;
3374
3375         fill_printer_driver_info_2(info, driver, servername);
3376
3377         free_a_printer(&printer,2);
3378
3379         return NT_STATUS_NO_PROBLEMO;
3380 }
3381
3382 /********************************************************************
3383  * copy a strings array and convert to UNICODE
3384  *
3385  * convert an array of ascii string to a UNICODE string
3386  ********************************************************************/
3387 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
3388 {
3389         int i=0;
3390         int j=0;
3391         char *v;
3392         pstring line;
3393
3394         DEBUG(6,("init_unistr_array\n"));
3395         *uni_array=NULL;
3396
3397         while (1) {
3398                 if (char_array == NULL)
3399                         v = "";
3400                 else {
3401                         v = char_array[i];
3402                         if (!v) v = ""; /* hack to handle null lists */
3403                 }
3404                 if (strlen(v) == 0) break;
3405                 slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
3406                 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
3407                 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
3408                         DEBUG(0,("init_unistr_array: Realloc error\n" ));
3409                         return;
3410                 }
3411                 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
3412                 i++;
3413         }
3414         
3415         if (*uni_array) {
3416                 (*uni_array)[j]=0x0000;
3417         }
3418         
3419         DEBUGADD(6,("last one:done\n"));
3420 }
3421
3422 /********************************************************************
3423  * construct_printer_info_3
3424  * fill a printer_info_3 struct
3425  ********************************************************************/
3426 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3427 {
3428         pstring temp;
3429
3430         ZERO_STRUCTP(info);
3431
3432         info->version=driver.info_3->cversion;
3433
3434         init_unistr( &info->name, driver.info_3->name );        
3435         init_unistr( &info->architecture, driver.info_3->environment );
3436
3437     if (strlen(driver.info_3->driverpath)) {
3438         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3439         init_unistr( &info->driverpath, temp );
3440     } else
3441         init_unistr( &info->driverpath, "" );
3442     
3443     if (strlen(driver.info_3->datafile)) {
3444         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3445         init_unistr( &info->datafile, temp );
3446     } else
3447         init_unistr( &info->datafile, "" );
3448
3449     if (strlen(driver.info_3->configfile)) {
3450         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3451         init_unistr( &info->configfile, temp ); 
3452     } else
3453         init_unistr( &info->configfile, "" );
3454
3455     if (strlen(driver.info_3->helpfile)) {
3456         slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3457         init_unistr( &info->helpfile, temp );
3458     } else
3459         init_unistr( &info->helpfile, "" );
3460
3461         init_unistr( &info->monitorname, driver.info_3->monitorname );
3462         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3463
3464         info->dependentfiles=NULL;
3465         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3466 }
3467
3468 /********************************************************************
3469  * construct_printer_info_3
3470  * fill a printer_info_3 struct
3471  ********************************************************************/
3472 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
3473 {       
3474         NT_PRINTER_INFO_LEVEL *printer = NULL;
3475         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3476         uint32 status=0;
3477         ZERO_STRUCT(driver);
3478
3479         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3480         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3481         if (status != 0)
3482                 return ERROR_INVALID_PRINTER_NAME;
3483
3484         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3485         DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
3486         if (status != 0) {
3487                 free_a_printer(&printer,2);
3488                 return ERROR_UNKNOWN_PRINTER_DRIVER;
3489         }
3490
3491         fill_printer_driver_info_3(info, driver, servername);
3492
3493         free_a_printer(&printer,2);
3494
3495         return NT_STATUS_NO_PROBLEMO;
3496 }
3497
3498 /********************************************************************
3499  * construct_printer_info_6
3500  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3501  ********************************************************************/
3502
3503 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
3504 {
3505         pstring temp;
3506         fstring nullstr;
3507
3508         ZERO_STRUCTP(info);
3509         memset(&nullstr, '\0', sizeof(fstring));
3510
3511         info->version=driver.info_3->cversion;
3512
3513         init_unistr( &info->name, driver.info_3->name );        
3514         init_unistr( &info->architecture, driver.info_3->environment );
3515
3516         if (strlen(driver.info_3->driverpath)) {
3517                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
3518                 init_unistr( &info->driverpath, temp );
3519         } else
3520                 init_unistr( &info->driverpath, "" );
3521
3522         if (strlen(driver.info_3->datafile)) {
3523                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
3524                 init_unistr( &info->datafile, temp );
3525         } else
3526                 init_unistr( &info->datafile, "" );
3527
3528         if (strlen(driver.info_3->configfile)) {
3529                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
3530                 init_unistr( &info->configfile, temp ); 
3531         } else
3532                 init_unistr( &info->configfile, "" );
3533
3534         if (strlen(driver.info_3->helpfile)) {
3535                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
3536                 init_unistr( &info->helpfile, temp );
3537         } else
3538                 init_unistr( &info->helpfile, "" );
3539         
3540         init_unistr( &info->monitorname, driver.info_3->monitorname );
3541         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
3542
3543         info->dependentfiles=NULL;
3544         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
3545
3546         info->previousdrivernames=NULL;
3547         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
3548
3549         info->driver_date.low=0;
3550         info->driver_date.high=0;
3551
3552         info->padding=0;
3553         info->driver_version_low=0;
3554         info->driver_version_high=0;
3555
3556         init_unistr( &info->mfgname, "");
3557         init_unistr( &info->oem_url, "");
3558         init_unistr( &info->hardware_id, "");
3559         init_unistr( &info->provider, "");
3560 }
3561
3562 /********************************************************************
3563  * construct_printer_info_6
3564  * fill a printer_info_6 struct
3565  ********************************************************************/
3566 static uint32 construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
3567 {       
3568         NT_PRINTER_INFO_LEVEL *printer = NULL;
3569         NT_PRINTER_DRIVER_INFO_LEVEL driver;
3570         uint32 status=0;
3571         ZERO_STRUCT(driver);
3572
3573         status=get_a_printer(&printer, 2, lp_servicename(snum) );
3574         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3575         if (status != 0)
3576                 return ERROR_INVALID_PRINTER_NAME;
3577
3578         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3579         DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3580         if (status != 0) {
3581                 /*
3582                  * Is this a W2k client ?
3583                  */
3584
3585                 if (version < 3) {
3586                         free_a_printer(&printer,2);
3587                         return ERROR_UNKNOWN_PRINTER_DRIVER;
3588                 }
3589
3590                 /* Yes - try again with a WinNT driver. */
3591                 version = 2;
3592                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
3593                 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status));
3594                 if (status != 0) {
3595                         free_a_printer(&printer,2);
3596                         return ERROR_UNKNOWN_PRINTER_DRIVER;
3597                 }
3598         }
3599
3600         fill_printer_driver_info_6(info, driver, servername);
3601
3602         free_a_printer(&printer,2);
3603
3604         return NT_STATUS_NO_PROBLEMO;
3605 }
3606
3607 /****************************************************************************
3608 ****************************************************************************/
3609
3610 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
3611 {
3612         safe_free(info->dependentfiles);
3613 }
3614
3615 /****************************************************************************
3616 ****************************************************************************/
3617
3618 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
3619 {
3620         safe_free(info->dependentfiles);
3621         
3622 }
3623
3624 /****************************************************************************
3625 ****************************************************************************/
3626 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3627 {
3628         DRIVER_INFO_1 *info=NULL;
3629         uint32 status;
3630         
3631         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
3632                 return ERROR_NOT_ENOUGH_MEMORY;
3633         
3634         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
3635         if (status != NT_STATUS_NO_PROBLEMO) {
3636                 safe_free(info);
3637                 return status;
3638         }
3639
3640         /* check the required size. */  
3641         *needed += spoolss_size_printer_driver_info_1(info);
3642
3643         if (!alloc_buffer_size(buffer, *needed)) {
3644                 safe_free(info);
3645                 return ERROR_INSUFFICIENT_BUFFER;
3646         }
3647
3648         /* fill the buffer with the structures */
3649         smb_io_printer_driver_info_1("", buffer, info, 0);      
3650
3651         /* clear memory */
3652         safe_free(info);
3653
3654         if (*needed > offered)
3655                 return ERROR_INSUFFICIENT_BUFFER;
3656         else
3657                 return NT_STATUS_NO_PROBLEMO;
3658 }
3659
3660 /****************************************************************************
3661 ****************************************************************************/
3662 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3663 {
3664         DRIVER_INFO_2 *info=NULL;
3665         uint32 status;
3666         
3667         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
3668                 return ERROR_NOT_ENOUGH_MEMORY;
3669         
3670         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
3671         if (status != NT_STATUS_NO_PROBLEMO) {
3672                 safe_free(info);
3673                 return status;
3674         }
3675
3676         /* check the required size. */  
3677         *needed += spoolss_size_printer_driver_info_2(info);
3678
3679         if (!alloc_buffer_size(buffer, *needed)) {
3680                 safe_free(info);
3681                 return ERROR_INSUFFICIENT_BUFFER;
3682         }
3683
3684         /* fill the buffer with the structures */
3685         smb_io_printer_driver_info_2("", buffer, info, 0);      
3686
3687         /* clear memory */
3688         safe_free(info);
3689
3690         if (*needed > offered)
3691                 return ERROR_INSUFFICIENT_BUFFER;
3692         else
3693                 return NT_STATUS_NO_PROBLEMO;
3694 }
3695
3696 /****************************************************************************
3697 ****************************************************************************/
3698 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3699 {
3700         DRIVER_INFO_3 info;
3701         uint32 status;
3702
3703         ZERO_STRUCT(info);
3704
3705         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
3706         if (status != NT_STATUS_NO_PROBLEMO) {
3707                 return status;
3708         }
3709
3710         /* check the required size. */  
3711         *needed += spoolss_size_printer_driver_info_3(&info);
3712
3713         if (!alloc_buffer_size(buffer, *needed)) {
3714                 free_printer_driver_info_3(&info);
3715                 return ERROR_INSUFFICIENT_BUFFER;
3716         }
3717
3718         /* fill the buffer with the structures */
3719         smb_io_printer_driver_info_3("", buffer, &info, 0);
3720
3721         free_printer_driver_info_3(&info);
3722
3723         if (*needed > offered)
3724                 return ERROR_INSUFFICIENT_BUFFER;
3725         else
3726                 return NT_STATUS_NO_PROBLEMO;
3727 }
3728
3729 /****************************************************************************
3730 ****************************************************************************/
3731 static uint32 getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
3732 {
3733         DRIVER_INFO_6 info;
3734         uint32 status;
3735
3736         ZERO_STRUCT(info);
3737
3738         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
3739         if (status != NT_STATUS_NO_PROBLEMO) {
3740                 return status;
3741         }
3742
3743         /* check the required size. */  
3744         *needed += spoolss_size_printer_driver_info_6(&info);
3745
3746         if (!alloc_buffer_size(buffer, *needed)) {
3747                 free_printer_driver_info_6(&info);
3748                 return ERROR_INSUFFICIENT_BUFFER;
3749         }
3750
3751         /* fill the buffer with the structures */
3752         smb_io_printer_driver_info_6("", buffer, &info, 0);
3753
3754         free_printer_driver_info_6(&info);
3755
3756         if (*needed > offered)
3757                 return ERROR_INSUFFICIENT_BUFFER;
3758         else
3759                 return NT_STATUS_NO_PROBLEMO;
3760 }
3761
3762 /****************************************************************************
3763 ****************************************************************************/
3764
3765 uint32 _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
3766 {
3767         POLICY_HND *handle = &q_u->handle;
3768         UNISTR2 *uni_arch = &q_u->architecture;
3769         uint32 level = q_u->level;
3770         uint32 clientmajorversion = q_u->clientmajorversion;
3771 /*      uint32 clientminorversion = q_u->clientminorversion; - notused. */
3772         NEW_BUFFER *buffer = NULL;
3773         uint32 offered = q_u->offered;
3774         uint32 *needed = &r_u->needed;
3775         uint32 *servermajorversion = &r_u->servermajorversion;
3776         uint32 *serverminorversion = &r_u->serverminorversion;
3777
3778         fstring servername;
3779         fstring architecture;
3780         int snum;
3781
3782         /* that's an [in out] buffer */
3783         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
3784         buffer = r_u->buffer;
3785
3786         DEBUG(4,("_spoolss_getprinterdriver2\n"));
3787
3788         *needed=0;
3789         *servermajorversion=0;
3790         *serverminorversion=0;
3791
3792         pstrcpy(servername, global_myname);
3793         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
3794
3795         if (!get_printer_snum(p, handle, &snum))
3796                 return ERROR_INVALID_HANDLE;
3797
3798         switch (level) {
3799         case 1:
3800                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3801         case 2:
3802                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3803         case 3:
3804                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3805         case 6:
3806                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
3807         default:
3808                 return ERROR_INVALID_LEVEL;
3809         }
3810 }
3811
3812 /****************************************************************************
3813 ****************************************************************************/
3814
3815 uint32 _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
3816 {
3817         POLICY_HND *handle = &q_u->handle;
3818
3819         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3820
3821         if (Printer) {
3822                 Printer->page_started=True;
3823                 return 0x0;
3824         }
3825
3826         DEBUG(3,("Error in startpageprinter printer handle\n"));
3827         return ERROR_INVALID_HANDLE;
3828 }
3829
3830 /****************************************************************************
3831 ****************************************************************************/
3832
3833 uint32 _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
3834 {
3835         POLICY_HND *handle = &q_u->handle;
3836
3837         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3838
3839         if (!Printer) {
3840                 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
3841                 return ERROR_INVALID_HANDLE;
3842         }
3843         
3844         Printer->page_started=False;
3845
3846         return NT_STATUS_NO_PROBLEMO;
3847 }
3848
3849 /********************************************************************
3850  * api_spoolss_getprinter
3851  * called from the spoolss dispatcher
3852  *
3853  ********************************************************************/
3854
3855 uint32 _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
3856 {
3857         POLICY_HND *handle = &q_u->handle;
3858 /*      uint32 level = q_u->doc_info_container.level; - notused. */
3859         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
3860         uint32 *jobid = &r_u->jobid;
3861
3862         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
3863         int snum;
3864         pstring jobname;
3865         fstring datatype;
3866         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3867         struct current_user user;
3868
3869         if (!Printer) {
3870                 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3871                 return ERROR_INVALID_HANDLE;
3872         }
3873
3874         get_current_user(&user, p);
3875
3876         /*
3877          * a nice thing with NT is it doesn't listen to what you tell it.
3878          * when asked to send _only_ RAW datas, it tries to send datas
3879          * in EMF format.
3880          *
3881          * So I add checks like in NT Server ...
3882          *
3883          * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
3884          * there's a bug in NT client-side code, so we'll fix it in the
3885          * server-side code. *nnnnnggggh!*
3886          */
3887         
3888         if (info_1->p_datatype != 0) {
3889                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
3890                 if (strcmp(datatype, "RAW") != 0) {
3891                         (*jobid)=0;
3892                         return ERROR_INVALID_DATATYPE;
3893                 }               
3894         }               
3895         
3896         /* get the share number of the printer */
3897         if (!get_printer_snum(p, handle, &snum)) {
3898                 return ERROR_INVALID_HANDLE;
3899         }
3900
3901         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
3902         
3903         Printer->jobid = print_job_start(&user, snum, jobname);
3904
3905         /* An error occured in print_job_start() so return an appropriate
3906            NT error code. */
3907
3908         if (Printer->jobid == -1) {
3909                 return map_nt_error_from_unix(errno);
3910         }
3911         
3912         Printer->document_started=True;
3913         (*jobid) = Printer->jobid;
3914
3915         return 0x0;
3916 }
3917
3918 /********************************************************************
3919  * api_spoolss_getprinter
3920  * called from the spoolss dispatcher
3921  *
3922  ********************************************************************/
3923
3924 uint32 _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
3925 {
3926         POLICY_HND *handle = &q_u->handle;
3927
3928         return _spoolss_enddocprinter_internal(p, handle);
3929 }
3930
3931 /****************************************************************************
3932 ****************************************************************************/
3933
3934 uint32 _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
3935 {
3936         POLICY_HND *handle = &q_u->handle;
3937         uint32 buffer_size = q_u->buffer_size;
3938         uint8 *buffer = q_u->buffer;
3939         uint32 *buffer_written = &q_u->buffer_size2;
3940
3941         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3942         
3943         if (!Printer) {
3944                 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
3945                 r_u->buffer_written = q_u->buffer_size2;
3946                 return ERROR_INVALID_HANDLE;
3947         }
3948
3949         (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
3950
3951
3952         r_u->buffer_written = q_u->buffer_size2;
3953
3954         return 0x0;
3955 }
3956
3957 /********************************************************************
3958  * api_spoolss_getprinter
3959  * called from the spoolss dispatcher
3960  *
3961  ********************************************************************/
3962 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3963                               pipes_struct *p)
3964 {
3965         struct current_user user;
3966         int snum, errcode = ERROR_INVALID_FUNCTION;
3967         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
3968
3969         get_current_user(&user, p);
3970
3971         if (!Printer) {
3972                 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3973                 return ERROR_INVALID_HANDLE;
3974         }
3975
3976         if (!get_printer_snum(p, handle, &snum))
3977                 return ERROR_INVALID_HANDLE;
3978
3979         switch (command) {
3980         case PRINTER_CONTROL_PAUSE:
3981                 if (print_queue_pause(&user, snum, &errcode)) {
3982                         errcode = 0;
3983                 }
3984                 break;
3985         case PRINTER_CONTROL_RESUME:
3986         case PRINTER_CONTROL_UNPAUSE:
3987                 if (print_queue_resume(&user, snum, &errcode)) {
3988                         errcode = 0;
3989                 }
3990                 break;
3991         case PRINTER_CONTROL_PURGE:
3992                 if (print_queue_purge(&user, snum, &errcode)) {
3993                         errcode = 0;
3994                 }
3995                 break;
3996         default:
3997                 return ERROR_INVALID_LEVEL;
3998         }
3999
4000         return errcode;
4001 }
4002
4003 /********************************************************************
4004  * api_spoolss_abortprinter
4005  ********************************************************************/
4006
4007 uint32 _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
4008 {
4009         POLICY_HND *handle = &q_u->handle;
4010
4011         return control_printer(handle, PRINTER_CONTROL_PURGE, p);
4012 }
4013
4014 /********************************************************************
4015  * called by spoolss_api_setprinter
4016  * when updating a printer description
4017  ********************************************************************/
4018 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
4019                                  const SPOOL_PRINTER_INFO_LEVEL *info,
4020                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
4021 {
4022         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
4023         struct current_user user;
4024         uint32 result;
4025         int snum;
4026
4027         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4028
4029         if (!Printer || !get_printer_snum(p, handle, &snum)) {
4030                 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4031                          OUR_HANDLE(handle)));
4032
4033                 result = ERROR_INVALID_HANDLE;
4034                 goto done;
4035         }
4036
4037         /* NT seems to like setting the security descriptor even though
4038            nothing may have actually changed.  This causes annoying
4039            dialog boxes when the user doesn't have permission to change
4040            the security descriptor. */
4041
4042         nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
4043
4044         if (DEBUGLEVEL >= 10) {
4045                 SEC_ACL *acl;
4046                 int i;
4047
4048                 acl = old_secdesc_ctr->sec->dacl;
4049                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
4050                            PRINTERNAME(snum), acl->num_aces));
4051
4052                 for (i = 0; i < acl->num_aces; i++) {
4053                         fstring sid_str;
4054
4055                         sid_to_string(sid_str, &acl->ace[i].sid);
4056
4057                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
4058                                   acl->ace[i].info.mask));
4059                 }
4060
4061                 acl = secdesc_ctr->sec->dacl;
4062
4063                 if (acl) {
4064                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
4065                                    PRINTERNAME(snum), acl->num_aces));
4066
4067                         for (i = 0; i < acl->num_aces; i++) {
4068                                 fstring sid_str;
4069                                 
4070                                 sid_to_string(sid_str, &acl->ace[i].sid);
4071                                 
4072                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
4073                                            acl->ace[i].info.mask));
4074                         }
4075                 } else {
4076                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4077                 }
4078         }
4079
4080         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
4081
4082         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
4083                 result = NT_STATUS_NO_PROBLEMO;
4084                 goto done;
4085         }
4086
4087         /* Work out which user is performing the operation */
4088
4089         get_current_user(&user, p);
4090
4091         /* Check the user has permissions to change the security
4092            descriptor.  By experimentation with two NT machines, the user
4093            requires Full Access to the printer to change security
4094            information. */
4095
4096         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
4097                 result = ERROR_ACCESS_DENIED;
4098                 goto done;
4099         }
4100
4101         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
4102
4103  done:
4104
4105         return result;
4106 }
4107
4108 /********************************************************************
4109  Do Samba sanity checks on a printer info struct.
4110  this has changed purpose: it now "canonicalises" printer
4111  info from a client rather than just checking it is correct
4112  ********************************************************************/
4113
4114 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
4115 {
4116         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4117                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
4118
4119         /* we force some elements to "correct" values */
4120         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname);
4121         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
4122                  global_myname, lp_servicename(snum));
4123         fstrcpy(info->sharename, lp_servicename(snum));
4124         info->attributes = PRINTER_ATTRIBUTE_SHARED   \
4125                 | PRINTER_ATTRIBUTE_LOCAL  \
4126                 | PRINTER_ATTRIBUTE_RAW_ONLY \
4127                 | PRINTER_ATTRIBUTE_QUEUED ;
4128         
4129         return True;
4130 }
4131
4132 /****************************************************************************
4133 ****************************************************************************/
4134 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
4135 {
4136         pid_t local_pid = sys_getpid();
4137         char *cmd = lp_addprinter_cmd();
4138         char *path;
4139         char **qlines;
4140         pstring tmp_file;
4141         pstring command;
4142         pstring driverlocation;
4143         int numlines;
4144         int ret;
4145
4146         if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4147                 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4148         else
4149                 path = tmpdir();
4150
4151         /* build driver path... only 9X architecture is needed for legacy reasons */
4152         slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
4153                         global_myname);
4154         /* change \ to \\ for the shell */
4155         all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
4156         
4157         slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
4158         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4159                         cmd, printer->info_2->printername, printer->info_2->sharename,
4160                         printer->info_2->portname, printer->info_2->drivername,
4161                         printer->info_2->location, driverlocation);
4162
4163         unlink(tmp_file);
4164
4165     /* Convert script args to unix-codepage */
4166     dos_to_unix(command, True);
4167         DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4168         ret = smbrun(command, tmp_file, False);
4169         DEBUGADD(10,("returned [%d]\n", ret));
4170
4171         if ( ret != 0 ) {
4172                 unlink(tmp_file);
4173                 return False;
4174         }
4175
4176         numlines = 0;
4177     /* Get lines and convert them back to dos-codepage */
4178         qlines = file_lines_load(tmp_file, &numlines, True);
4179         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4180         DEBUGADD(10,("Unlinking script output file [%s]\n", tmp_file));
4181         unlink(tmp_file);
4182
4183         if(numlines) {
4184                 /* Set the portname to what the script says the portname should be. */
4185                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
4186                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
4187
4188                 /* Send SIGHUP to process group... is there a better way? */
4189                 kill(0, SIGHUP);
4190                 add_all_printers();
4191         }
4192
4193         file_lines_free(qlines);
4194         return True;
4195 }
4196
4197 /* Return true if two devicemodes are equal */
4198
4199 #define DEVMODE_CHECK_INT(field) \
4200     if (d1->field != d2->field) { \
4201         DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4202             d1->field, d2->field)); \
4203         return False; \
4204     }
4205
4206 static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
4207 {
4208         if (!d1 && !d2) goto equal;  /* if both are NULL they are equal */
4209
4210         if (!d1 ^ !d2) {
4211                 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4212                 return False; /* if either is exclusively NULL are not equal */
4213         }
4214
4215         if (!strequal(d1->devicename, d2->devicename)) {
4216                 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
4217                 return False;
4218         }
4219
4220         if (!strequal(d1->formname, d2->formname)) {
4221                 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
4222                 return False;
4223         }
4224
4225         DEVMODE_CHECK_INT(specversion);
4226         DEVMODE_CHECK_INT(driverversion);
4227         DEVMODE_CHECK_INT(driverextra);
4228         DEVMODE_CHECK_INT(orientation);
4229         DEVMODE_CHECK_INT(papersize);
4230         DEVMODE_CHECK_INT(paperlength);
4231         DEVMODE_CHECK_INT(paperwidth);
4232         DEVMODE_CHECK_INT(scale);
4233         DEVMODE_CHECK_INT(copies);
4234         DEVMODE_CHECK_INT(defaultsource);
4235         DEVMODE_CHECK_INT(printquality);
4236         DEVMODE_CHECK_INT(color);
4237         DEVMODE_CHECK_INT(duplex);
4238         DEVMODE_CHECK_INT(yresolution);
4239         DEVMODE_CHECK_INT(ttoption);
4240         DEVMODE_CHECK_INT(collate);
4241         DEVMODE_CHECK_INT(logpixels);
4242
4243         DEVMODE_CHECK_INT(fields);
4244         DEVMODE_CHECK_INT(bitsperpel);
4245         DEVMODE_CHECK_INT(pelswidth);
4246         DEVMODE_CHECK_INT(pelsheight);
4247         DEVMODE_CHECK_INT(displayflags);
4248         DEVMODE_CHECK_INT(displayfrequency);
4249         DEVMODE_CHECK_INT(icmmethod);
4250         DEVMODE_CHECK_INT(icmintent);
4251         DEVMODE_CHECK_INT(mediatype);
4252         DEVMODE_CHECK_INT(dithertype);
4253         DEVMODE_CHECK_INT(reserved1);
4254         DEVMODE_CHECK_INT(reserved2);
4255         DEVMODE_CHECK_INT(panningwidth);
4256         DEVMODE_CHECK_INT(panningheight);
4257
4258         /* compare the private data if it exists */
4259         if (!d1->driverextra && !d2->driverextra) goto equal;
4260
4261
4262         DEVMODE_CHECK_INT(driverextra);
4263
4264         if (memcmp(d1->private, d2->private, d1->driverextra)) {
4265                 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4266                 return False;
4267         }
4268
4269  equal:
4270         DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4271         return True;
4272 }
4273
4274 /* Return true if two NT_PRINTER_PARAM structures are equal */
4275
4276 static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
4277                                    NT_PRINTER_PARAM *p2)
4278 {
4279         if (!p1 && !p2) goto equal;
4280
4281         if ((!p1 && p2) || (p1 && !p2)) {
4282                 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4283                 return False;
4284         }
4285
4286         /* Compare lists of printer parameters */
4287
4288         while (p1) {
4289                 BOOL found = False;
4290                 NT_PRINTER_PARAM *q = p1;
4291
4292                 /* Find the parameter in the second structure */
4293
4294                 while(q) {
4295
4296                         if (strequal(p1->value, q->value)) {
4297
4298                                 if (p1->type != q->type) {
4299                                         DEBUG(10, ("nt_printer_param_equal():"
4300                                                    "types for %s differ (%d != %d)\n",
4301                                                    p1->value, p1->type,
4302                                                    q->type));
4303                                         break;
4304                                 }
4305
4306                                 if (p1->data_len != q->data_len) {
4307                                         DEBUG(10, ("nt_printer_param_equal():"
4308                                                    "len for %s differs (%d != %d)\n",
4309                                                    p1->value, p1->data_len,
4310                                                    q->data_len));
4311                                         break;
4312                                 }
4313
4314                                 if (memcmp(p1->data, q->data, p1->data_len) == 0) {
4315                                         found = True;
4316                                 } else {
4317                                         DEBUG(10, ("nt_printer_param_equal():"
4318                                                    "data for %s differs\n", p1->value));
4319                                 }
4320
4321                                 break;
4322                         }
4323
4324                         q = q->next;
4325                 }
4326
4327                 if (!found) {
4328                         DEBUG(10, ("nt_printer_param_equal(): param %s "
4329                                    "does not exist\n", p1->value));
4330                         return False;
4331                 }
4332
4333                 p1 = p1->next;
4334         }
4335
4336         equal:
4337
4338         DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4339         return True;
4340 }
4341
4342 /********************************************************************
4343  * Called by update_printer when trying to work out whether to
4344  * actually update printer info.
4345  ********************************************************************/
4346
4347 #define PI_CHECK_INT(field) \
4348     if (pi1->field != pi2->field) { \
4349         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4350             pi1->field, pi2->field)); \
4351         return False; \
4352     }
4353
4354 #define PI_CHECK_STR(field) \
4355     if (!strequal(pi1->field, pi2->field)) { \
4356         DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4357             pi1->field, pi2->field)); \
4358         return False; \
4359     }
4360
4361 static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
4362                                         NT_PRINTER_INFO_LEVEL *p2)
4363 {
4364         NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
4365
4366         /* Trivial conditions */
4367
4368         if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
4369                 goto equal;
4370         }
4371
4372         if ((!p1 && p2) || (p1 && !p2) ||
4373             (!p1->info_2 && p2->info_2) ||
4374             (p1->info_2 && !p2->info_2)) {
4375                 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4376                            "differ\n"));
4377                 return False;
4378         }
4379
4380         /* Compare two nt_printer_info_level structures.  Don't compare
4381            status or cjobs as they seem to have something to do with the
4382            printer queue. */
4383
4384         pi1 = p1->info_2;
4385         pi2 = p2->info_2;
4386
4387         /* Don't check the attributes as we stomp on the value in
4388            check_printer_ok() anyway. */
4389
4390 #if 0
4391         PI_CHECK_INT(attributes);
4392 #endif
4393
4394         PI_CHECK_INT(priority);
4395         PI_CHECK_INT(default_priority);
4396         PI_CHECK_INT(starttime);
4397         PI_CHECK_INT(untiltime);
4398         PI_CHECK_INT(averageppm);
4399
4400         /* Yuck - don't check the printername or servername as the
4401            add_a_printer() code plays games with them.  You can't
4402            change the printername or the sharename through this interface
4403            in Samba. */
4404
4405         PI_CHECK_STR(sharename);
4406         PI_CHECK_STR(portname);
4407         PI_CHECK_STR(drivername);
4408         PI_CHECK_STR(comment);
4409         PI_CHECK_STR(location);
4410
4411         if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
4412                 return False;
4413         }
4414
4415         PI_CHECK_STR(sepfile);
4416         PI_CHECK_STR(printprocessor);
4417         PI_CHECK_STR(datatype);
4418         PI_CHECK_STR(parameters);
4419
4420         if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
4421                 return False;
4422         }
4423
4424         if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
4425                 return False;
4426         }
4427
4428         PI_CHECK_INT(changeid);
4429         PI_CHECK_INT(c_setprinter);
4430         PI_CHECK_INT(setuptime);
4431
4432  equal:
4433         DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4434         return True;
4435 }
4436
4437 /********************************************************************
4438  * called by spoolss_api_setprinter
4439  * when updating a printer description
4440  ********************************************************************/
4441
4442 static uint32 update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
4443                            const SPOOL_PRINTER_INFO_LEVEL *info,
4444                            DEVICEMODE *devmode)
4445 {
4446         int snum;
4447         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
4448         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4449         uint32 result;
4450
4451         DEBUG(8,("update_printer\n"));
4452         
4453         result = NT_STATUS_NO_PROBLEMO;
4454
4455         if (level!=2) {
4456                 DEBUG(0,("Send a mail to samba@samba.org\n"));
4457                 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4458                 result = ERROR_INVALID_LEVEL;
4459                 goto done;
4460         }
4461
4462         if (!Printer) {
4463                 result = ERROR_INVALID_HANDLE;
4464                 goto done;
4465         }
4466
4467         if (!get_printer_snum(p, handle, &snum)) {
4468                 result = ERROR_INVALID_HANDLE;
4469                 goto done;
4470         }
4471
4472         if((get_a_printer(&printer, 2, lp_servicename(snum)) != 0) ||
4473            (get_a_printer(&old_printer, 2, lp_servicename(snum)) != 0)) {
4474                 result = ERROR_INVALID_HANDLE;
4475                 goto done;
4476         }
4477
4478         DEBUGADD(8,("Converting info_2 struct\n"));
4479
4480         /*
4481          * convert_printer_info converts the incoming
4482          * info from the client and overwrites the info
4483          * just read from the tdb in the pointer 'printer'.
4484          */
4485
4486         convert_printer_info(info, printer, level);
4487
4488         if (info->info_2->devmode_ptr != 0) {
4489                 /* we have a valid devmode
4490                    convert it and link it*/
4491
4492                 DEBUGADD(8,("Converting the devicemode struct\n"));
4493                 if (!convert_devicemode(printer->info_2->printername, devmode,
4494                                 &printer->info_2->devmode)) {
4495                         result =  ERROR_NOT_ENOUGH_MEMORY;
4496                         goto done;
4497                 }
4498         }
4499
4500         /* Do sanity check on the requested changes for Samba */
4501
4502         if (!check_printer_ok(printer->info_2, snum)) {
4503                 result = ERROR_INVALID_PARAMETER;
4504                 goto done;
4505         }
4506
4507         /* NT likes to call this function even though nothing has actually
4508            changed.  Check this so the user doesn't end up with an
4509            annoying permission denied dialog box. */
4510
4511         if (nt_printer_info_level_equal(printer, old_printer)) {
4512                 DEBUG(3, ("printer info has not changed\n"));
4513                 result = NT_STATUS_NO_PROBLEMO;
4514                 goto done;
4515         }
4516
4517         /* Check calling user has permission to update printer description */
4518
4519         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4520                 DEBUG(3, ("printer property change denied by security "
4521                           "descriptor\n"));
4522                 result = ERROR_ACCESS_DENIED;
4523                 goto done;
4524         }
4525
4526         /* Call addprinter hook */
4527
4528         if (*lp_addprinter_cmd() )
4529                 if ( !add_printer_hook(printer) ) {
4530                         result = ERROR_ACCESS_DENIED;
4531                         goto done;
4532                 }
4533         
4534         /* Update printer info */
4535
4536         if (add_a_printer(*printer, 2)!=0) {
4537                 /* I don't really know what to return here !!! */
4538                 result = ERROR_ACCESS_DENIED;
4539                 goto done;
4540         }
4541
4542  done:
4543         free_a_printer(&printer, 2);
4544         free_a_printer(&old_printer, 2);
4545
4546         srv_spoolss_sendnotify(p, handle);
4547
4548         return result;
4549 }
4550
4551 /****************************************************************************
4552 ****************************************************************************/
4553
4554 uint32 _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
4555 {
4556         POLICY_HND *handle = &q_u->handle;
4557         uint32 level = q_u->level;
4558         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
4559         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
4560         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
4561         uint32 command = q_u->command;
4562
4563         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
4564         
4565         if (!Printer) {
4566                 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4567                 return ERROR_INVALID_HANDLE;
4568         }
4569
4570         /* check the level */   
4571         switch (level) {
4572                 case 0:
4573                         return control_printer(handle, command, p);
4574                 case 2:
4575                         return update_printer(p, handle, level, info, devmode_ctr.devmode);
4576                 case 3:
4577                         return update_printer_sec(handle, level, info, p,
4578                                                   secdesc_ctr);
4579                 default:
4580                         return ERROR_INVALID_LEVEL;
4581         }
4582 }
4583
4584 /****************************************************************************
4585 ****************************************************************************/
4586
4587 uint32 _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
4588 {
4589         POLICY_HND *handle = &q_u->handle;
4590
4591         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
4592         
4593         if (!Printer) {
4594                 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
4595                 return ERROR_INVALID_HANDLE;
4596         }
4597
4598         if (Printer->notify.client_connected==True)
4599                 srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
4600
4601         Printer->notify.flags=0;
4602         Printer->notify.options=0;
4603         Printer->notify.localmachine[0]='\0';
4604         Printer->notify.printerlocal=0;
4605         if (Printer->notify.option)
4606                 free_spool_notify_option(&Printer->notify.option);
4607         Printer->notify.client_connected=False;
4608
4609         return NT_STATUS_NO_PROBLEMO;
4610 }
4611
4612 /****************************************************************************
4613 ****************************************************************************/
4614
4615 uint32 _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
4616 {
4617         /* that's an [in out] buffer (despite appearences to the contrary) */
4618         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4619
4620         r_u->needed = 0;
4621         return ERROR_INVALID_PARAMETER; /* this is what a NT server
4622                                            returns for AddJob. AddJob
4623                                            must fail on non-local
4624                                            printers */
4625 }
4626
4627 /****************************************************************************
4628 ****************************************************************************/
4629 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
4630                             int position, int snum)
4631 {
4632         pstring temp_name;
4633         
4634         struct tm *t;
4635         
4636         t=gmtime(&queue->time);
4637         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4638
4639         job_info->jobid=queue->job;     
4640         init_unistr(&job_info->printername, lp_servicename(snum));
4641         init_unistr(&job_info->machinename, temp_name);
4642         init_unistr(&job_info->username, queue->user);
4643         init_unistr(&job_info->document, queue->file);
4644         init_unistr(&job_info->datatype, "RAW");
4645         init_unistr(&job_info->text_status, "");
4646         job_info->status=nt_printj_status(queue->status);
4647         job_info->priority=queue->priority;
4648         job_info->position=position;
4649         job_info->totalpages=0;
4650         job_info->pagesprinted=0;
4651
4652         make_systemtime(&job_info->submitted, t);
4653 }
4654
4655 /****************************************************************************
4656 ****************************************************************************/
4657 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
4658                             int position, int snum, 
4659                             NT_PRINTER_INFO_LEVEL *ntprinter)
4660 {
4661         pstring temp_name;
4662         pstring chaine;
4663         struct tm *t;
4664
4665         t=gmtime(&queue->time);
4666         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
4667
4668         job_info->jobid=queue->job;
4669         
4670         slprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
4671
4672         init_unistr(&job_info->printername, chaine);
4673         
4674         init_unistr(&job_info->machinename, temp_name);
4675         init_unistr(&job_info->username, queue->user);
4676         init_unistr(&job_info->document, queue->file);
4677         init_unistr(&job_info->notifyname, queue->user);
4678         init_unistr(&job_info->datatype, "RAW");
4679         init_unistr(&job_info->printprocessor, "winprint");
4680         init_unistr(&job_info->parameters, "");
4681         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
4682         init_unistr(&job_info->text_status, "");
4683         
4684 /* and here the security descriptor */
4685
4686         job_info->status=nt_printj_status(queue->status);
4687         job_info->priority=queue->priority;
4688         job_info->position=position;
4689         job_info->starttime=0;
4690         job_info->untiltime=0;
4691         job_info->totalpages=0;
4692         job_info->size=queue->size;
4693         make_systemtime(&(job_info->submitted), t);
4694         job_info->timeelapsed=0;
4695         job_info->pagesprinted=0;
4696
4697         if((job_info->devmode = construct_dev_mode(snum)) == NULL) {
4698                 return False;
4699         }
4700
4701         return (True);
4702 }
4703
4704 /****************************************************************************
4705  Enumjobs at level 1.
4706 ****************************************************************************/
4707 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
4708                               NEW_BUFFER *buffer, uint32 offered,
4709                               uint32 *needed, uint32 *returned)
4710 {
4711         JOB_INFO_1 *info;
4712         int i;
4713         
4714         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
4715         if (info==NULL) {
4716                 safe_free(queue);
4717                 *returned=0;
4718                 return ERROR_NOT_ENOUGH_MEMORY;
4719         }
4720         
4721         for (i=0; i<*returned; i++)
4722                 fill_job_info_1(&info[i], &queue[i], i, snum);
4723
4724         safe_free(queue);
4725
4726         /* check the required size. */  
4727         for (i=0; i<*returned; i++)
4728                 (*needed) += spoolss_size_job_info_1(&info[i]);
4729
4730         if (!alloc_buffer_size(buffer, *needed)) {
4731                 safe_free(info);
4732                 return ERROR_INSUFFICIENT_BUFFER;
4733         }
4734
4735         /* fill the buffer with the structures */
4736         for (i=0; i<*returned; i++)
4737                 smb_io_job_info_1("", buffer, &info[i], 0);     
4738
4739         /* clear memory */
4740         safe_free(info);
4741
4742         if (*needed > offered) {
4743                 *returned=0;
4744                 return ERROR_INSUFFICIENT_BUFFER;
4745         }
4746         else
4747                 return NT_STATUS_NO_PROBLEMO;
4748 }
4749
4750 /****************************************************************************
4751  Enumjobs at level 2.
4752 ****************************************************************************/
4753 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
4754                               NEW_BUFFER *buffer, uint32 offered,
4755                               uint32 *needed, uint32 *returned)
4756 {
4757         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4758         JOB_INFO_2 *info;
4759         int i;
4760         
4761         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
4762         if (info==NULL) {
4763                 *returned=0;
4764                 return ERROR_NOT_ENOUGH_MEMORY;
4765         }
4766
4767         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
4768                 *returned = 0;
4769                 return ERROR_NOT_ENOUGH_MEMORY;
4770         }
4771                 
4772         for (i=0; i<*returned; i++)
4773                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter);
4774
4775         free_a_printer(&ntprinter, 2);
4776         safe_free(queue);
4777
4778         /* check the required size. */  
4779         for (i=0; i<*returned; i++)
4780                 (*needed) += spoolss_size_job_info_2(&info[i]);
4781
4782         if (!alloc_buffer_size(buffer, *needed)) {
4783                 safe_free(info);
4784                 return ERROR_INSUFFICIENT_BUFFER;
4785         }
4786
4787         /* fill the buffer with the structures */
4788         for (i=0; i<*returned; i++)
4789                 smb_io_job_info_2("", buffer, &info[i], 0);     
4790
4791         /* clear memory */
4792         for (i = 0; i < *returned; i++)
4793                 free_job_info_2(&info[i]);
4794
4795         free(info);
4796
4797         if (*needed > offered) {
4798                 *returned=0;
4799                 return ERROR_INSUFFICIENT_BUFFER;
4800         }
4801         else
4802                 return NT_STATUS_NO_PROBLEMO;
4803 }
4804
4805 /****************************************************************************
4806  Enumjobs.
4807 ****************************************************************************/
4808
4809 uint32 _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
4810 {       
4811         POLICY_HND *handle = &q_u->handle;
4812 /*      uint32 firstjob = q_u->firstjob; - notused. */
4813 /*      uint32 numofjobs = q_u->numofjobs; - notused. */
4814         uint32 level = q_u->level;
4815         NEW_BUFFER *buffer = NULL;
4816         uint32 offered = q_u->offered;
4817         uint32 *needed = &r_u->needed;
4818         uint32 *returned = &r_u->returned;
4819
4820         int snum;
4821         print_queue_struct *queue=NULL;
4822         print_status_struct prt_status;
4823
4824         /* that's an [in out] buffer */
4825         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4826         buffer = r_u->buffer;
4827
4828         DEBUG(4,("_spoolss_enumjobs\n"));
4829
4830         ZERO_STRUCT(prt_status);
4831
4832         *needed=0;
4833         *returned=0;
4834
4835         if (!get_printer_snum(p, handle, &snum))
4836                 return ERROR_INVALID_HANDLE;
4837
4838         *returned = print_queue_status(snum, &queue, &prt_status);
4839         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
4840
4841         if (*returned == 0) {
4842                 safe_free(queue);
4843                 return NT_STATUS_NO_PROBLEMO;
4844         }
4845
4846         switch (level) {
4847         case 1:
4848                 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
4849         case 2:
4850                 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
4851         default:
4852                 safe_free(queue);
4853                 *returned=0;
4854                 return ERROR_INVALID_LEVEL;
4855         }
4856 }
4857
4858 /****************************************************************************
4859 ****************************************************************************/
4860
4861 uint32 _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
4862 {
4863         return 0x0;
4864 }
4865
4866 /****************************************************************************
4867 ****************************************************************************/
4868
4869 uint32 _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
4870 {
4871         POLICY_HND *handle = &q_u->handle;
4872         uint32 jobid = q_u->jobid;
4873 /*      uint32 level = q_u->level; - notused. */
4874 /*      JOB_INFO *ctr = &q_u->ctr; - notused. */
4875         uint32 command = q_u->command;
4876
4877         struct current_user user;
4878         print_status_struct prt_status;
4879         int snum, errcode = ERROR_INVALID_FUNCTION;
4880                 
4881         memset(&prt_status, 0, sizeof(prt_status));
4882
4883         if (!get_printer_snum(p, handle, &snum)) {
4884                 return ERROR_INVALID_HANDLE;
4885         }
4886
4887         if (!print_job_exists(jobid)) {
4888                 return ERROR_INVALID_PRINTER_NAME;
4889         }
4890
4891         get_current_user(&user, p);     
4892
4893         switch (command) {
4894         case JOB_CONTROL_CANCEL:
4895         case JOB_CONTROL_DELETE:
4896                 if (print_job_delete(&user, jobid, &errcode)) {
4897                         errcode = 0;
4898                 }
4899                 break;
4900         case JOB_CONTROL_PAUSE:
4901                 if (print_job_pause(&user, jobid, &errcode)) {
4902                         errcode = 0;
4903                 }               
4904                 break;
4905         case JOB_CONTROL_RESTART:
4906         case JOB_CONTROL_RESUME:
4907                 if (print_job_resume(&user, jobid, &errcode)) {
4908                         errcode = 0;
4909                 }
4910                 break;
4911         default:
4912                 return ERROR_INVALID_LEVEL;
4913         }
4914
4915         return errcode;
4916 }
4917
4918 /****************************************************************************
4919  Enumerates all printer drivers at level 1.
4920 ****************************************************************************/
4921 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4922 {
4923         int i;
4924         int ndrivers;
4925         uint32 version;
4926         fstring *list = NULL;
4927
4928         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4929         DRIVER_INFO_1 *driver_info_1=NULL;
4930
4931         *returned=0;
4932
4933 #define MAX_VERSION 4
4934
4935         for (version=0; version<MAX_VERSION; version++) {
4936                 list=NULL;
4937                 ndrivers=get_ntdrivers(&list, architecture, version);
4938                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
4939
4940                 if(ndrivers == -1)
4941                         return ERROR_NOT_ENOUGH_MEMORY;
4942
4943                 if(ndrivers != 0) {
4944                         if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
4945                                 safe_free(list);
4946                                 return ERROR_NOT_ENOUGH_MEMORY;
4947                         }
4948                 }
4949
4950                 for (i=0; i<ndrivers; i++) {
4951                         uint32 status;
4952                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4953                         ZERO_STRUCT(driver);
4954                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
4955                                 safe_free(list);
4956                                 return status;
4957                         }
4958                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
4959                         free_a_printer_driver(driver, 3);
4960                 }       
4961
4962                 *returned+=ndrivers;
4963                 safe_free(list);
4964         }
4965         
4966         /* check the required size. */
4967         for (i=0; i<*returned; i++) {
4968                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
4969                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
4970         }
4971
4972         if (!alloc_buffer_size(buffer, *needed)) {
4973                 safe_free(driver_info_1);
4974                 return ERROR_INSUFFICIENT_BUFFER;
4975         }
4976
4977         /* fill the buffer with the driver structures */
4978         for (i=0; i<*returned; i++) {
4979                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
4980                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
4981         }
4982
4983         safe_free(driver_info_1);
4984
4985         if (*needed > offered) {
4986                 *returned=0;
4987                 return ERROR_INSUFFICIENT_BUFFER;
4988         }
4989         else
4990                 return NT_STATUS_NO_PROBLEMO;
4991 }
4992
4993 /****************************************************************************
4994  Enumerates all printer drivers at level 2.
4995 ****************************************************************************/
4996 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4997 {
4998         int i;
4999         int ndrivers;
5000         uint32 version;
5001         fstring *list = NULL;
5002
5003         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5004         DRIVER_INFO_2 *driver_info_2=NULL;
5005
5006         *returned=0;
5007
5008 #define MAX_VERSION 4
5009
5010         for (version=0; version<MAX_VERSION; version++) {
5011                 list=NULL;
5012                 ndrivers=get_ntdrivers(&list, architecture, version);
5013                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5014
5015                 if(ndrivers == -1)
5016                         return ERROR_NOT_ENOUGH_MEMORY;
5017
5018                 if(ndrivers != 0) {
5019                         if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
5020                                 safe_free(list);
5021                                 return ERROR_NOT_ENOUGH_MEMORY;
5022                         }
5023                 }
5024                 
5025                 for (i=0; i<ndrivers; i++) {
5026                         uint32 status;
5027
5028                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5029                         ZERO_STRUCT(driver);
5030                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5031                                 safe_free(list);
5032                                 return status;
5033                         }
5034                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
5035                         free_a_printer_driver(driver, 3);
5036                 }       
5037
5038                 *returned+=ndrivers;
5039                 safe_free(list);
5040         }
5041         
5042         /* check the required size. */
5043         for (i=0; i<*returned; i++) {
5044                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5045                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
5046         }
5047
5048         if (!alloc_buffer_size(buffer, *needed)) {
5049                 safe_free(driver_info_2);
5050                 return ERROR_INSUFFICIENT_BUFFER;
5051         }
5052
5053         /* fill the buffer with the form structures */
5054         for (i=0; i<*returned; i++) {
5055                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5056                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
5057         }
5058
5059         safe_free(driver_info_2);
5060
5061         if (*needed > offered) {
5062                 *returned=0;
5063                 return ERROR_INSUFFICIENT_BUFFER;
5064         }
5065         else
5066                 return NT_STATUS_NO_PROBLEMO;
5067 }
5068
5069 /****************************************************************************
5070  Enumerates all printer drivers at level 3.
5071 ****************************************************************************/
5072 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5073 {
5074         int i;
5075         int ndrivers;
5076         uint32 version;
5077         fstring *list = NULL;
5078
5079         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5080         DRIVER_INFO_3 *driver_info_3=NULL;
5081
5082         *returned=0;
5083
5084 #define MAX_VERSION 4
5085
5086         for (version=0; version<MAX_VERSION; version++) {
5087                 list=NULL;
5088                 ndrivers=get_ntdrivers(&list, architecture, version);
5089                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
5090
5091                 if(ndrivers == -1)
5092                         return ERROR_NOT_ENOUGH_MEMORY;
5093
5094                 if(ndrivers != 0) {
5095                         if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
5096                                 safe_free(list);
5097                                 return ERROR_NOT_ENOUGH_MEMORY;
5098                         }
5099                 }
5100
5101                 for (i=0; i<ndrivers; i++) {
5102                         uint32 status;
5103
5104                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5105                         ZERO_STRUCT(driver);
5106                         if ((status = get_a_printer_driver(&driver, 3, list[i], architecture, version)) != 0) {
5107                                 safe_free(list);
5108                                 return status;
5109                         }
5110                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
5111                         free_a_printer_driver(driver, 3);
5112                 }       
5113
5114                 *returned+=ndrivers;
5115                 safe_free(list);
5116         }
5117
5118         /* check the required size. */
5119         for (i=0; i<*returned; i++) {
5120                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
5121                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
5122         }
5123
5124         if (!alloc_buffer_size(buffer, *needed)) {
5125                 safe_free(driver_info_3);
5126                 return ERROR_INSUFFICIENT_BUFFER;
5127         }
5128         
5129         /* fill the buffer with the driver structures */
5130         for (i=0; i<*returned; i++) {
5131                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
5132                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
5133         }
5134
5135         for (i=0; i<*returned; i++)
5136                 safe_free(driver_info_3[i].dependentfiles);
5137         
5138         safe_free(driver_info_3);
5139         
5140         if (*needed > offered) {
5141                 *returned=0;
5142                 return ERROR_INSUFFICIENT_BUFFER;
5143         }
5144         else
5145                 return NT_STATUS_NO_PROBLEMO;
5146 }
5147
5148 /****************************************************************************
5149  Enumerates all printer drivers.
5150 ****************************************************************************/
5151
5152 uint32 _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
5153 {
5154 /*      UNISTR2 *name = &q_u->name; - notused. */
5155         UNISTR2 *environment = &q_u->environment;
5156         uint32 level = q_u->level;
5157         NEW_BUFFER *buffer = NULL;
5158         uint32 offered = q_u->offered;
5159         uint32 *needed = &r_u->needed;
5160         uint32 *returned = &r_u->returned;
5161
5162         fstring *list = NULL;
5163         fstring servername;
5164         fstring architecture;
5165
5166         /* that's an [in out] buffer */
5167         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5168         buffer = r_u->buffer;
5169
5170         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5171         fstrcpy(servername, global_myname);
5172         *needed=0;
5173         *returned=0;
5174
5175         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
5176
5177         switch (level) {
5178         case 1:
5179                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
5180         case 2:
5181                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
5182         case 3:
5183                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
5184         default:
5185                 *returned=0;
5186                 safe_free(list);
5187                 return ERROR_INVALID_LEVEL;
5188         }
5189 }
5190
5191 /****************************************************************************
5192 ****************************************************************************/
5193
5194 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
5195 {
5196         form->flag=list->flag;
5197         init_unistr(&form->name, list->name);
5198         form->width=list->width;
5199         form->length=list->length;
5200         form->left=list->left;
5201         form->top=list->top;
5202         form->right=list->right;
5203         form->bottom=list->bottom;      
5204 }
5205         
5206 /****************************************************************************
5207 ****************************************************************************/
5208
5209 uint32 _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
5210 {
5211 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5212         uint32 level = q_u->level;
5213         NEW_BUFFER *buffer = NULL;
5214         uint32 offered = q_u->offered;
5215         uint32 *needed = &r_u->needed;
5216         uint32 *numofforms = &r_u->numofforms;
5217         uint32 numbuiltinforms;
5218
5219         nt_forms_struct *list=NULL;
5220         nt_forms_struct *builtinlist=NULL;
5221         FORM_1 *forms_1;
5222         int buffer_size=0;
5223         int i;
5224
5225         /* that's an [in out] buffer */
5226         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5227         buffer = r_u->buffer;
5228
5229         DEBUG(4,("_spoolss_enumforms\n"));
5230         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5231         DEBUGADD(5,("Info level [%d]\n",          level));
5232
5233         numbuiltinforms = get_builtin_ntforms(&builtinlist);
5234         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
5235         *numofforms = get_ntforms(&list);
5236         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
5237         *numofforms += numbuiltinforms;
5238
5239         if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
5240
5241         switch (level) {
5242         case 1:
5243                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
5244                         *numofforms=0;
5245                         return ERROR_NOT_ENOUGH_MEMORY;
5246                 }
5247
5248                 /* construct the list of form structures */
5249                 for (i=0; i<numbuiltinforms; i++) {
5250                         DEBUGADD(6,("Filling form number [%d]\n",i));
5251                         fill_form_1(&forms_1[i], &builtinlist[i]);
5252                 }
5253                 
5254                 safe_free(builtinlist);
5255
5256                 for (; i<*numofforms; i++) {
5257                         DEBUGADD(6,("Filling form number [%d]\n",i));
5258                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
5259                 }
5260                 
5261                 safe_free(list);
5262
5263                 /* check the required size. */
5264                 for (i=0; i<numbuiltinforms; i++) {
5265                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5266                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5267                 }
5268                 for (; i<*numofforms; i++) {
5269                         DEBUGADD(6,("adding form [%d]'s size\n",i));
5270                         buffer_size += spoolss_size_form_1(&forms_1[i]);
5271                 }
5272
5273                 *needed=buffer_size;            
5274                 
5275                 if (!alloc_buffer_size(buffer, buffer_size)){
5276                         safe_free(forms_1);
5277                         return ERROR_INSUFFICIENT_BUFFER;
5278                 }
5279
5280                 /* fill the buffer with the form structures */
5281                 for (i=0; i<numbuiltinforms; i++) {
5282                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5283                         smb_io_form_1("", buffer, &forms_1[i], 0);
5284                 }
5285                 for (; i<*numofforms; i++) {
5286                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
5287                         smb_io_form_1("", buffer, &forms_1[i], 0);
5288                 }
5289
5290                 safe_free(forms_1);
5291
5292                 if (*needed > offered) {
5293                         *numofforms=0;
5294                         return ERROR_INSUFFICIENT_BUFFER;
5295                 }
5296                 else
5297                         return NT_STATUS_NO_PROBLEMO;
5298                         
5299         default:
5300                 safe_free(list);
5301                 safe_free(builtinlist);
5302                 return ERROR_INVALID_LEVEL;
5303         }
5304
5305 }
5306
5307 /****************************************************************************
5308 ****************************************************************************/
5309
5310 uint32 _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
5311 {
5312 /*      POLICY_HND *handle = &q_u->handle; - notused. */
5313         uint32 level = q_u->level;
5314         UNISTR2 *uni_formname = &q_u->formname;
5315         NEW_BUFFER *buffer = NULL;
5316         uint32 offered = q_u->offered;
5317         uint32 *needed = &r_u->needed;
5318
5319         nt_forms_struct *list=NULL;
5320         nt_forms_struct builtin_form;
5321         BOOL foundBuiltin;
5322         FORM_1 form_1;
5323         fstring form_name;
5324         int buffer_size=0;
5325         int numofforms, i;
5326
5327         /* that's an [in out] buffer */
5328         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5329         buffer = r_u->buffer;
5330
5331         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
5332
5333         DEBUG(4,("_spoolss_getform\n"));
5334         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
5335         DEBUGADD(5,("Info level [%d]\n",          level));
5336
5337         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
5338         if (!foundBuiltin) {
5339                 numofforms = get_ntforms(&list);
5340                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
5341
5342                 if (numofforms == 0)
5343                         return ERROR_INVALID_HANDLE;
5344         }
5345
5346         switch (level) {
5347         case 1:
5348                 if (foundBuiltin) {
5349                         fill_form_1(&form_1, &builtin_form);
5350                 } else {
5351
5352                         /* Check if the requested name is in the list of form structures */
5353                         for (i=0; i<numofforms; i++) {
5354
5355                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
5356
5357                                 if (strequal(form_name, list[i].name)) {
5358                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
5359                                         fill_form_1(&form_1, &list[i]);
5360                                         break;
5361                                 }
5362                         }
5363                         
5364                         safe_free(list);
5365                         if (i == numofforms) {
5366                                 return ERROR_INVALID_HANDLE;
5367                         }
5368                 }
5369                 /* check the required size. */
5370
5371                 *needed=spoolss_size_form_1(&form_1);
5372                 
5373                 if (!alloc_buffer_size(buffer, buffer_size)){
5374                         return ERROR_INSUFFICIENT_BUFFER;
5375                 }
5376
5377                 if (*needed > offered) {
5378                         return ERROR_INSUFFICIENT_BUFFER;
5379                 }
5380
5381                 /* fill the buffer with the form structures */
5382                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
5383                 smb_io_form_1("", buffer, &form_1, 0);
5384
5385                 return NT_STATUS_NO_PROBLEMO;
5386                         
5387         default:
5388                 safe_free(list);
5389                 return ERROR_INVALID_LEVEL;
5390         }
5391 }
5392
5393 /****************************************************************************
5394 ****************************************************************************/
5395 static void fill_port_1(PORT_INFO_1 *port, char *name)
5396 {
5397         init_unistr(&port->port_name, name);
5398 }
5399
5400 /****************************************************************************
5401 ****************************************************************************/
5402 static void fill_port_2(PORT_INFO_2 *port, char *name)
5403 {
5404         init_unistr(&port->port_name, name);
5405         init_unistr(&port->monitor_name, "Local Monitor");
5406         init_unistr(&port->description, "Local Port");
5407 #define PORT_TYPE_WRITE 1
5408         port->port_type=PORT_TYPE_WRITE;
5409         port->reserved=0x0;     
5410 }
5411
5412 /****************************************************************************
5413  enumports level 1.
5414 ****************************************************************************/
5415 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5416 {
5417         PORT_INFO_1 *ports=NULL;
5418         int i=0;
5419
5420         if (*lp_enumports_cmd()) {
5421                 pid_t local_pid = sys_getpid();
5422                 char *cmd = lp_enumports_cmd();
5423                 char *path;
5424                 char **qlines;
5425                 pstring tmp_file;
5426                 pstring command;
5427                 int numlines;
5428                 int ret;
5429
5430                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5431                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5432                 else
5433                         path = tmpdir();
5434
5435                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5436                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
5437
5438                 unlink(tmp_file);
5439                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5440                 ret = smbrun(command, tmp_file, False);
5441                 DEBUG(10,("Returned [%d]\n", ret));
5442                 if (ret != 0) {
5443                         unlink(tmp_file);
5444                         /* Is this the best error to return here? */
5445                         return ERROR_ACCESS_DENIED;
5446                 }
5447
5448                 numlines = 0;
5449                 qlines = file_lines_load(tmp_file, &numlines,True);
5450                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5451                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5452                 unlink(tmp_file);
5453
5454                 if(numlines) {
5455                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
5456                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5457                                 file_lines_free(qlines);
5458                                 return ERROR_NOT_ENOUGH_MEMORY;
5459                         }
5460
5461                         for (i=0; i<numlines; i++) {
5462                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5463                                 fill_port_1(&ports[i], qlines[i]);
5464                         }
5465
5466                         file_lines_free(qlines);
5467                 }
5468
5469                 *returned = numlines;
5470
5471         } else {
5472                 *returned = 1; /* Sole Samba port returned. */
5473
5474                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
5475                         return ERROR_NOT_ENOUGH_MEMORY;
5476         
5477                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5478
5479                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
5480         }
5481
5482         /* check the required size. */
5483         for (i=0; i<*returned; i++) {
5484                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5485                 *needed += spoolss_size_port_info_1(&ports[i]);
5486         }
5487                 
5488         if (!alloc_buffer_size(buffer, *needed)) {
5489                 safe_free(ports);
5490                 return ERROR_INSUFFICIENT_BUFFER;
5491         }
5492
5493         /* fill the buffer with the ports structures */
5494         for (i=0; i<*returned; i++) {
5495                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5496                 smb_io_port_1("", buffer, &ports[i], 0);
5497         }
5498
5499         safe_free(ports);
5500
5501         if (*needed > offered) {
5502                 *returned=0;
5503                 return ERROR_INSUFFICIENT_BUFFER;
5504         }
5505         else
5506                 return NT_STATUS_NO_PROBLEMO;
5507 }
5508
5509 /****************************************************************************
5510  enumports level 2.
5511 ****************************************************************************/
5512
5513 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
5514 {
5515         PORT_INFO_2 *ports=NULL;
5516         int i=0;
5517
5518         if (*lp_enumports_cmd()) {
5519                 pid_t local_pid = sys_getpid();
5520                 char *cmd = lp_enumports_cmd();
5521                 char *path;
5522                 char **qlines;
5523                 pstring tmp_file;
5524                 pstring command;
5525                 int numlines;
5526                 int ret;
5527
5528                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
5529                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
5530                 else
5531                         path = tmpdir();
5532
5533                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%d", path, local_pid);
5534                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
5535
5536                 unlink(tmp_file);
5537                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
5538                 ret = smbrun(command, tmp_file, False);
5539                 DEBUGADD(10,("returned [%d]\n", ret));
5540                 if (ret != 0) {
5541                         unlink(tmp_file);
5542                         /* Is this the best error to return here? */
5543                         return ERROR_ACCESS_DENIED;
5544                 }
5545
5546                 numlines = 0;
5547                 qlines = file_lines_load(tmp_file, &numlines,True);
5548                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5549                 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
5550                 unlink(tmp_file);
5551
5552                 if(numlines) {
5553                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
5554                                 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
5555                                 file_lines_free(qlines);
5556                                 return ERROR_NOT_ENOUGH_MEMORY;
5557                         }
5558
5559                         for (i=0; i<numlines; i++) {
5560                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
5561                                 fill_port_2(&(ports[i]), qlines[i]);
5562                         }
5563
5564                         file_lines_free(qlines);
5565                 }
5566
5567                 *returned = numlines;
5568
5569         } else {
5570
5571                 *returned = 1;
5572
5573                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
5574                         return ERROR_NOT_ENOUGH_MEMORY;
5575         
5576                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
5577
5578                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
5579         }
5580
5581         /* check the required size. */
5582         for (i=0; i<*returned; i++) {
5583                 DEBUGADD(6,("adding port [%d]'s size\n", i));
5584                 *needed += spoolss_size_port_info_2(&ports[i]);
5585         }
5586                 
5587         if (!alloc_buffer_size(buffer, *needed)) {
5588                 safe_free(ports);
5589                 return ERROR_INSUFFICIENT_BUFFER;
5590         }
5591
5592         /* fill the buffer with the ports structures */
5593         for (i=0; i<*returned; i++) {
5594                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
5595                 smb_io_port_2("", buffer, &ports[i], 0);
5596         }
5597
5598         safe_free(ports);
5599
5600         if (*needed > offered) {
5601                 *returned=0;
5602                 return ERROR_INSUFFICIENT_BUFFER;
5603         }
5604         else
5605                 return NT_STATUS_NO_PROBLEMO;
5606 }
5607
5608 /****************************************************************************
5609  enumports.
5610 ****************************************************************************/
5611
5612 uint32 _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
5613 {
5614 /*      UNISTR2 *name = &q_u->name; - notused. */
5615         uint32 level = q_u->level;
5616         NEW_BUFFER *buffer = NULL;
5617         uint32 offered = q_u->offered;
5618         uint32 *needed = &r_u->needed;
5619         uint32 *returned = &r_u->returned;
5620
5621         /* that's an [in out] buffer */
5622         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5623         buffer = r_u->buffer;
5624
5625         DEBUG(4,("_spoolss_enumports\n"));
5626         
5627         *returned=0;
5628         *needed=0;
5629         
5630         switch (level) {
5631         case 1:
5632                 return enumports_level_1(buffer, offered, needed, returned);
5633         case 2:
5634                 return enumports_level_2(buffer, offered, needed, returned);
5635         default:
5636                 return ERROR_INVALID_LEVEL;
5637         }
5638 }
5639
5640 /****************************************************************************
5641 ****************************************************************************/
5642 static uint32 spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
5643                                 const SPOOL_PRINTER_INFO_LEVEL *info,
5644                                 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
5645                                 uint32 user_switch, const SPOOL_USER_CTR *user,
5646                                 POLICY_HND *handle)
5647 {
5648         NT_PRINTER_INFO_LEVEL *printer = NULL;
5649         fstring name;
5650         int snum;
5651
5652         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
5653                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5654                 return ERROR_NOT_ENOUGH_MEMORY;
5655         }
5656
5657         ZERO_STRUCTP(printer);
5658
5659         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5660         convert_printer_info(info, printer, 2);
5661
5662         if (*lp_addprinter_cmd() )
5663                 if ( !add_printer_hook(printer) ) {
5664                         free_a_printer(&printer,2);
5665                         return ERROR_ACCESS_DENIED;
5666         }
5667
5668         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
5669              printer->info_2->sharename);
5670
5671         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
5672                 free_a_printer(&printer,2);
5673                 return ERROR_ACCESS_DENIED;
5674         }
5675
5676         /* you must be a printer admin to add a new printer */
5677         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
5678                 free_a_printer(&printer,2);
5679                 return ERROR_ACCESS_DENIED;             
5680         }
5681         
5682         /*
5683          * Do sanity check on the requested changes for Samba.
5684          */
5685
5686         if (!check_printer_ok(printer->info_2, snum)) {
5687                 free_a_printer(&printer,2);
5688                 return ERROR_INVALID_PARAMETER;
5689         }
5690
5691         /* write the ASCII on disk */
5692         if (add_a_printer(*printer, 2) != 0) {
5693                 free_a_printer(&printer,2);
5694                 return ERROR_ACCESS_DENIED;
5695         }
5696
5697         if (!open_printer_hnd(p, handle, name)) {
5698                 /* Handle open failed - remove addition. */
5699                 del_a_printer(printer->info_2->sharename);
5700                 free_a_printer(&printer,2);
5701                 return ERROR_ACCESS_DENIED;
5702         }
5703
5704         free_a_printer(&printer,2);
5705
5706         srv_spoolss_sendnotify(p, handle);
5707
5708         return NT_STATUS_NO_PROBLEMO;
5709 }
5710
5711 /****************************************************************************
5712 ****************************************************************************/
5713
5714 uint32 _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
5715 {
5716         UNISTR2 *uni_srv_name = &q_u->server_name;
5717         uint32 level = q_u->level;
5718         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
5719         uint32 unk0 = q_u->unk0;
5720         uint32 unk1 = q_u->unk1;
5721         uint32 unk2 = q_u->unk2;
5722         uint32 unk3 = q_u->unk3;
5723         uint32 user_switch = q_u->user_switch;
5724         SPOOL_USER_CTR *user = &q_u->user_ctr;
5725         POLICY_HND *handle = &r_u->handle;
5726
5727         switch (level) {
5728                 case 1:
5729                         /* we don't handle yet */
5730                         /* but I know what to do ... */
5731                         return ERROR_INVALID_LEVEL;
5732                 case 2:
5733                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
5734                                                             unk0, unk1, unk2, unk3,
5735                                                             user_switch, user, handle);
5736                 default:
5737                         return ERROR_INVALID_LEVEL;
5738         }
5739 }
5740
5741 /****************************************************************************
5742 ****************************************************************************/
5743
5744 uint32 _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
5745 {
5746 /*      UNISTR2 *server_name = &q_u->server_name; - notused. */
5747         uint32 level = q_u->level;
5748         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
5749
5750         uint32 err = NT_STATUS_NO_PROBLEMO;
5751         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5752         struct current_user user;
5753         
5754         ZERO_STRUCT(driver);
5755
5756         get_current_user(&user, p);     
5757         
5758         convert_printer_driver_info(info, &driver, level);
5759
5760         DEBUG(5,("Cleaning driver's information\n"));
5761         if ((err = clean_up_driver_struct(driver, level, &user)) != NT_STATUS_NO_PROBLEMO )
5762                 goto done;
5763
5764         DEBUG(5,("Moving driver to final destination\n"));
5765         if(!move_driver_to_download_area(driver, level, &user, &err)) {
5766                 if (err == 0)
5767                         err = ERROR_ACCESS_DENIED;
5768                 goto done;
5769         }
5770
5771         if (add_a_printer_driver(driver, level)!=0) {
5772                 err = ERROR_ACCESS_DENIED;
5773                 goto done;
5774         }
5775
5776  done:
5777         free_a_printer_driver(driver, level);
5778         return err;
5779 }
5780
5781 /****************************************************************************
5782 ****************************************************************************/
5783 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
5784 {
5785         init_unistr(&info->name, name);
5786 }
5787
5788 /****************************************************************************
5789 ****************************************************************************/
5790 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5791 {
5792         pstring path;
5793         pstring long_archi;
5794         pstring short_archi;
5795         DRIVER_DIRECTORY_1 *info=NULL;
5796
5797         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
5798
5799         if (get_short_archi(short_archi, long_archi)==FALSE)
5800                 return ERROR_INVALID_ENVIRONMENT;
5801
5802         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
5803                 return ERROR_NOT_ENOUGH_MEMORY;
5804
5805         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
5806
5807         DEBUG(4,("printer driver directory: [%s]\n", path));
5808
5809         fill_driverdir_1(info, path);
5810         
5811         *needed += spoolss_size_driverdir_info_1(info);
5812
5813         if (!alloc_buffer_size(buffer, *needed)) {
5814                 safe_free(info);
5815                 return ERROR_INSUFFICIENT_BUFFER;
5816         }
5817
5818         smb_io_driverdir_1("", buffer, info, 0);
5819
5820         safe_free(info);
5821         
5822         if (*needed > offered)
5823                 return ERROR_INSUFFICIENT_BUFFER;
5824         else
5825                 return NT_STATUS_NO_PROBLEMO;
5826 }
5827
5828 /****************************************************************************
5829 ****************************************************************************/
5830
5831 uint32 _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
5832 {
5833         UNISTR2 *name = &q_u->name;
5834         UNISTR2 *uni_environment = &q_u->environment;
5835         uint32 level = q_u->level;
5836         NEW_BUFFER *buffer = NULL;
5837         uint32 offered = q_u->offered;
5838         uint32 *needed = &r_u->needed;
5839
5840         /* that's an [in out] buffer */
5841         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5842         buffer = r_u->buffer;
5843
5844         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5845
5846         *needed=0;
5847
5848         switch(level) {
5849         case 1:
5850                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
5851         default:
5852                 return ERROR_INVALID_LEVEL;
5853         }
5854 }
5855         
5856 /****************************************************************************
5857 ****************************************************************************/
5858
5859 uint32 _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
5860 {
5861         POLICY_HND *handle = &q_u->handle;
5862         uint32 idx = q_u->index;
5863         uint32 in_value_len = q_u->valuesize;
5864         uint32 in_data_len = q_u->datasize;
5865         uint32 *out_max_value_len = &r_u->valuesize;
5866         uint16 **out_value = &r_u->value;
5867         uint32 *out_value_len = &r_u->realvaluesize;
5868         uint32 *out_type = &r_u->type;
5869         uint32 *out_max_data_len = &r_u->datasize;
5870         uint8  **data_out = &r_u->data;
5871         uint32 *out_data_len = &r_u->realdatasize;
5872
5873         NT_PRINTER_INFO_LEVEL *printer = NULL;
5874         
5875         fstring value;
5876         
5877         uint32 param_index;
5878         uint32 biggest_valuesize;
5879         uint32 biggest_datasize;
5880         uint32 data_len;
5881         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5882         int snum;
5883         uint8 *data=NULL;
5884         uint32 type;
5885
5886         ZERO_STRUCT(printer);
5887         
5888         *out_max_value_len=0;
5889         *out_value=NULL;
5890         *out_value_len=0;
5891
5892         *out_type=0;
5893
5894         *out_max_data_len=0;
5895         *data_out=NULL;
5896         *out_data_len=0;
5897
5898         DEBUG(5,("spoolss_enumprinterdata\n"));
5899
5900         if (!Printer) {
5901                 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
5902                 return ERROR_INVALID_HANDLE;
5903         }
5904
5905         if (!get_printer_snum(p,handle, &snum))
5906                 return ERROR_INVALID_HANDLE;
5907         
5908         if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
5909                 return ERROR_INVALID_HANDLE;
5910
5911         /*
5912          * The NT machine wants to know the biggest size of value and data
5913          *
5914          * cf: MSDN EnumPrinterData remark section
5915          */
5916         if ( (in_value_len==0) && (in_data_len==0) ) {
5917                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5918
5919 #if 0
5920                 /*
5921                  * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5922                  * if this parameter size doesn't exist.
5923                  * Ok - my opinion here is that the client is not asking for the greatest
5924                  * possible size of all the parameters, but is asking specifically for the size needed
5925                  * for this specific parameter. In that case we can remove the loop below and
5926                  * simplify this lookup code considerably. JF - comments welcome. JRA.
5927                  */
5928
5929                 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5930                         safe_free(data);
5931                         free_a_printer(&printer, 2);
5932                         return ERROR_NO_MORE_ITEMS;
5933                 }
5934 #endif
5935
5936                 safe_free(data);
5937                 data = NULL;
5938
5939                 param_index=0;
5940                 biggest_valuesize=0;
5941                 biggest_datasize=0;
5942                 
5943                 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
5944                         if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
5945                         if (data_len > biggest_datasize) biggest_datasize=data_len;
5946
5947                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
5948
5949                         safe_free(data);
5950                         data = NULL;
5951                         param_index++;
5952                 }
5953
5954                 /*
5955                  * I think this is correct, it doesn't break APW and
5956                  * allows Gerald's Win32 test programs to work correctly,
5957                  * but may need altering.... JRA.
5958                  */
5959
5960                 if (param_index == 0) {
5961                         /* No parameters found. */
5962                         free_a_printer(&printer, 2);
5963                         return ERROR_NO_MORE_ITEMS;
5964                 }
5965
5966                 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5967                 *out_value_len=2*(1+biggest_valuesize);
5968                 *out_data_len=biggest_datasize;
5969
5970                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
5971
5972                 free_a_printer(&printer, 2);
5973                 return NT_STATUS_NO_PROBLEMO;
5974         }
5975         
5976         /*
5977          * the value len is wrong in NT sp3
5978          * that's the number of bytes not the number of unicode chars
5979          */
5980
5981         if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
5982                 safe_free(data);
5983                 free_a_printer(&printer, 2);
5984                 return ERROR_NO_MORE_ITEMS;
5985         }
5986
5987         free_a_printer(&printer, 2);
5988
5989         /*
5990          * the value is:
5991          * - counted in bytes in the request
5992          * - counted in UNICODE chars in the max reply
5993          * - counted in bytes in the real size
5994          *
5995          * take a pause *before* coding not *during* coding
5996          */
5997         
5998         *out_max_value_len=(in_value_len/sizeof(uint16));
5999         if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
6000                 safe_free(data);
6001                 return ERROR_NOT_ENOUGH_MEMORY;
6002         }
6003         
6004         *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
6005
6006         *out_type=type;
6007
6008         /* the data is counted in bytes */
6009         *out_max_data_len=in_data_len;
6010         if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
6011                 safe_free(data);
6012                 return ERROR_NOT_ENOUGH_MEMORY;
6013         }
6014         
6015         memcpy(*data_out, data, (size_t)data_len);
6016         *out_data_len=data_len;
6017
6018         safe_free(data);
6019         
6020         return NT_STATUS_NO_PROBLEMO;
6021 }
6022
6023 /****************************************************************************
6024 ****************************************************************************/
6025
6026 uint32 _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
6027 {
6028         POLICY_HND *handle = &q_u->handle;
6029         UNISTR2 *value = &q_u->value;
6030         uint32 type = q_u->type;
6031 /*      uint32 max_len = q_u->max_len; - notused. */
6032         uint8 *data = q_u->data;
6033         uint32 real_len = q_u->real_len;
6034 /*      uint32 numeric_data = q_u->numeric_data; - notused. */
6035
6036         NT_PRINTER_INFO_LEVEL *printer = NULL;
6037         NT_PRINTER_PARAM *param = NULL, old_param;
6038         int snum=0;
6039         uint32 status = 0x0;
6040         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6041         
6042         DEBUG(5,("spoolss_setprinterdata\n"));
6043
6044         if (!Printer) {
6045                 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6046                 return ERROR_INVALID_HANDLE;
6047         }
6048
6049         if (!get_printer_snum(p,handle, &snum))
6050                 return ERROR_INVALID_HANDLE;
6051
6052         status = get_a_printer(&printer, 2, lp_servicename(snum));
6053         if (status != 0x0)
6054                 return ERROR_INVALID_NAME;
6055
6056         convert_specific_param(&param, value , type, data, real_len);
6057
6058     /* Check if we are making any changes or not.  Return true if
6059            nothing is actually changing. */
6060         
6061     ZERO_STRUCT(old_param);
6062
6063         if (get_specific_param(*printer, 2, param->value, &old_param.data,
6064                                &old_param.type, (unsigned int *)&old_param.data_len)) {
6065
6066                 if (param->type == old_param.type &&
6067                     param->data_len == old_param.data_len &&
6068                     memcmp(param->data, old_param.data,
6069                            old_param.data_len) == 0) {
6070
6071                         DEBUG(3, ("setprinterdata hasn't changed\n"));
6072                         status = NT_STATUS_NO_PROBLEMO;
6073                         goto done;
6074                 }
6075         }
6076
6077         /* Access check */
6078
6079         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6080                 DEBUG(3, ("security descriptor change denied by existing "
6081                           "security descriptor\n"));
6082                 status = ERROR_ACCESS_DENIED;
6083                 goto done;
6084         }
6085
6086         unlink_specific_param_if_exist(printer->info_2, param);
6087         
6088         add_a_specific_param(printer->info_2, &param);
6089         status = mod_a_printer(*printer, 2);
6090
6091  done:
6092         free_a_printer(&printer, 2);
6093         if (param)
6094                 free_nt_printer_param(&param);
6095         safe_free(old_param.data);
6096
6097         return status;
6098 }
6099
6100 /****************************************************************************
6101 ****************************************************************************/
6102
6103 uint32 _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
6104 {
6105         POLICY_HND *handle = &q_u->handle;
6106         UNISTR2 *value = &q_u->valuename;
6107
6108         NT_PRINTER_INFO_LEVEL *printer = NULL;
6109         NT_PRINTER_PARAM param;
6110         int snum=0;
6111         uint32 status = 0x0;
6112         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
6113         
6114         DEBUG(5,("spoolss_deleteprinterdata\n"));
6115         
6116         if (!Printer) {
6117                 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6118                 return ERROR_INVALID_HANDLE;
6119         }
6120
6121         if (!get_printer_snum(p, handle, &snum))
6122                 return ERROR_INVALID_HANDLE;
6123
6124         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
6125                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6126                           "change denied by existing security descriptor\n"));
6127                 return ERROR_ACCESS_DENIED;
6128         }
6129
6130         status = get_a_printer(&printer, 2, lp_servicename(snum));
6131         if (status != 0x0)
6132                 return ERROR_INVALID_NAME;
6133
6134         ZERO_STRUCTP(&param);
6135         unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
6136
6137         if(!unlink_specific_param_if_exist(printer->info_2, &param))
6138                 status = ERROR_INVALID_PARAMETER;
6139         else
6140                 status = mod_a_printer(*printer, 2);
6141
6142         free_a_printer(&printer, 2);
6143         return status;
6144 }
6145
6146 /****************************************************************************
6147 ****************************************************************************/
6148
6149 uint32 _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
6150 {
6151         POLICY_HND *handle = &q_u->handle;
6152 /*      uint32 level = q_u->level; - notused. */
6153         FORM *form = &q_u->form;
6154         nt_forms_struct tmpForm;
6155
6156         int count=0;
6157         nt_forms_struct *list=NULL;
6158         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6159
6160         DEBUG(5,("spoolss_addform\n"));
6161
6162         if (!Printer) {
6163                 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6164                 return ERROR_INVALID_HANDLE;
6165         }
6166
6167         /* can't add if builtin */
6168         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6169                 return ERROR_INVALID_PARAMETER;
6170         }
6171
6172         count=get_ntforms(&list);
6173         if(!add_a_form(&list, form, &count))
6174                 return ERROR_NOT_ENOUGH_MEMORY;
6175         write_ntforms(&list, count);
6176
6177         safe_free(list);
6178
6179         return 0x0;
6180 }
6181
6182 /****************************************************************************
6183 ****************************************************************************/
6184
6185 uint32 _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
6186 {
6187         POLICY_HND *handle = &q_u->handle;
6188         UNISTR2 *form_name = &q_u->name;
6189         nt_forms_struct tmpForm;
6190         int count=0;
6191         uint32 ret = 0;
6192         nt_forms_struct *list=NULL;
6193         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6194
6195         DEBUG(5,("spoolss_deleteform\n"));
6196
6197         if (!Printer) {
6198                 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6199                 return ERROR_INVALID_HANDLE;
6200         }
6201
6202         /* can't delete if builtin */
6203         if (get_a_builtin_ntform(form_name,&tmpForm)) {
6204                 return ERROR_INVALID_PARAMETER;
6205         }
6206
6207         count = get_ntforms(&list);
6208         if(!delete_a_form(&list, form_name, &count, &ret))
6209                 return ERROR_INVALID_PARAMETER;
6210
6211         safe_free(list);
6212
6213         return ret;
6214 }
6215
6216 /****************************************************************************
6217 ****************************************************************************/
6218
6219 uint32 _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
6220 {
6221         POLICY_HND *handle = &q_u->handle;
6222 /*      UNISTR2 *uni_name = &q_u->name; - notused. */
6223 /*      uint32 level = q_u->level; - notused. */
6224         FORM *form = &q_u->form;
6225         nt_forms_struct tmpForm;
6226
6227         int count=0;
6228         nt_forms_struct *list=NULL;
6229         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6230
6231         DEBUG(5,("spoolss_setform\n"));
6232
6233         if (!Printer) {
6234                 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
6235                 return ERROR_INVALID_HANDLE;
6236         }
6237         /* can't set if builtin */
6238         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
6239                 return ERROR_INVALID_PARAMETER;
6240         }
6241
6242         count=get_ntforms(&list);
6243         update_a_form(&list, form, count);
6244         write_ntforms(&list, count);
6245
6246         safe_free(list);
6247
6248         return 0x0;
6249 }
6250
6251 /****************************************************************************
6252  enumprintprocessors level 1.
6253 ****************************************************************************/
6254 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6255 {
6256         PRINTPROCESSOR_1 *info_1=NULL;
6257         
6258         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
6259                 return ERROR_NOT_ENOUGH_MEMORY;
6260
6261         (*returned) = 0x1;
6262         
6263         init_unistr(&info_1->name, "winprint");
6264
6265         *needed += spoolss_size_printprocessor_info_1(info_1);
6266
6267         if (!alloc_buffer_size(buffer, *needed))
6268                 return ERROR_INSUFFICIENT_BUFFER;
6269
6270         smb_io_printprocessor_info_1("", buffer, info_1, 0);
6271
6272         safe_free(info_1);
6273
6274         if (*needed > offered) {
6275                 *returned=0;
6276                 return ERROR_INSUFFICIENT_BUFFER;
6277         }
6278         else
6279                 return NT_STATUS_NO_PROBLEMO;
6280 }
6281
6282 /****************************************************************************
6283 ****************************************************************************/
6284
6285 uint32 _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
6286 {
6287 /*      UNISTR2 *name = &q_u->name; - notused. */
6288 /*      UNISTR2 *environment = &q_u->environment; - notused. */
6289         uint32 level = q_u->level;
6290     NEW_BUFFER *buffer = NULL;
6291         uint32 offered = q_u->offered;
6292     uint32 *needed = &r_u->needed;
6293         uint32 *returned = &r_u->returned;
6294
6295         /* that's an [in out] buffer */
6296         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6297         buffer = r_u->buffer;
6298
6299         DEBUG(5,("spoolss_enumprintprocessors\n"));
6300
6301         /*
6302          * Enumerate the print processors ...
6303          *
6304          * Just reply with "winprint", to keep NT happy
6305          * and I can use my nice printer checker.
6306          */
6307         
6308         *returned=0;
6309         *needed=0;
6310         
6311         switch (level) {
6312         case 1:
6313                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
6314         default:
6315                 return ERROR_INVALID_LEVEL;
6316         }
6317 }
6318
6319 /****************************************************************************
6320  enumprintprocdatatypes level 1.
6321 ****************************************************************************/
6322 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6323 {
6324         PRINTPROCDATATYPE_1 *info_1=NULL;
6325         
6326         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
6327                 return ERROR_NOT_ENOUGH_MEMORY;
6328
6329         (*returned) = 0x1;
6330         
6331         init_unistr(&info_1->name, "RAW");
6332
6333         *needed += spoolss_size_printprocdatatype_info_1(info_1);
6334
6335         if (!alloc_buffer_size(buffer, *needed))
6336                 return ERROR_INSUFFICIENT_BUFFER;
6337
6338         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
6339
6340         safe_free(info_1);
6341
6342         if (*needed > offered) {
6343                 *returned=0;
6344                 return ERROR_INSUFFICIENT_BUFFER;
6345         }
6346         else
6347                 return NT_STATUS_NO_PROBLEMO;
6348 }
6349
6350 /****************************************************************************
6351 ****************************************************************************/
6352
6353 uint32 _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
6354 {
6355 /*      UNISTR2 *name = &q_u->name; - notused. */
6356 /*      UNISTR2 *processor = &q_u->processor; - notused. */
6357         uint32 level = q_u->level;
6358         NEW_BUFFER *buffer = NULL;
6359         uint32 offered = q_u->offered;
6360         uint32 *needed = &r_u->needed;
6361         uint32 *returned = &r_u->returned;
6362
6363         /* that's an [in out] buffer */
6364         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6365         buffer = r_u->buffer;
6366
6367         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6368         
6369         *returned=0;
6370         *needed=0;
6371         
6372         switch (level) {
6373         case 1:
6374                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
6375         default:
6376                 return ERROR_INVALID_LEVEL;
6377         }
6378 }
6379
6380 /****************************************************************************
6381  enumprintmonitors level 1.
6382 ****************************************************************************/
6383
6384 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6385 {
6386         PRINTMONITOR_1 *info_1=NULL;
6387         
6388         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
6389                 return ERROR_NOT_ENOUGH_MEMORY;
6390
6391         (*returned) = 0x1;
6392         
6393         init_unistr(&info_1->name, "Local Port");
6394
6395         *needed += spoolss_size_printmonitor_info_1(info_1);
6396
6397         if (!alloc_buffer_size(buffer, *needed))
6398                 return ERROR_INSUFFICIENT_BUFFER;
6399
6400         smb_io_printmonitor_info_1("", buffer, info_1, 0);
6401
6402         safe_free(info_1);
6403
6404         if (*needed > offered) {
6405                 *returned=0;
6406                 return ERROR_INSUFFICIENT_BUFFER;
6407         }
6408         else
6409                 return NT_STATUS_NO_PROBLEMO;
6410 }
6411
6412 /****************************************************************************
6413  enumprintmonitors level 2.
6414 ****************************************************************************/
6415 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6416 {
6417         PRINTMONITOR_2 *info_2=NULL;
6418         
6419         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
6420                 return ERROR_NOT_ENOUGH_MEMORY;
6421
6422         (*returned) = 0x1;
6423         
6424         init_unistr(&info_2->name, "Local Port");
6425         init_unistr(&info_2->environment, "Windows NT X86");
6426         init_unistr(&info_2->dll_name, "localmon.dll");
6427
6428         *needed += spoolss_size_printmonitor_info_2(info_2);
6429
6430         if (!alloc_buffer_size(buffer, *needed))
6431                 return ERROR_INSUFFICIENT_BUFFER;
6432
6433         smb_io_printmonitor_info_2("", buffer, info_2, 0);
6434
6435         safe_free(info_2);
6436
6437         if (*needed > offered) {
6438                 *returned=0;
6439                 return ERROR_INSUFFICIENT_BUFFER;
6440         }
6441         else
6442                 return NT_STATUS_NO_PROBLEMO;
6443 }
6444
6445 /****************************************************************************
6446 ****************************************************************************/
6447
6448 uint32 _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
6449 {
6450 /*      UNISTR2 *name = &q_u->name; - notused. */
6451         uint32 level = q_u->level;
6452     NEW_BUFFER *buffer = NULL;
6453         uint32 offered = q_u->offered;
6454     uint32 *needed = &r_u->needed;
6455         uint32 *returned = &r_u->returned;
6456
6457         /* that's an [in out] buffer */
6458         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6459         buffer = r_u->buffer;
6460
6461         DEBUG(5,("spoolss_enumprintmonitors\n"));
6462
6463         /*
6464          * Enumerate the print monitors ...
6465          *
6466          * Just reply with "Local Port", to keep NT happy
6467          * and I can use my nice printer checker.
6468          */
6469         
6470         *returned=0;
6471         *needed=0;
6472         
6473         switch (level) {
6474         case 1:
6475                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
6476         case 2:
6477                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
6478         default:
6479                 return ERROR_INVALID_LEVEL;
6480         }
6481 }
6482
6483 /****************************************************************************
6484 ****************************************************************************/
6485 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6486 {
6487         int i=0;
6488         BOOL found=False;
6489         JOB_INFO_1 *info_1=NULL;
6490
6491         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
6492
6493         if (info_1 == NULL) {
6494                 safe_free(queue);
6495                 return ERROR_NOT_ENOUGH_MEMORY;
6496         }
6497                 
6498         for (i=0; i<count && found==False; i++) {
6499                 if (queue[i].job==(int)jobid)
6500                         found=True;
6501         }
6502         
6503         if (found==False) {
6504                 safe_free(queue);
6505                 safe_free(info_1);
6506                 /* I shoud reply something else ... I can't find the good one */
6507                 return NT_STATUS_NO_PROBLEMO;
6508         }
6509         
6510         fill_job_info_1(info_1, &(queue[i-1]), i, snum);
6511         
6512         safe_free(queue);
6513         
6514         *needed += spoolss_size_job_info_1(info_1);
6515
6516         if (!alloc_buffer_size(buffer, *needed)) {
6517                 safe_free(info_1);
6518                 return ERROR_INSUFFICIENT_BUFFER;
6519         }
6520
6521         smb_io_job_info_1("", buffer, info_1, 0);
6522
6523         safe_free(info_1);
6524
6525         if (*needed > offered)
6526                 return ERROR_INSUFFICIENT_BUFFER;
6527         else
6528                 return NT_STATUS_NO_PROBLEMO;
6529 }
6530
6531
6532 /****************************************************************************
6533 ****************************************************************************/
6534 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
6535 {
6536         int i=0;
6537         BOOL found=False;
6538         JOB_INFO_2 *info_2;
6539         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6540
6541         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
6542
6543         ZERO_STRUCTP(info_2);
6544
6545         if (info_2 == NULL) {
6546                 safe_free(queue);
6547                 return ERROR_NOT_ENOUGH_MEMORY;
6548         }
6549
6550         for (i=0; i<count && found==False; i++) {
6551                 if (queue[i].job==(int)jobid)
6552                         found=True;
6553         }
6554         
6555         if (found==False) {
6556                 safe_free(queue);
6557                 safe_free(info_2);
6558                 /* I shoud reply something else ... I can't find the good one */
6559                 return NT_STATUS_NO_PROBLEMO;
6560         }
6561         
6562         if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0) {
6563                 safe_free(queue);
6564                 return ERROR_NOT_ENOUGH_MEMORY;
6565         }
6566
6567         fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter);
6568         
6569         free_a_printer(&ntprinter, 2);
6570         safe_free(queue);
6571         
6572         *needed += spoolss_size_job_info_2(info_2);
6573
6574         if (!alloc_buffer_size(buffer, *needed)) {
6575                 safe_free(info_2);
6576                 return ERROR_INSUFFICIENT_BUFFER;
6577         }
6578
6579         smb_io_job_info_2("", buffer, info_2, 0);
6580
6581         free_job_info_2(info_2);
6582         free(info_2);
6583
6584         if (*needed > offered)
6585                 return ERROR_INSUFFICIENT_BUFFER;
6586         else
6587                 return NT_STATUS_NO_PROBLEMO;
6588 }
6589
6590 /****************************************************************************
6591 ****************************************************************************/
6592
6593 uint32 _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
6594 {
6595         POLICY_HND *handle = &q_u->handle;
6596         uint32 jobid = q_u->jobid;
6597         uint32 level = q_u->level;
6598         NEW_BUFFER *buffer = NULL;
6599         uint32 offered = q_u->offered;
6600         uint32 *needed = &r_u->needed;
6601
6602         int snum;
6603         int count;
6604         print_queue_struct *queue=NULL;
6605         print_status_struct prt_status;
6606
6607         /* that's an [in out] buffer */
6608         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6609         buffer = r_u->buffer;
6610
6611         DEBUG(5,("spoolss_getjob\n"));
6612         
6613         memset(&prt_status, 0, sizeof(prt_status));
6614
6615         *needed=0;
6616         
6617         if (!get_printer_snum(p, handle, &snum))
6618                 return ERROR_INVALID_HANDLE;
6619         
6620         count = print_queue_status(snum, &queue, &prt_status);
6621         
6622         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6623                      count, prt_status.status, prt_status.message));
6624                 
6625         switch (level) {
6626         case 1:
6627                 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
6628         case 2:
6629                 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
6630         default:
6631                 safe_free(queue);
6632                 return ERROR_INVALID_LEVEL;
6633         }
6634 }