diff options
author | Jean-François Micouleau <jfm@samba.org> | 2000-02-07 16:17:59 +0000 |
---|---|---|
committer | Jean-François Micouleau <jfm@samba.org> | 2000-02-07 16:17:59 +0000 |
commit | 6a6749d81e892bb06bfdc0fefdc428e5e6599f71 (patch) | |
tree | 1422ec8d31fc4202f6b565015ac28dd6d0573158 /source3/printing/nt_printing.c | |
parent | 868c81eefa72b31023eeac32788eaa439013c0f8 (diff) | |
download | samba-6a6749d81e892bb06bfdc0fefdc428e5e6599f71.tar.gz samba-6a6749d81e892bb06bfdc0fefdc428e5e6599f71.tar.bz2 samba-6a6749d81e892bb06bfdc0fefdc428e5e6599f71.zip |
First commit of the spoolss code to the HEAD branch.
still needs a lot of cleaning/debuging.
J.F.
(This used to be commit bd9d4cdde9193c120c6f4e8cf72f87cd67a9387e)
Diffstat (limited to 'source3/printing/nt_printing.c')
-rw-r--r-- | source3/printing/nt_printing.c | 1413 |
1 files changed, 1413 insertions, 0 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c new file mode 100644 index 0000000000..00e052772e --- /dev/null +++ b/source3/printing/nt_printing.c @@ -0,0 +1,1413 @@ +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + +/**************************************************************************** +parse a form line. +****************************************************************************/ +static BOOL parse_form_entry(char *line, nt_forms_struct *buf) +{ +#define NAMETOK 0 +#define FLAGTOK 1 +#define WIDTHTOK 2 +#define LENGTHTOK 3 +#define LEFTTOK 4 +#define TOPTOK 5 +#define RIGHTTOK 6 +#define BOTTOMTOK 7 +#define MAXTOK 8 + char *tok[MAXTOK]; + int count = 0; + + tok[count] = strtok(line,":"); + + /* strip the comment lines */ + if (tok[0][0]=='#') return (False); + count++; + + while ( ((tok[count] = strtok(NULL,":")) != NULL ) && count<MAXTOK-1) + { + count++; + } + + DEBUG(6,("Found [%d] tokens\n", count)); + + StrnCpy(buf->name,tok[NAMETOK],sizeof(buf->name)-1); + buf->flag=atoi(tok[FLAGTOK]); + buf->width=atoi(tok[WIDTHTOK]); + buf->length=atoi(tok[LENGTHTOK]); + buf->left=atoi(tok[LEFTTOK]); + buf->top=atoi(tok[TOPTOK]); + buf->right=atoi(tok[RIGHTTOK]); + buf->bottom=atoi(tok[BOTTOMTOK]); + + return(True); +} + +/**************************************************************************** +get a form struct list +****************************************************************************/ +int get_ntforms(nt_forms_struct **list) +{ + FILE *f; + pstring line; + char *lp_forms = lp_nt_forms(); + int total=0; + int grandtotal=0; + *line=0; + + f = sys_fopen(lp_forms,"r"); + if (!f) + { + return(0); + } + + while ( fgets(line, sizeof(pstring), f) ) + { + DEBUG(5,("%s\n",line)); + + *list = Realloc(*list, sizeof(nt_forms_struct)*(total+1)); + if (! *list) + { + total = 0; + break; + } + bzero( (char *)&(*list)[total], sizeof(nt_forms_struct) ); + if ( parse_form_entry(line, &(*list)[total] ) ) + { + total++; + } + grandtotal++; + } + fclose(f); + + DEBUG(4,("%d info lines on %d\n",total, grandtotal)); + + return(total); +} + +/**************************************************************************** +write a form struct list +****************************************************************************/ +int write_ntforms(nt_forms_struct **list, int number) +{ + FILE *f; + pstring line; + char *file = lp_nt_forms(); + int total=0; + int i; + + *line=0; + + DEBUG(6,("write_ntforms\n")); + + if((f = sys_fopen(file, "w")) == NULL) + { + DEBUG(1, ("cannot create forms file [%s]\n", file)); + return(0); + } + + for (i=0; i<number;i++) + { + + fprintf(f,"%s:%d:%d:%d:%d:%d:%d:%d\n", (*list)[i].name, + (*list)[i].flag, (*list)[i].width, (*list)[i].length, + (*list)[i].left, (*list)[i].top, (*list)[i].right, (*list)[i].bottom); + + DEBUGADD(7,("adding entry [%s]\n", (*list)[i].name)); + } + + fclose(f); + DEBUGADD(6,("closing file\n")); + return(total); +} + +/**************************************************************************** +add a form struct at the end of the list +****************************************************************************/ +void add_a_form(nt_forms_struct **list, const FORM *form, int *count) +{ + int n=0; + BOOL update; + fstring form_name; + + /* + * NT tries to add forms even when + * they are already in the base + * only update the values if already present + */ + + update=False; + + unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1); + for (n=0; n<*count && update==False; n++) + { + if (!strncmp((*list)[n].name, form_name, strlen(form_name))) + { + DEBUG(3, ("NT workaround, [%s] already exists\n", form_name)); + update=True; + } + } + + if (update==False) + { + *list=Realloc(*list, (n+1)*sizeof(nt_forms_struct)); + unistr2_to_ascii((*list)[n].name, &(form->name), sizeof((*list)[n].name)-1); + (*count)++; + } + + (*list)[n].flag=form->flags; + (*list)[n].width=form->size_x; + (*list)[n].length=form->size_y; + (*list)[n].left=form->left; + (*list)[n].top=form->top; + (*list)[n].right=form->right; + (*list)[n].bottom=form->bottom; +} + +/**************************************************************************** +update a form struct +****************************************************************************/ +void update_a_form(nt_forms_struct **list, const FORM *form, int count) +{ + int n=0; + fstring form_name; + unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1); + + DEBUG(6, ("[%s]\n", form_name)); + for (n=0; n<count; n++) + { + DEBUGADD(6, ("n [%d]:[%s]\n", n, (*list)[n].name)); + if (!strncmp((*list)[n].name, form_name, strlen(form_name))) + break; + } + + if (n==count) return; + + (*list)[n].flag=form->flags; + (*list)[n].width=form->size_x; + (*list)[n].length=form->size_y; + (*list)[n].left=form->left; + (*list)[n].top=form->top; + (*list)[n].right=form->right; + (*list)[n].bottom=form->bottom; +} + +/**************************************************************************** +get the nt drivers list + +open the directory and look-up the matching names +****************************************************************************/ +int get_ntdrivers(fstring **list, char *architecture) +{ + DIR *dirp; + char *dpname; + fstring name_match; + fstring short_archi; + fstring driver_name; + int match_len; + int total=0; + + DEBUG(5,("Getting the driver list from directory: [%s]\n", lp_nt_drivers_file())); + + *list=NULL; + dirp = opendir(lp_nt_drivers_file()); + + if (dirp == NULL) + { + DEBUG(0,("Error opening driver directory [%s]\n",lp_nt_drivers_file())); + return(-1); + } + + get_short_archi(short_archi, architecture); + slprintf(name_match, sizeof(name_match)-1, "NTdriver_%s_", short_archi); + match_len=strlen(name_match); + + while ((dpname = readdirname(dirp)) != NULL) + { + if (strncmp(dpname, name_match, match_len)==0) + { + DEBUGADD(7,("Found: [%s]\n", dpname)); + + fstrcpy(driver_name, dpname+match_len); + all_string_sub(driver_name, "#", "/", 0); + *list = Realloc(*list, sizeof(fstring)*(total+1)); + StrnCpy((*list)[total], driver_name, strlen(driver_name)); + DEBUGADD(6,("Added: [%s]\n", driver_name)); + total++; + } + } + + closedir(dirp); + return(total); +} + +/**************************************************************************** +function to do the mapping between the long architecture name and +the short one. +****************************************************************************/ +void get_short_archi(char *short_archi, char *long_archi) +{ + struct table { + char *long_archi; + char *short_archi; + }; + + struct table archi_table[]= + { + {"Windows 4.0", "" }, + {"Windows NT x86", "W32X86" }, + {"Windows NT R4000", "" }, + {"Windows NT Alpha_AXP", "" }, + {"Windows NT PowerPC", "" }, + {NULL, "" } + }; + + int i=-1; + + DEBUG(7,("Getting architecture dependant directory\n")); + do { + i++; + } while ( (archi_table[i].long_archi!=NULL ) && strncmp(long_archi, archi_table[i].long_archi, strlen(long_archi)) ); + + if (archi_table[i].long_archi==NULL) + { + DEBUGADD(7,("Unknown architecture [%s] !\n", long_archi)); + } + StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi)); + + DEBUGADD(8,("index: [%d]\n", i)); + DEBUGADD(8,("long architecture: [%s]\n", long_archi)); + DEBUGADD(8,("short architecture: [%s]\n", short_archi)); +} + +/**************************************************************************** +****************************************************************************/ +static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) +{ + FILE *f; + pstring file; + fstring architecture; + fstring driver_name; + char **dependentfiles; + + /* create a file in the dir lp_nt_driver_file */ + /* with the full printer DRIVER name */ + /* eg: "/usr/local/samba/lib/NTdriver_HP LaserJet 6MP" */ + /* each name is really defining an *unique* printer model */ + /* I don't want to mangle the name to find it back when enumerating */ + + /* il faut substituer les / par 1 autre caractere d'abord */ + /* dans le nom de l'imprimante par un # ???*/ + + StrnCpy(driver_name, driver->name, sizeof(driver_name)-1); + + all_string_sub(driver_name, "/", "#", 0); + + get_short_archi(architecture, driver->environment); + + slprintf(file, sizeof(file)-1, "%s/NTdriver_%s_%s", + lp_nt_drivers_file(), architecture, driver_name); + + if((f = sys_fopen(file, "w")) == NULL) + { + DEBUG(1, ("cannot create driver file [%s]\n", file)); + return(2); + } + + /* + * cversion must be 2. + * when adding a printer ON the SERVER + * rpcAddPrinterDriver defines it to zero + * which is wrong !!! + * + * JFM, 4/14/99 + */ + driver->cversion=2; + + fprintf(f, "version: %d\n", driver->cversion); + fprintf(f, "name: %s\n", driver->name); + fprintf(f, "environment: %s\n", driver->environment); + fprintf(f, "driverpath: %s\n", driver->driverpath); + fprintf(f, "datafile: %s\n", driver->datafile); + fprintf(f, "configfile: %s\n", driver->configfile); + fprintf(f, "helpfile: %s\n", driver->helpfile); + fprintf(f, "monitorname: %s\n", driver->monitorname); + fprintf(f, "defaultdatatype: %s\n", driver->defaultdatatype); + + /* and the dependants files */ + + dependentfiles=driver->dependentfiles; + + while ( **dependentfiles != '\0' ) + { + fprintf(f, "dependentfile: %s\n", *dependentfiles); + dependentfiles++; + } + + fclose(f); + return(0); +} + +/**************************************************************************** +****************************************************************************/ +static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch) +{ + FILE *f; + pstring file; + fstring driver_name; + fstring architecture; + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info; + char *line; + fstring p; + char *v; + int i=0; + char **dependentfiles=NULL; + + /* + * replace all the / by # in the driver name + * get the short architecture name + * construct the driver file name + */ + StrnCpy(driver_name, in_prt, sizeof(driver_name)-1); + all_string_sub(driver_name, "/", "#", 0); + + get_short_archi(architecture, in_arch); + + slprintf(file, sizeof(file)-1, "%s/NTdriver_%s_%s", + lp_nt_drivers_file(), architecture, driver_name); + + if((f = sys_fopen(file, "r")) == NULL) + { + DEBUG(2, ("cannot open printer driver file [%s]\n", file)); + return(2); + } + + /* the file exists, allocate some memory */ + info=(NT_PRINTER_DRIVER_INFO_LEVEL_3 *)malloc(sizeof(NT_PRINTER_DRIVER_INFO_LEVEL_3)); + ZERO_STRUCTP(info); + + /* allocate a 4Kbytes buffer for parsing lines */ + line=(char *)malloc(4096*sizeof(char)); + + while ( fgets(line, 4095, f) ) + { + + v=strncpyn(p, line, sizeof(p), ':'); + if (v==NULL) + { + DEBUG(1, ("malformed printer entry (no :)\n")); + continue; + } + + v++; + + trim_string(v, " ", NULL); + trim_string(v, NULL, " "); + trim_string(v, NULL, "\n"); + /* don't check if v==NULL as an empty arg is valid */ + + if (!strncmp(p, "version", strlen("version"))) + info->cversion=atoi(v); + + if (!strncmp(p, "name", strlen("name"))) + StrnCpy(info->name, v, strlen(v)); + + if (!strncmp(p, "environment", strlen("environment"))) + StrnCpy(info->environment, v, strlen(v)); + + if (!strncmp(p, "driverpath", strlen("driverpath"))) + StrnCpy(info->driverpath, v, strlen(v)); + + if (!strncmp(p, "datafile", strlen("datafile"))) + StrnCpy(info->datafile, v, strlen(v)); + + if (!strncmp(p, "configfile", strlen("configfile"))) + StrnCpy(info->configfile, v, strlen(v)); + + if (!strncmp(p, "helpfile", strlen("helpfile"))) + StrnCpy(info->helpfile, v, strlen(v)); + + if (!strncmp(p, "monitorname", strlen("monitorname"))) + StrnCpy(info->monitorname, v, strlen(v)); + + if (!strncmp(p, "defaultdatatype", strlen("defaultdatatype"))) + StrnCpy(info->defaultdatatype, v, strlen(v)); + + if (!strncmp(p, "dependentfile", strlen("dependentfile"))) + { + dependentfiles=(char **)Realloc(dependentfiles, sizeof(char *)*(i+1)); + + dependentfiles[i]=(char *)malloc( sizeof(char)* (strlen(v)+1) ); + + StrnCpy(dependentfiles[i], v, strlen(v) ); + i++; + } + + } + + free(line); + + fclose(f); + + dependentfiles=(char **)Realloc(dependentfiles, sizeof(char *)*(i+1)); + dependentfiles[i]=(char *)malloc( sizeof(char) ); + *dependentfiles[i]='\0'; + + info->dependentfiles=dependentfiles; + + *info_ptr=info; + + return (0); +} + +/**************************************************************************** +debugging function, dump at level 6 the struct in the logs +****************************************************************************/ +static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) +{ + uint32 success; + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3; + char **dependentfiles; + + DEBUG(6,("Dumping printer driver at level [%d]\n", level)); + + switch (level) + { + case 3: + { + if (driver.info_3 == NULL) + { + DEBUGADD(3,("NULL pointer, memory not alloced ?\n")); + success=5; + } + else + { + info3=driver.info_3; + + DEBUGADD(6,("version:[%d]\n", info3->cversion)); + DEBUGADD(6,("name:[%s]\n", info3->name)); + DEBUGADD(6,("environment:[%s]\n", info3->environment)); + DEBUGADD(6,("driverpath:[%s]\n", info3->driverpath)); + DEBUGADD(6,("datafile:[%s]\n", info3->datafile)); + DEBUGADD(6,("configfile:[%s]\n", info3->configfile)); + DEBUGADD(6,("helpfile:[%s]\n", info3->helpfile)); + DEBUGADD(6,("monitorname:[%s]\n", info3->monitorname)); + DEBUGADD(6,("defaultdatatype:[%s]\n", info3->defaultdatatype)); + + dependentfiles=info3->dependentfiles; + + while ( **dependentfiles != '\0' ) + { + DEBUGADD(6,("dependentfile:[%s]\n", *dependentfiles)); + dependentfiles++; + } + success=0; + } + break; + } + default: + DEBUGADD(1,("Level not implemented\n")); + success=1; + break; + } + + return (success); +} + +/**************************************************************************** +****************************************************************************/ +static void add_a_devicemode(NT_DEVICEMODE *nt_devmode, FILE *f) +{ + int i; + + fprintf(f, "formname: %s\n", nt_devmode->formname); + fprintf(f, "specversion: %d\n", nt_devmode->specversion); + fprintf(f, "driverversion: %d\n", nt_devmode->driverversion); + fprintf(f, "size: %d\n", nt_devmode->size); + fprintf(f, "driverextra: %d\n", nt_devmode->driverextra); + fprintf(f, "fields: %d\n", nt_devmode->fields); + fprintf(f, "orientation: %d\n", nt_devmode->orientation); + fprintf(f, "papersize: %d\n", nt_devmode->papersize); + fprintf(f, "paperlength: %d\n", nt_devmode->paperlength); + fprintf(f, "paperwidth: %d\n", nt_devmode->paperwidth); + fprintf(f, "scale: %d\n", nt_devmode->scale); + fprintf(f, "copies: %d\n", nt_devmode->copies); + fprintf(f, "defaultsource: %d\n", nt_devmode->defaultsource); + fprintf(f, "printquality: %d\n", nt_devmode->printquality); + fprintf(f, "color: %d\n", nt_devmode->color); + fprintf(f, "duplex: %d\n", nt_devmode->duplex); + fprintf(f, "yresolution: %d\n", nt_devmode->yresolution); + fprintf(f, "ttoption: %d\n", nt_devmode->ttoption); + fprintf(f, "collate: %d\n", nt_devmode->collate); + fprintf(f, "icmmethod: %d\n", nt_devmode->icmmethod); + fprintf(f, "icmintent: %d\n", nt_devmode->icmintent); + fprintf(f, "mediatype: %d\n", nt_devmode->mediatype); + fprintf(f, "dithertype: %d\n", nt_devmode->dithertype); + + if (nt_devmode->private != NULL) + { + fprintf(f, "private: "); + for (i=0; i<nt_devmode->driverextra; i++) + fprintf(f, "%02X", nt_devmode->private[i]); + fprintf(f, "\n"); + } +} + +/**************************************************************************** +****************************************************************************/ +static void save_specifics(NT_PRINTER_PARAM *param, FILE *f) +{ + int i; + + while (param != NULL) + { + fprintf(f, "specific: %s#%d#%d#", param->value, param->type, param->data_len); + + for (i=0; i<param->data_len; i++) + fprintf(f, "%02X", param->data[i]); + + fprintf(f, "\n"); + + param=param->next; + } +} + +/**************************************************************************** +****************************************************************************/ +static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) +{ + FILE *f; + pstring file; + fstring printer_name; + NT_DEVICEMODE *nt_devmode; + + /* + * JFM: one day I'll forget. + * below that's info->portname because that's the SAMBA sharename + * and I made NT 'thinks' it's the portname + * the info->sharename is the thing you can name when you add a printer + * that's the short-name when you create shared printer for 95/98 + * So I've made a limitation in SAMBA: you can only have 1 printer model + * behind a SAMBA share. + */ + + + StrnCpy(printer_name, info->portname, sizeof(printer_name)-1); + + slprintf(file, sizeof(file)-1, "%s/NTprinter_%s", + lp_nt_drivers_file(), printer_name); + + /* create a file in the dir lp_nt_driver_file */ + /* with the full printer name */ + /* eg: "/usr/local/samba/lib/NTprinter_HP LaserJet 6MP" */ + /* each name is really defining an *unique* printer model */ + /* I don't want to mangle the name to find it back when enumerating */ + + if((f = sys_fopen(file, "w")) == NULL) + { + DEBUG(1, ("cannot create printer file [%s]\n", file)); + return(2); + } + + fprintf(f, "attributes: %d\n", info->attributes); + fprintf(f, "priority: %d\n", info->priority); + fprintf(f, "default_priority: %d\n", info->default_priority); + fprintf(f, "starttime: %d\n", info->starttime); + fprintf(f, "untiltime: %d\n", info->untiltime); + fprintf(f, "status: %d\n", info->status); + fprintf(f, "cjobs: %d\n", info->cjobs); + fprintf(f, "averageppm: %d\n", info->averageppm); + + /* + * in addprinter: no servername and the printer is the name + * in setprinter: servername is \\server + * and printer is \\server\\printer + * + * Samba manages only local printers. + * we currently don't support things like path=\\other_server\printer + */ + + if (info->servername[0]!='\0') + { + trim_string(info->printername, info->servername, NULL); + trim_string(info->printername, "\\", NULL); + info->servername[0]='\0'; + } + + fprintf(f, "servername: %s\n", info->servername); + fprintf(f, "printername: %s\n", info->printername); + fprintf(f, "sharename: %s\n", info->sharename); + fprintf(f, "portname: %s\n", info->portname); + fprintf(f, "drivername: %s\n", info->drivername); + fprintf(f, "comment: %s\n", info->comment); + fprintf(f, "location: %s\n", info->location); + fprintf(f, "sepfile: %s\n", info->sepfile); + fprintf(f, "printprocessor: %s\n", info->printprocessor); + fprintf(f, "datatype: %s\n", info->datatype); + fprintf(f, "parameters: %s\n", info->parameters); + + /* store the devmode and the private part if it exist */ + nt_devmode=info->devmode; + if (nt_devmode!=NULL) + { + add_a_devicemode(nt_devmode, f); + } + + /* and store the specific parameters */ + if (info->specific != NULL) + { + save_specifics(info->specific, f); + } + + fclose(f); + + return (0); +} + +/**************************************************************************** +fill a NT_PRINTER_PARAM from a text file + +used when reading from disk. +****************************************************************************/ +static void dissect_and_fill_a_param(NT_PRINTER_PARAM *param, char *v) +{ + char *tok[5]; + int count = 0; + + DEBUG(5,("dissect_and_fill_a_param\n")); + + tok[count] = strtok(v,"#"); + count++; + + while ( ((tok[count] = strtok(NULL,"#")) != NULL ) && count<4) + { + count++; + } + + StrnCpy(param->value, tok[0], sizeof(param->value)-1); + param->type=atoi(tok[1]); + param->data_len=atoi(tok[2]); + param->data=(uint8 *)malloc(param->data_len * sizeof(uint8)); + strhex_to_str(param->data, 2*(param->data_len), tok[3]); + param->next=NULL; + + DEBUGADD(5,("value:[%s], len:[%d]\n", param->value, param->data_len)); +} + +/**************************************************************************** +fill a NT_PRINTER_PARAM from a text file + +used when reading from disk. +****************************************************************************/ +void dump_a_param(NT_PRINTER_PARAM *param) +{ + DEBUG(5,("dump_a_param\n")); + DEBUGADD(6,("value [%s]\n", param->value)); + DEBUGADD(6,("type [%d]\n", param->type)); + DEBUGADD(6,("data len [%d]\n", param->data_len)); +} + +/**************************************************************************** +****************************************************************************/ +BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param) +{ + NT_PRINTER_PARAM *current; + + DEBUG(8,("add_a_specific_param\n")); + + param->next=NULL; + + if (info_2->specific == NULL) + { + info_2->specific=param; + } + else + { + current=info_2->specific; + while (current->next != NULL) { + current=current->next; + } + current->next=param; + } + return (True); +} + +/**************************************************************************** +****************************************************************************/ +BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param) +{ + NT_PRINTER_PARAM *current; + NT_PRINTER_PARAM *previous; + + current=info_2->specific; + previous=current; + + if (current==NULL) return (False); + + if ( !strcmp(current->value, param->value) && + (strlen(current->value)==strlen(param->value)) ) + { + DEBUG(9,("deleting first value\n")); + info_2->specific=current->next; + free(current); + DEBUG(9,("deleted first value\n")); + return (True); + } + + current=previous->next; + + while ( current!=NULL ) + { + if (!strcmp(current->value, param->value) && + strlen(current->value)==strlen(param->value) ) + { + DEBUG(9,("deleting current value\n")); + previous->next=current->next; + free(current); + DEBUG(9,("deleted current value\n")); + return(True); + } + + previous=previous->next; + current=current->next; + } + return (False); +} + +/**************************************************************************** +****************************************************************************/ +static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename) +{ + FILE *f; + pstring file; + fstring printer_name; + NT_PRINTER_INFO_LEVEL_2 *info; + NT_DEVICEMODE *nt_devmode; + NT_PRINTER_PARAM *param; + char *line; + fstring p; + char *v; + + /* + * the sharename argument is the SAMBA sharename + */ + StrnCpy(printer_name, sharename, sizeof(printer_name)-1); + + slprintf(file, sizeof(file)-1, "%s/NTprinter_%s", + lp_nt_drivers_file(), printer_name); + + if((f = sys_fopen(file, "r")) == NULL) + { + DEBUG(2, ("cannot open printer file [%s]\n", file)); + return(2); + } + + /* the file exists, allocate some memory */ + info=(NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2)); + ZERO_STRUCTP(info); + + nt_devmode=(NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE)); + ZERO_STRUCTP(nt_devmode); + init_devicemode(nt_devmode); + + info->devmode=nt_devmode; + + line=(char *)malloc(4096*sizeof(char)); + + while ( fgets(line, 4095, f) ) + { + + v=strncpyn(p, line, sizeof(p), ':'); + if (v==NULL) + { + DEBUG(1, ("malformed printer entry (no `:')\n")); + DEBUGADD(2, ("line [%s]\n", line)); + continue; + } + + v++; + + trim_string(v, " ", NULL); + trim_string(v, NULL, " "); + trim_string(v, NULL, "\n"); + + /* don't check if v==NULL as an empty arg is valid */ + + DEBUGADD(15, ("[%s]:[%s]\n", p, v)); + + /* + * The PRINTER_INFO_2 fields + */ + + if (!strncmp(p, "attributes", strlen("attributes"))) + info->attributes=atoi(v); + + if (!strncmp(p, "priority", strlen("priority"))) + info->priority=atoi(v); + + if (!strncmp(p, "default_priority", strlen("default_priority"))) + info->default_priority=atoi(v); + + if (!strncmp(p, "starttime", strlen("starttime"))) + info->starttime=atoi(v); + + if (!strncmp(p, "untiltime", strlen("untiltime"))) + info->untiltime=atoi(v); + + if (!strncmp(p, "status", strlen("status"))) + info->status=atoi(v); + + if (!strncmp(p, "cjobs", strlen("cjobs"))) + info->cjobs=atoi(v); + + if (!strncmp(p, "averageppm", strlen("averageppm"))) + info->averageppm=atoi(v); + + if (!strncmp(p, "servername", strlen("servername"))) + StrnCpy(info->servername, v, strlen(v)); + + if (!strncmp(p, "printername", strlen("printername"))) + StrnCpy(info->printername, v, strlen(v)); + + if (!strncmp(p, "sharename", strlen("sharename"))) + StrnCpy(info->sharename, v, strlen(v)); + + if (!strncmp(p, "portname", strlen("portname"))) + StrnCpy(info->portname, v, strlen(v)); + + if (!strncmp(p, "drivername", strlen("drivername"))) + StrnCpy(info->drivername, v, strlen(v)); + + if (!strncmp(p, "comment", strlen("comment"))) + StrnCpy(info->comment, v, strlen(v)); + + if (!strncmp(p, "location", strlen("location"))) + StrnCpy(info->location, v, strlen(v)); + + if (!strncmp(p, "sepfile", strlen("sepfile"))) + StrnCpy(info->sepfile, v, strlen(v)); + + if (!strncmp(p, "printprocessor", strlen("printprocessor"))) + StrnCpy(info->printprocessor, v, strlen(v)); + + if (!strncmp(p, "datatype", strlen("datatype"))) + StrnCpy(info->datatype, v, strlen(v)); + + if (!strncmp(p, "parameters", strlen("parameters"))) + StrnCpy(info->parameters, v, strlen(v)); + + /* + * The DEVICEMODE fields + */ + + if (!strncmp(p, "formname", strlen("formname"))) + StrnCpy(nt_devmode->formname, v, strlen(v)); + + if (!strncmp(p, "specversion", strlen("specversion"))) + nt_devmode->specversion=atoi(v); + + if (!strncmp(p, "driverversion", strlen("driverversion"))) + nt_devmode->driverversion=atoi(v); + + if (!strncmp(p, "size", strlen("size"))) + nt_devmode->size=atoi(v); + + if (!strncmp(p, "driverextra", strlen("driverextra"))) + nt_devmode->driverextra=atoi(v); + + if (!strncmp(p, "fields", strlen("fields"))) + nt_devmode->fields=atoi(v); + + if (!strncmp(p, "orientation", strlen("orientation"))) + nt_devmode->orientation=atoi(v); + + if (!strncmp(p, "papersize", strlen("papersize"))) + nt_devmode->papersize=atoi(v); + + if (!strncmp(p, "paperlength", strlen("paperlength"))) + nt_devmode->paperlength=atoi(v); + + if (!strncmp(p, "paperwidth", strlen("paperwidth"))) + nt_devmode->paperwidth=atoi(v); + + if (!strncmp(p, "scale", strlen("scale"))) + nt_devmode->scale=atoi(v); + + if (!strncmp(p, "copies", strlen("copies"))) + nt_devmode->copies=atoi(v); + + if (!strncmp(p, "defaultsource", strlen("defaultsource"))) + nt_devmode->defaultsource=atoi(v); + + if (!strncmp(p, "printquality", strlen("printquality"))) + nt_devmode->printquality=atoi(v); + + if (!strncmp(p, "color", strlen("color"))) + nt_devmode->color=atoi(v); + + if (!strncmp(p, "duplex", strlen("duplex"))) + nt_devmode->duplex=atoi(v); + + if (!strncmp(p, "yresolution", strlen("yresolution"))) + nt_devmode->yresolution=atoi(v); + + if (!strncmp(p, "ttoption", strlen("ttoption"))) + nt_devmode->ttoption=atoi(v); + + if (!strncmp(p, "collate", strlen("collate"))) + nt_devmode->collate=atoi(v); + + if (!strncmp(p, "icmmethod", strlen("icmmethod"))) + nt_devmode->icmmethod=atoi(v); + + if (!strncmp(p, "icmintent", strlen("icmintent"))) + nt_devmode->icmintent=atoi(v); + + if (!strncmp(p, "mediatype", strlen("mediatype"))) + nt_devmode->mediatype=atoi(v); + + if (!strncmp(p, "dithertype", strlen("dithertype"))) + nt_devmode->dithertype=atoi(v); + + if (!strncmp(p, "private", strlen("private"))) + { + nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra*sizeof(uint8)); + strhex_to_str(nt_devmode->private, 2*nt_devmode->driverextra, v); + } + + /* the specific */ + + if (!strncmp(p, "specific", strlen("specific"))) + { + param=(NT_PRINTER_PARAM *)malloc(sizeof(NT_PRINTER_PARAM)); + ZERO_STRUCTP(param); + + dissect_and_fill_a_param(param, v); + + dump_a_param(param); + + add_a_specific_param(info, param); + } + + } + fclose(f); + free(line); + + *info_ptr=info; + + return (0); +} + +/**************************************************************************** +debugging function, dump at level 6 the struct in the logs +****************************************************************************/ +static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) +{ + uint32 success; + NT_PRINTER_INFO_LEVEL_2 *info2; + + DEBUG(6,("Dumping printer at level [%d]\n", level)); + + switch (level) + { + case 2: + { + if (printer.info_2 == NULL) + { + DEBUGADD(3,("NULL pointer, memory not alloced ?\n")); + success=5; + } + else + { + info2=printer.info_2; + + DEBUGADD(6,("attributes:[%d]\n", info2->attributes)); + DEBUGADD(6,("priority:[%d]\n", info2->priority)); + DEBUGADD(6,("default_priority:[%d]\n", info2->default_priority)); + DEBUGADD(6,("starttime:[%d]\n", info2->starttime)); + DEBUGADD(6,("untiltime:[%d]\n", info2->untiltime)); + DEBUGADD(6,("status:[%d]\n", info2->status)); + DEBUGADD(6,("cjobs:[%d]\n", info2->cjobs)); + DEBUGADD(6,("averageppm:[%d]\n", info2->averageppm)); + + DEBUGADD(6,("servername:[%s]\n", info2->servername)); + DEBUGADD(6,("printername:[%s]\n", info2->printername)); + DEBUGADD(6,("sharename:[%s]\n", info2->sharename)); + DEBUGADD(6,("portname:[%s]\n", info2->portname)); + DEBUGADD(6,("drivername:[%s]\n", info2->drivername)); + DEBUGADD(6,("comment:[%s]\n", info2->comment)); + DEBUGADD(6,("location:[%s]\n", info2->location)); + DEBUGADD(6,("sepfile:[%s]\n", info2->sepfile)); + DEBUGADD(6,("printprocessor:[%s]\n", info2->printprocessor)); + DEBUGADD(6,("datatype:[%s]\n", info2->datatype)); + DEBUGADD(6,("parameters:[%s]\n", info2->parameters)); + success=0; + } + break; + } + default: + DEBUGADD(1,("Level not implemented\n")); + success=1; + break; + } + + return (success); +} + +/* + * The function below are the high level ones. + * only those ones must be called from the spoolss code. + * JFM. + */ + + +/**************************************************************************** +****************************************************************************/ +uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) +{ + uint32 success; + + dump_a_printer(printer, level); + + switch (level) + { + case 2: + { + success=add_a_printer_2(printer.info_2); + break; + } + default: + success=1; + break; + } + + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 get_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level, fstring sharename) +{ + uint32 success; + + switch (level) + { + case 2: + { + printer->info_2=NULL; + success=get_a_printer_2(&(printer->info_2), sharename); + break; + } + default: + success=1; + break; + } + + dump_a_printer(*printer, level); + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 free_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) +{ + uint32 success; + DEBUG(4,("freeing a printer at level [%d]\n", level)); + + switch (level) + { + case 2: + { + if (printer.info_2 != NULL) + { + if ((printer.info_2)->devmode != NULL) + { + DEBUG(6,("deleting DEVMODE\n")); + if ((printer.info_2)->devmode->private !=NULL ) + free((printer.info_2)->devmode->private); + free((printer.info_2)->devmode); + } + + if ((printer.info_2)->specific != NULL) + { + NT_PRINTER_PARAM *param; + NT_PRINTER_PARAM *next_param; + + param=(printer.info_2)->specific; + + while ( param != NULL) + { + next_param=param->next; + DEBUG(6,("deleting param [%s]\n", param->value)); + free(param->data); + free(param); + param=next_param; + } + } + + free(printer.info_2); + success=0; + } + else + { + success=4; + } + break; + } + default: + success=1; + break; + } + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) +{ + uint32 success; + DEBUG(4,("adding a printer at level [%d]\n", level)); + dump_a_printer_driver(driver, level); + + switch (level) + { + case 3: + { + success=add_a_printer_driver_3(driver.info_3); + break; + } + default: + success=1; + break; + } + + return (success); +} +/**************************************************************************** +****************************************************************************/ +uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level, + fstring printername, fstring architecture) +{ + uint32 success; + + switch (level) + { + case 3: + { + success=get_a_printer_driver_3(&(driver->info_3), + printername, + architecture); + break; + } + default: + success=1; + break; + } + + dump_a_printer_driver(*driver, level); + return (success); +} + +/**************************************************************************** +****************************************************************************/ +uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) +{ + uint32 success; + NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3; + char **dependentfiles; + + switch (level) + { + case 3: + { + if (driver.info_3 != NULL) + { + info3=driver.info_3; + dependentfiles=info3->dependentfiles; + + while ( **dependentfiles != '\0' ) + { + free (*dependentfiles); + dependentfiles++; + } + + /* the last one (1 char !) */ + free (*dependentfiles); + + dependentfiles=info3->dependentfiles; + free (dependentfiles); + + free(info3); + success=0; + } + else + { + success=4; + } + break; + } + default: + success=1; + break; + } + return (success); +} + +/**************************************************************************** +****************************************************************************/ +BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index, + fstring value, uint8 **data, uint32 *type, uint32 *len) +{ + /* right now that's enough ! */ + NT_PRINTER_PARAM *param; + int i=0; + + param=printer.info_2->specific; + + while (param != NULL && i < param_index) + { + param=param->next; + i++; + } + + if (param != NULL) + { + /* exited because it exist */ + *type=param->type; + StrnCpy(value, param->value, sizeof(value)-1); + *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); + memcpy(*data, param->data, param->data_len); + *len=param->data_len; + return (True); + } + return (False); +} + +/**************************************************************************** +****************************************************************************/ +BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level, + fstring value, uint8 **data, uint32 *type, uint32 *len) +{ + /* right now that's enough ! */ + NT_PRINTER_PARAM *param; + + DEBUG(5, ("get_specific_param\n")); + + param=printer.info_2->specific; + + while (param != NULL) + { + if ( !strcmp(value, param->value) + && strlen(value)==strlen(param->value)) + break; + + param=param->next; + } + + DEBUG(6, ("found one param\n")); + if (param != NULL) + { + /* exited because it exist */ + *type=param->type; + + *data=(uint8 *)malloc(param->data_len*sizeof(uint8)); + memcpy(*data, param->data, param->data_len); + *len=param->data_len; + + DEBUG(6, ("exit of get_specific_param:true\n")); + return (True); + } + DEBUG(6, ("exit of get_specific_param:false\n")); + return (False); +} + +/**************************************************************************** +****************************************************************************/ +void init_devicemode(NT_DEVICEMODE *nt_devmode) +{ +/* + * should I init this ones ??? + nt_devmode->devicename +*/ + fstrcpy(nt_devmode->formname, "A4"); + + nt_devmode->specversion = 0x0401; + nt_devmode->driverversion = 0x0400; + nt_devmode->size = 0x00DC; + nt_devmode->driverextra = 0x0000; + nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY | + DEFAULTSOURCE | COPIES | SCALE | + PAPERSIZE | ORIENTATION; + nt_devmode->orientation = 1; + nt_devmode->papersize = PAPER_A4; + nt_devmode->paperlength = 0; + nt_devmode->paperwidth = 0; + nt_devmode->scale = 0x64; + nt_devmode->copies = 01; + nt_devmode->defaultsource = BIN_FORMSOURCE; + nt_devmode->printquality = 0x0258; + nt_devmode->color = COLOR_MONOCHROME; + nt_devmode->duplex = DUP_SIMPLEX; + nt_devmode->yresolution = 0; + nt_devmode->ttoption = TT_SUBDEV; + nt_devmode->collate = COLLATE_FALSE; + nt_devmode->icmmethod = 0; + nt_devmode->icmintent = 0; + nt_devmode->mediatype = 0; + nt_devmode->dithertype = 0; + + /* non utilisés par un driver d'imprimante */ + nt_devmode->logpixels = 0; + nt_devmode->bitsperpel = 0; + nt_devmode->pelswidth = 0; + nt_devmode->pelsheight = 0; + nt_devmode->displayflags = 0; + nt_devmode->displayfrequency = 0; + nt_devmode->reserved1 = 0; + nt_devmode->reserved2 = 0; + nt_devmode->panningwidth = 0; + nt_devmode->panningheight = 0; + + nt_devmode->private=NULL; +} + + +/* error code: + 0: everything OK + 1: level not implemented + 2: file doesn't exist + 3: can't allocate memory + 4: can't free memory + 5: non existant struct +*/ + +/* + A printer and a printer driver are 2 different things. + NT manages them separatelly, Samba does the same. + Why ? Simply because it's easier and it makes sense ! + + Now explanation: You have 3 printers behind your samba server, + 2 of them are the same make and model (laser A and B). But laser B + has an 3000 sheet feeder and laser A doesn't such an option. + Your third printer is an old dot-matrix model for the accounting :-). + + If the /usr/local/samba/lib directory (default dir), you will have + 5 files to describe all of this. + + 3 files for the printers (1 by printer): + NTprinter_laser A + NTprinter_laser B + NTprinter_accounting + 2 files for the drivers (1 for the laser and 1 for the dot matrix) + NTdriver_printer model X + NTdriver_printer model Y + +jfm: I should use this comment for the text file to explain + same thing for the forms BTW. + Je devrais mettre mes commentaires en francais, ca serait mieux :-) + +*/ + + |