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