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