a fairly big change in spoolss.
[samba.git] / source3 / printing / nt_printing.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) Jean François Micouleau      1998-2000.
7  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 extern int DEBUGLEVEL;
26
27 static TDB_CONTEXT *tdb; /* used for driver files */
28
29 #define FORMS_PREFIX "FORMS/"
30 #define DRIVERS_PREFIX "DRIVERS/"
31 #define PRINTERS_PREFIX "PRINTERS/"
32
33 #define DATABASE_VERSION 1
34
35 /****************************************************************************
36 open the NT printing tdb
37 ****************************************************************************/
38 int nt_printing_init(void)
39 {
40         static pid_t local_pid;
41
42         if (tdb && local_pid == sys_getpid()) return True;
43         tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
44         if (!tdb) {
45                 DEBUG(0,("Failed to open nt drivers database\n"));
46         }
47         local_pid = sys_getpid();
48
49         /* handle a Samba upgrade */
50         tdb_writelock(tdb);
51         if (tdb_fetch_int(tdb, "INFO/version") != DATABASE_VERSION) {
52                 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
53                 tdb_store_int(tdb, "INFO/version", DATABASE_VERSION);
54         }
55         tdb_writeunlock(tdb);
56
57         return True;
58 }
59
60   
61 /****************************************************************************
62 get a form struct list
63 ****************************************************************************/
64 int get_ntforms(nt_forms_struct **list)
65 {
66         TDB_DATA kbuf, dbuf;
67         nt_forms_struct form;
68         int ret;
69         int n = 0;
70
71         for (kbuf = tdb_firstkey(tdb); 
72              kbuf.dptr; 
73              free(kbuf.dptr), kbuf = tdb_nextkey(tdb, kbuf)) {
74                 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
75                 
76                 dbuf = tdb_fetch(tdb, kbuf);
77                 if (!dbuf.dptr) continue;
78
79                 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
80                 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddddddd",
81                                  &form.flag, &form.width, &form.length, &form.left,
82                                  &form.top, &form.right, &form.bottom);
83                 free(dbuf.dptr);
84                 if (ret != dbuf.dsize) continue;
85
86                 *list = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
87                 (*list)[n] = form;
88                 n++;
89         }
90
91         return n;
92 }
93
94 /****************************************************************************
95 write a form struct list
96 ****************************************************************************/
97 int write_ntforms(nt_forms_struct **list, int number)
98 {
99         pstring buf, key;
100         int len;
101         TDB_DATA kbuf,dbuf;
102         int i;
103
104         for (i=0;i<number;i++) {
105                 len = tdb_pack(buf, sizeof(buf), "ddddddd", 
106                                (*list)[i].flag, (*list)[i].width, (*list)[i].length,
107                                (*list)[i].left, (*list)[i].top, (*list)[i].right, 
108                                (*list)[i].bottom);
109                 if (len > sizeof(buf)) break;
110                 slprintf(key, sizeof(key), "%s/%s", FORMS_PREFIX, (*list)[i].name);
111                 kbuf.dsize = strlen(key)+1;
112                 kbuf.dptr = key;
113                 dbuf.dsize = len;
114                 dbuf.dptr = buf;
115                 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
116        }
117
118        return i;
119 }
120
121 /****************************************************************************
122 add a form struct at the end of the list
123 ****************************************************************************/
124 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
125 {
126         int n=0;
127         BOOL update;
128         fstring form_name;
129
130         /* 
131          * NT tries to add forms even when 
132          * they are already in the base
133          * only update the values if already present
134          */
135
136         update=False;
137         
138         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
139         for (n=0; n<*count && update==False; n++)
140         {
141                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
142                 {
143                         DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
144                         update=True;
145                 }
146         }
147
148         if (update==False)
149         {
150                 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
151                         return False;
152                 unistr2_to_ascii((*list)[n].name, &(form->name), sizeof((*list)[n].name)-1);
153                 (*count)++;
154         }
155         
156         (*list)[n].flag=form->flags;
157         (*list)[n].width=form->size_x;
158         (*list)[n].length=form->size_y;
159         (*list)[n].left=form->left;
160         (*list)[n].top=form->top;
161         (*list)[n].right=form->right;
162         (*list)[n].bottom=form->bottom;
163
164         return True;
165 }
166
167 /****************************************************************************
168 update a form struct 
169 ****************************************************************************/
170 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
171 {
172         int n=0;
173         fstring form_name;
174         unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
175
176         DEBUG(106, ("[%s]\n", form_name));
177         for (n=0; n<count; n++)
178         {
179                 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
180                 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
181                         break;
182         }
183
184         if (n==count) return;
185
186         (*list)[n].flag=form->flags;
187         (*list)[n].width=form->size_x;
188         (*list)[n].length=form->size_y;
189         (*list)[n].left=form->left;
190         (*list)[n].top=form->top;
191         (*list)[n].right=form->right;
192         (*list)[n].bottom=form->bottom;
193 }
194  
195 /****************************************************************************
196 get the nt drivers list
197
198 traverse the database and look-up the matching names
199 ****************************************************************************/
200 int get_ntdrivers(fstring **list, char *architecture)
201 {
202         int total=0;
203         fstring short_archi;
204         pstring key;
205         TDB_DATA kbuf;
206
207         get_short_archi(short_archi, architecture);
208         slprintf(key, sizeof(key), "%s/%s/", DRIVERS_PREFIX, short_archi);
209
210         for (kbuf = tdb_firstkey(tdb); 
211              kbuf.dptr; 
212              free(kbuf.dptr), kbuf = tdb_nextkey(tdb, kbuf)) {
213                 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
214                 
215                 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
216                         return -1;
217
218                 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
219                 total++;
220         }
221
222         return(total);
223 }
224
225 /****************************************************************************
226 function to do the mapping between the long architecture name and
227 the short one.
228 ****************************************************************************/
229 void get_short_archi(char *short_archi, char *long_archi)
230 {
231         struct table {
232                 char *long_archi;
233                 char *short_archi;
234         };
235         
236         struct table archi_table[]=
237         {
238                 {"Windows 4.0",          "WIN40"    },
239                 {"Windows NT x86",       "W32X86"   },
240                 {"Windows NT R4000",     "W32mips"  },
241                 {"Windows NT Alpha_AXP", "W32alpha" },
242                 {"Windows NT PowerPC",   "W32ppc"   },
243                 {NULL,                   ""         }
244         };
245         
246         int i=-1;
247
248         DEBUG(107,("Getting architecture dependant directory\n"));
249         do {
250                 i++;
251         } while ( (archi_table[i].long_archi!=NULL ) && strncmp(long_archi, archi_table[i].long_archi, strlen(long_archi)) );
252
253         if (archi_table[i].long_archi==NULL)
254         {
255                 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
256         }
257         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
258
259         DEBUGADD(108,("index: [%d]\n", i));
260         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
261         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
262 }
263
264 /****************************************************************************
265 ****************************************************************************/
266 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
267 {
268         int len, buflen;
269         fstring architecture;
270         pstring key;
271         char *buf;
272         int i, ret;
273         TDB_DATA kbuf, dbuf;
274
275         get_short_archi(architecture, driver->environment);
276         slprintf(key, sizeof(key), "%s/%s/%s", DRIVERS_PREFIX, architecture, driver->name);
277
278         /*
279          * cversion must be 2.
280          * when adding a printer ON the SERVER
281          * rpcAddPrinterDriver defines it to zero
282          * which is wrong !!!
283          *
284          * JFM, 4/14/99
285          */
286         driver->cversion=2;
287         
288         buf = NULL;
289         len = buflen = 0;
290
291  again:
292         len = 0;
293         len += tdb_pack(buf+len, buflen-len, "dffffffff", 
294                         driver->cversion,
295                         driver->name,
296                         driver->environment,
297                         driver->driverpath,
298                         driver->datafile,
299                         driver->configfile,
300                         driver->helpfile,
301                         driver->monitorname,
302                         driver->defaultdatatype);
303         
304         if (driver->dependentfiles) {
305                 for (i=0; *driver->dependentfiles[i]; i++) {
306                         len += tdb_pack(buf+len, buflen-len, "f", 
307                                         driver->dependentfiles[i]);
308                 }
309         }
310
311         if (len != buflen) {
312                 buf = (char *)Realloc(buf, len);
313                 buflen = len;
314                 goto again;
315         }
316
317
318         kbuf.dptr = key;
319         kbuf.dsize = strlen(key)+1;
320         dbuf.dptr = buf;
321         dbuf.dsize = len;
322         
323         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
324
325         free(buf);
326         return ret;
327 }
328
329 /****************************************************************************
330 ****************************************************************************/
331 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
332 {
333         NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
334
335         info3.cversion = driver->version;
336         fstrcpy(info3.environment,driver->environment);
337         fstrcpy(info3.driverpath,driver->driverpath);
338         fstrcpy(info3.datafile,driver->datafile);
339         fstrcpy(info3.configfile,driver->configfile);
340         fstrcpy(info3.helpfile,driver->helpfile);
341         fstrcpy(info3.monitorname,driver->monitorname);
342         fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
343         info3.dependentfiles = driver->dependentfiles;
344
345         return add_a_printer_driver_3(&info3);
346 }
347
348
349 /****************************************************************************
350 ****************************************************************************/
351 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
352 {
353         NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
354         int snum;
355
356         ZERO_STRUCT(info);
357
358         snum = lp_servicenumber(in_prt);
359
360         fstrcpy(info.name, lp_printerdriver(snum));
361         fstrcpy(info.defaultdatatype, "RAW");
362         
363         info.dependentfiles=(fstring *)malloc(sizeof(fstring));
364         fstrcpy(info.dependentfiles[0], "");
365
366         *info_ptr = memdup(&info, sizeof(info));
367         
368         return 0;       
369 }
370
371 /****************************************************************************
372 ****************************************************************************/
373 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
374 {
375         NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
376         TDB_DATA kbuf, dbuf;
377         fstring architecture;
378         int len = 0;
379         int i;
380         pstring key;
381
382         ZERO_STRUCT(driver);
383
384         get_short_archi(architecture, in_arch);
385         slprintf(key, sizeof(key), "%s/%s/%s", DRIVERS_PREFIX, architecture, in_prt);
386
387         kbuf.dptr = key;
388         kbuf.dsize = strlen(key)+1;
389         
390         dbuf = tdb_fetch(tdb, kbuf);
391         if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
392
393         len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", 
394                           &driver.cversion,
395                           driver.name,
396                           driver.environment,
397                           driver.driverpath,
398                           driver.datafile,
399                           driver.configfile,
400                           driver.helpfile,
401                           driver.monitorname,
402                           driver.defaultdatatype);
403
404         i=0;
405         while (len < dbuf.dsize) {
406                 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
407                                                          sizeof(fstring)*(i+2));
408                 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", 
409                                   driver.dependentfiles[i]);
410                 i++;
411         }
412         fstrcpy(driver.dependentfiles[i], "");
413
414         free(dbuf.dptr);
415         return 0;
416 }
417
418 /****************************************************************************
419 debugging function, dump at level 6 the struct in the logs
420 ****************************************************************************/
421 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
422 {
423         uint32 success;
424         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
425         int i;
426         
427         DEBUG(106,("Dumping printer driver at level [%d]\n", level));
428         
429         switch (level)
430         {
431                 case 3: 
432                 {
433                         if (driver.info_3 == NULL)
434                                 success=5;
435                         else {
436                                 info3=driver.info_3;
437                         
438                                 DEBUGADD(106,("version:[%d]\n",         info3->cversion));
439                                 DEBUGADD(106,("name:[%s]\n",            info3->name));
440                                 DEBUGADD(106,("environment:[%s]\n",     info3->environment));
441                                 DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
442                                 DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
443                                 DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
444                                 DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
445                                 DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
446                                 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
447                                 
448                                 for (i=0; *info3->dependentfiles[i]; i++) {
449                                         DEBUGADD(106,("dependentfile:[%s]\n", 
450                                                       info3->dependentfiles[i]));
451                                 }
452                                 success=0;
453                         }
454                         break;
455                 }
456                 default:
457                         DEBUGADD(1,("Level not implemented\n"));
458                         success=1;
459                         break;
460         }
461         
462         return (success);
463 }
464
465 /****************************************************************************
466 ****************************************************************************/
467 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
468 {
469         int len = 0;
470
471         len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
472
473         if (!nt_devmode) return len;
474
475         len += tdb_pack(buf+len, buflen-len, "fddddddddddddddddddddddp",
476                        nt_devmode->formname,
477                        nt_devmode->specversion,
478                        nt_devmode->driverversion,
479                        nt_devmode->size,
480                        nt_devmode->driverextra,
481                        nt_devmode->fields,
482                        nt_devmode->orientation,
483                        nt_devmode->papersize,
484                        nt_devmode->paperlength,
485                        nt_devmode->paperwidth,
486                        nt_devmode->scale,
487                        nt_devmode->copies,
488                        nt_devmode->defaultsource,
489                        nt_devmode->printquality,
490                        nt_devmode->color,
491                        nt_devmode->duplex,
492                        nt_devmode->yresolution,
493                        nt_devmode->ttoption,
494                        nt_devmode->collate,
495                        nt_devmode->icmmethod,
496                        nt_devmode->icmintent,
497                        nt_devmode->mediatype,
498                        nt_devmode->dithertype,
499                        nt_devmode->private);
500         
501         if (nt_devmode->private) {
502                 len += tdb_pack(buf+len, buflen-len, "B",
503                                 nt_devmode->driverextra,
504                                 nt_devmode->private);
505         }
506
507         return len;
508 }
509
510 /****************************************************************************
511 ****************************************************************************/
512 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
513 {
514         int len = 0;
515
516         while (param != NULL) {
517                 len += tdb_pack(buf+len, buflen-len, "pfdB",
518                                 param,
519                                 param->value, 
520                                 param->type, 
521                                 param->data_len,
522                                 param->data);
523                 param=param->next;      
524         }
525
526         len += tdb_pack(buf+len, buflen-len, "p", param);
527
528         return len;
529 }
530
531
532 /****************************************************************************
533 delete a printer - this just deletes the printer info file, any open
534 handles are not affected
535 ****************************************************************************/
536 uint32 del_a_printer(char *portname)
537 {
538         pstring key;
539         TDB_DATA kbuf;
540
541         slprintf(key, sizeof(key), "%s/%s",
542                  PRINTERS_PREFIX, portname);
543
544         kbuf.dptr=key;
545         kbuf.dsize=strlen(key)+1;
546
547         tdb_delete(tdb, kbuf);
548         return 0;
549 }
550
551 /****************************************************************************
552 ****************************************************************************/
553 static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
554 {
555         pstring key;
556         char *buf;
557         int buflen, len, ret;
558         TDB_DATA kbuf, dbuf;
559         
560         /* 
561          * in addprinter: no servername and the printer is the name
562          * in setprinter: servername is \\server
563          *                and printer is \\server\\printer
564          *
565          * Samba manages only local printers.
566          * we currently don't support things like path=\\other_server\printer
567          */
568         if (info->servername[0]!='\0')
569         {
570                 trim_string(info->printername, info->servername, NULL);
571                 trim_string(info->printername, "\\", NULL);
572                 info->servername[0]='\0';
573         }
574
575         /*
576          * JFM: one day I'll forget.
577          * below that's info->portname because that's the SAMBA sharename
578          * and I made NT 'thinks' it's the portname
579          * the info->sharename is the thing you can name when you add a printer
580          * that's the short-name when you create shared printer for 95/98
581          * So I've made a limitation in SAMBA: you can only have 1 printer model
582          * behind a SAMBA share.
583          */
584
585
586         buf = NULL;
587         buflen = 0;
588
589  again: 
590         len = 0;
591         len += tdb_pack(buf+len, buflen-len, "dddddddddddffffffffff",
592                         info->attributes,
593                         info->priority,
594                         info->default_priority,
595                         info->starttime,
596                         info->untiltime,
597                         info->status,
598                         info->cjobs,
599                         info->averageppm,
600                         info->changeid,
601                         info->c_setprinter,
602                         info->setuptime,
603                         info->servername,
604                         info->printername,
605                         info->sharename,
606                         info->portname,
607                         info->drivername,
608                         info->location,
609                         info->sepfile,
610                         info->printprocessor,
611                         info->datatype,
612                         info->parameters);
613
614         len += pack_devicemode(info->devmode, buf+len, buflen-len);
615         len += pack_specifics(info->specific, buf+len, buflen-len);
616
617         if (buflen != len) {
618                 buf = (char *)Realloc(buf, len);
619                 buflen = len;
620                 goto again;
621         }
622         
623
624         slprintf(key, sizeof(key), "%s/%s",
625                  PRINTERS_PREFIX, info->portname);
626
627         kbuf.dptr = key;
628         kbuf.dsize = strlen(key)+1;
629         dbuf.dptr = buf;
630         dbuf.dsize = len;
631
632         ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
633
634         free(buf);
635
636         return ret;
637 }
638
639
640 /****************************************************************************
641 ****************************************************************************/
642 BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
643 {
644         NT_PRINTER_PARAM *current;
645         
646         DEBUG(108,("add_a_specific_param\n"));  
647
648         param->next=NULL;
649         
650         if (info_2->specific == NULL)
651         {
652                 info_2->specific=param;
653         }
654         else
655         {
656                 current=info_2->specific;               
657                 while (current->next != NULL) {
658                         current=current->next;
659                 }               
660                 current->next=param;
661         }
662         return (True);
663 }
664
665 /****************************************************************************
666 ****************************************************************************/
667 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
668 {
669         NT_PRINTER_PARAM *current;
670         NT_PRINTER_PARAM *previous;
671         
672         current=info_2->specific;
673         previous=current;
674         
675         if (current==NULL) return (False);
676         
677         if ( !strcmp(current->value, param->value) && 
678             (strlen(current->value)==strlen(param->value)) )
679         {
680                 DEBUG(109,("deleting first value\n"));
681                 info_2->specific=current->next;
682                 safe_free(current->data);
683                 free(current);
684                 DEBUG(109,("deleted first value\n"));
685                 return (True);
686         }
687
688         current=previous->next;
689                 
690         while ( current!=NULL )
691         {
692                 if (!strcmp(current->value, param->value) &&
693                     strlen(current->value)==strlen(param->value) )
694                 {
695                         DEBUG(109,("deleting current value\n"));
696                         previous->next=current->next;
697                         free(current);
698                         DEBUG(109,("deleted current value\n"));
699                         return(True);
700                 }
701                 
702                 previous=previous->next;
703                 current=current->next;
704         }
705         return (False);
706 }
707
708 /****************************************************************************
709  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
710 ****************************************************************************/
711 static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
712 {
713         NT_PRINTER_PARAM *param = *param_ptr;
714
715         if(param == NULL)
716                 return;
717
718         DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
719
720         if(param->data)
721                 free(param->data);
722
723         free(param);
724         *param_ptr = NULL;
725 }
726
727 /****************************************************************************
728  Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
729 ****************************************************************************/
730 static void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
731 {
732         NT_DEVICEMODE *nt_devmode = *devmode_ptr;
733
734         if(nt_devmode == NULL)
735                 return;
736
737         DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
738
739         if(nt_devmode->private)
740                 free(nt_devmode->private);
741
742         free(nt_devmode);
743         *devmode_ptr = NULL;
744 }
745
746 /****************************************************************************
747  Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
748 ****************************************************************************/
749 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
750 {
751         NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
752         NT_PRINTER_PARAM *param_ptr;
753
754         if(info == NULL)
755                 return;
756
757         DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
758
759         free_nt_devicemode(&info->devmode);
760
761         for(param_ptr = info->specific; param_ptr; ) {
762                 NT_PRINTER_PARAM *tofree = param_ptr;
763
764                 param_ptr = param_ptr->next;
765                 free_nt_printer_param(&tofree);
766         }
767
768         free(info);
769         *info_ptr = NULL;
770 }
771
772
773 /****************************************************************************
774 ****************************************************************************/
775 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
776 {
777         int len = 0;
778         NT_DEVICEMODE devmode;
779
780         ZERO_STRUCT(devmode);
781
782         len += tdb_unpack(buf+len, buflen-len, "p", *nt_devmode);
783
784         if (!*nt_devmode) return len;
785
786         len += tdb_unpack(buf+len, buflen-len, "fddddddddddddddddddddddp",
787                        devmode.formname,
788                        &devmode.specversion,
789                        &devmode.driverversion,
790                        &devmode.size,
791                        &devmode.driverextra,
792                        &devmode.fields,
793                        &devmode.orientation,
794                        &devmode.papersize,
795                        &devmode.paperlength,
796                        &devmode.paperwidth,
797                        &devmode.scale,
798                        &devmode.copies,
799                        &devmode.defaultsource,
800                        &devmode.printquality,
801                        &devmode.color,
802                        &devmode.duplex,
803                        &devmode.yresolution,
804                        &devmode.ttoption,
805                        &devmode.collate,
806                        &devmode.icmmethod,
807                        &devmode.icmintent,
808                        &devmode.mediatype,
809                        &devmode.dithertype,
810                        &devmode.private);
811         
812         if (devmode.private) {
813                 devmode.private = (uint8 *)malloc(devmode.driverextra);
814                 if (!devmode.private) return 2;
815                 len += tdb_unpack(buf+len, buflen-len, "B",
816                                   devmode.driverextra,
817                                   devmode.private);
818         }
819
820         *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
821
822         return len;
823 }
824
825 /****************************************************************************
826 ****************************************************************************/
827 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
828 {
829         int len = 0;
830         NT_PRINTER_PARAM param, *p;
831
832         *list = NULL;
833
834         while (1) {
835                 len += tdb_unpack(buf+len, buflen-len, "p", p);
836                 if (!p) break;
837
838                 len += tdb_unpack(buf+len, buflen-len, "fdB",
839                                   param.value, 
840                                   &param.type, 
841                                   &param.data_len,
842                                   &param.data);
843                 param.next = *list;
844                 *list = memdup(&param, sizeof(param));
845         }
846
847         return len;
848 }
849
850
851 /****************************************************************************
852 get a default printer info 2 struct
853 ****************************************************************************/
854 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
855 {
856         extern pstring global_myname;
857         int snum;
858         NT_PRINTER_INFO_LEVEL_2 info;
859         NT_DEVICEMODE devmode;
860
861         ZERO_STRUCT(info);
862         ZERO_STRUCT(devmode);
863
864         init_devicemode(&devmode);
865         
866         snum = lp_servicenumber(sharename);
867
868         fstrcpy(info.servername, global_myname);
869         fstrcpy(info.printername, sharename);
870         fstrcpy(info.portname, sharename);
871         fstrcpy(info.drivername, lp_printerdriver(snum));
872         fstrcpy(info.printprocessor, "winprint");
873         fstrcpy(info.datatype, "RAW");
874
875         info.devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
876
877         *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
878         if (! *info_ptr) return 2;
879
880         return (0);     
881 }
882
883 /****************************************************************************
884 ****************************************************************************/
885 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
886 {
887         pstring key;
888         NT_PRINTER_INFO_LEVEL_2 info;
889         int len = 0;
890         TDB_DATA kbuf, dbuf;
891                 
892         ZERO_STRUCT(info);
893
894         slprintf(key, sizeof(key), "%s/%s",
895                  PRINTERS_PREFIX, sharename);
896
897         kbuf.dptr = key;
898         kbuf.dsize = strlen(key)+1;
899
900         dbuf = tdb_fetch(tdb, kbuf);
901         if (!dbuf.dptr) return get_a_printer_2_default(info_ptr, sharename);
902
903         len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddffffffffff",
904                         &info.attributes,
905                         &info.priority,
906                         &info.default_priority,
907                         &info.starttime,
908                         &info.untiltime,
909                         &info.status,
910                         &info.cjobs,
911                         &info.averageppm,
912                         &info.changeid,
913                         &info.c_setprinter,
914                         &info.setuptime,
915                         info.servername,
916                         info.printername,
917                         info.sharename,
918                         info.portname,
919                         info.drivername,
920                         info.location,
921                         info.sepfile,
922                         info.printprocessor,
923                         info.datatype,
924                         info.parameters);
925
926         len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
927         len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
928
929         *info_ptr=memdup(&info, sizeof(info));
930         
931         return 0;       
932 }
933
934 /****************************************************************************
935 debugging function, dump at level 6 the struct in the logs
936 ****************************************************************************/
937 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
938 {
939         uint32 success;
940         NT_PRINTER_INFO_LEVEL_2 *info2;
941         
942         DEBUG(106,("Dumping printer at level [%d]\n", level));
943         
944         switch (level)
945         {
946                 case 2: 
947                 {
948                         if (printer.info_2 == NULL)
949                                 success=5;
950                         else
951                         {
952                                 info2=printer.info_2;
953                         
954                                 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
955                                 DEBUGADD(106,("priority:[%d]\n", info2->priority));
956                                 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
957                                 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
958                                 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
959                                 DEBUGADD(106,("status:[%d]\n", info2->status));
960                                 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
961                                 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
962                                 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
963                                 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
964                                 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
965
966                                 DEBUGADD(106,("servername:[%s]\n", info2->servername));
967                                 DEBUGADD(106,("printername:[%s]\n", info2->printername));
968                                 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
969                                 DEBUGADD(106,("portname:[%s]\n", info2->portname));
970                                 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
971                                 DEBUGADD(106,("location:[%s]\n", info2->location));
972                                 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
973                                 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
974                                 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
975                                 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
976                                 success=0;
977                         }
978                         break;
979                 }
980                 default:
981                         DEBUGADD(1,("Level not implemented\n"));
982                         success=1;
983                         break;
984         }
985         
986         return (success);
987 }
988
989 /*
990  * The function below are the high level ones.
991  * only those ones must be called from the spoolss code.
992  * JFM.
993  */
994
995
996 /****************************************************************************
997 ****************************************************************************/
998 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
999 {
1000         uint32 success;
1001         
1002         dump_a_printer(printer, level); 
1003         
1004         switch (level)
1005         {
1006                 case 2: 
1007                 {
1008                         success=add_a_printer_2(printer.info_2);
1009                         break;
1010                 }
1011                 default:
1012                         success=1;
1013                         break;
1014         }
1015         
1016         return (success);
1017 }
1018
1019 /****************************************************************************
1020 ****************************************************************************/
1021 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level, fstring sharename)
1022 {
1023         uint32 success;
1024         
1025         DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1026
1027         switch (level)
1028         {
1029                 case 2: 
1030                 {
1031                         printer->info_2=NULL;
1032                         success=get_a_printer_2(&(printer->info_2), sharename);
1033                         break;
1034                 }
1035                 default:
1036                         success=1;
1037                         break;
1038         }
1039         
1040         dump_a_printer(*printer, level);
1041
1042         DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1043
1044         return (success);
1045 }
1046
1047 /****************************************************************************
1048 ****************************************************************************/
1049 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1050 {
1051         uint32 success;
1052         DEBUG(104,("freeing a printer at level [%d]\n", level));
1053         
1054         switch (level)
1055         {
1056                 case 2: 
1057                 {
1058                         if (printer.info_2 != NULL)
1059                         {
1060                                 free_nt_printer_info_level_2(&printer.info_2);
1061                                 success=0;
1062                         }
1063                         else
1064                         {
1065                                 success=4;
1066                         }
1067                         break;
1068                 }
1069                 default:
1070                         success=1;
1071                         break;
1072         }
1073         return (success);
1074 }
1075
1076 /****************************************************************************
1077 ****************************************************************************/
1078 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1079 {
1080         uint32 success;
1081         DEBUG(104,("adding a printer at level [%d]\n", level));
1082         dump_a_printer_driver(driver, level);
1083         
1084         switch (level)
1085         {
1086                 case 3: 
1087                 {
1088                         success=add_a_printer_driver_3(driver.info_3);
1089                         break;
1090                 }
1091
1092                 case 6: 
1093                 {
1094                         success=add_a_printer_driver_6(driver.info_6);
1095                         break;
1096                 }
1097                 default:
1098                         success=1;
1099                         break;
1100         }
1101         
1102         return (success);
1103 }
1104 /****************************************************************************
1105 ****************************************************************************/
1106 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, 
1107                             fstring printername, fstring architecture)
1108 {
1109         uint32 success;
1110         
1111         switch (level)
1112         {
1113                 case 3: 
1114                 {
1115                         success=get_a_printer_driver_3(&(driver->info_3), 
1116                                                        printername,
1117                                                        architecture);
1118                         break;
1119                 }
1120                 default:
1121                         success=1;
1122                         break;
1123         }
1124         
1125         if (success == 0) dump_a_printer_driver(*driver, level);
1126         return (success);
1127 }
1128
1129 /****************************************************************************
1130 ****************************************************************************/
1131 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1132 {
1133         uint32 success;
1134         NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1135         
1136         switch (level)
1137         {
1138                 case 3: 
1139                 {
1140                         if (driver.info_3 != NULL)
1141                         {
1142                                 info3=driver.info_3;
1143                                 if (info3->dependentfiles)
1144                                         free(info3->dependentfiles);
1145                                 free(info3);
1146                                 ZERO_STRUCTP(info3);
1147                                 success=0;
1148                         }
1149                         else
1150                         {
1151                                 success=4;
1152                         }
1153                         break;
1154                 }
1155                 default:
1156                         success=1;
1157                         break;
1158         }
1159         return (success);
1160 }
1161
1162 /****************************************************************************
1163 ****************************************************************************/
1164 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
1165                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
1166 {
1167         /* right now that's enough ! */ 
1168         NT_PRINTER_PARAM *param;
1169         int i=0;
1170         
1171         param=printer.info_2->specific;
1172         
1173         while (param != NULL && i <= param_index)
1174         {
1175                 param=param->next;
1176                 i++;
1177         }
1178         
1179         if (param == NULL)
1180                 return False;
1181
1182         /* exited because it exist */
1183         *type=param->type;              
1184         StrnCpy(value, param->value, sizeof(fstring)-1);
1185         *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1186         if(*data == NULL)
1187                 return False;
1188         memcpy(*data, param->data, param->data_len);
1189         *len=param->data_len;
1190         return True;
1191 }
1192
1193 /****************************************************************************
1194 ****************************************************************************/
1195 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, 
1196                         fstring value, uint8 **data, uint32 *type, uint32 *len)
1197 {
1198         /* right now that's enough ! */ 
1199         NT_PRINTER_PARAM *param;
1200         
1201         DEBUG(105, ("get_specific_param\n"));
1202         
1203         param=printer.info_2->specific;
1204                 
1205         while (param != NULL)
1206         {
1207                 if ( !strcmp(value, param->value) 
1208                     && strlen(value)==strlen(param->value))
1209                         break;
1210                         
1211                 param=param->next;
1212         }
1213         
1214         DEBUG(106, ("found one param\n"));
1215         if (param != NULL)
1216         {
1217                 /* exited because it exist */
1218                 *type=param->type;      
1219                 
1220                 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
1221                 if(*data == NULL)
1222                         return False;
1223                 memcpy(*data, param->data, param->data_len);
1224                 *len=param->data_len;
1225
1226                 DEBUG(106, ("exit of get_specific_param:true\n"));
1227                 return (True);
1228         }
1229         DEBUG(106, ("exit of get_specific_param:false\n"));
1230         return (False);
1231 }
1232
1233 /****************************************************************************
1234 ****************************************************************************/
1235 void init_devicemode(NT_DEVICEMODE *nt_devmode)
1236 {
1237 /*
1238  * should I init this ones ???
1239         nt_devmode->devicename
1240 */
1241         fstrcpy(nt_devmode->formname, "A4");
1242
1243         nt_devmode->specversion      = 0x0401;
1244         nt_devmode->driverversion    = 0x0400;
1245         nt_devmode->size             = 0x00DC;
1246         nt_devmode->driverextra      = 0x0000;
1247         nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY | 
1248                                        DEFAULTSOURCE | COPIES | SCALE | 
1249                                        PAPERSIZE | ORIENTATION;
1250         nt_devmode->orientation      = 1;
1251         nt_devmode->papersize        = PAPER_A4;
1252         nt_devmode->paperlength      = 0;
1253         nt_devmode->paperwidth       = 0;
1254         nt_devmode->scale            = 0x64;
1255         nt_devmode->copies           = 01;
1256         nt_devmode->defaultsource    = BIN_FORMSOURCE;
1257         nt_devmode->printquality     = 0x0258;
1258         nt_devmode->color            = COLOR_MONOCHROME;
1259         nt_devmode->duplex           = DUP_SIMPLEX;
1260         nt_devmode->yresolution      = 0;
1261         nt_devmode->ttoption         = TT_SUBDEV;
1262         nt_devmode->collate          = COLLATE_FALSE;
1263         nt_devmode->icmmethod        = 0;
1264         nt_devmode->icmintent        = 0;
1265         nt_devmode->mediatype        = 0;
1266         nt_devmode->dithertype       = 0;
1267
1268         /* non utilisés par un driver d'imprimante */
1269         nt_devmode->logpixels        = 0;
1270         nt_devmode->bitsperpel       = 0;
1271         nt_devmode->pelswidth        = 0;
1272         nt_devmode->pelsheight       = 0;
1273         nt_devmode->displayflags     = 0;
1274         nt_devmode->displayfrequency = 0;
1275         nt_devmode->reserved1        = 0;
1276         nt_devmode->reserved2        = 0;
1277         nt_devmode->panningwidth     = 0;
1278         nt_devmode->panningheight    = 0;
1279         
1280         nt_devmode->private=NULL;
1281 }
1282
1283
1284 /* error code:
1285         0: everything OK
1286         1: level not implemented
1287         2: file doesn't exist
1288         3: can't allocate memory
1289         4: can't free memory
1290         5: non existant struct
1291 */
1292
1293 /*
1294         A printer and a printer driver are 2 different things.
1295         NT manages them separatelly, Samba does the same.
1296         Why ? Simply because it's easier and it makes sense !
1297         
1298         Now explanation: You have 3 printers behind your samba server,
1299         2 of them are the same make and model (laser A and B). But laser B 
1300         has an 3000 sheet feeder and laser A doesn't such an option.
1301         Your third printer is an old dot-matrix model for the accounting :-).
1302         
1303         If the /usr/local/samba/lib directory (default dir), you will have
1304         5 files to describe all of this.
1305         
1306         3 files for the printers (1 by printer):
1307                 NTprinter_laser A
1308                 NTprinter_laser B
1309                 NTprinter_accounting
1310         2 files for the drivers (1 for the laser and 1 for the dot matrix)
1311                 NTdriver_printer model X
1312                 NTdriver_printer model Y
1313
1314 jfm: I should use this comment for the text file to explain 
1315         same thing for the forms BTW.
1316         Je devrais mettre mes commentaires en francais, ca serait mieux :-)
1317
1318 */
1319
1320