mirror of
https://github.com/samba-team/samba.git
synced 2025-01-24 02:04:21 +03:00
Added John Reilly's enumports/addprinter/delprinter scripting code plus the
fix for the Win9x printer drivers. Changed command names to add "command" string on the end for some consistancy with the other scripting commands. Added '%P' option to tdbpack/unpack to store long comment string. Made port name be "Samba Printer Port" if no enum port script given. Fixed prs_uint32_pre code to cope with null args. Jeremy. (This used to be commit 902ada63799cf27924c72e24e7593a8c9fb5eba9)
This commit is contained in:
parent
2759822674
commit
49fcb300de
@ -239,7 +239,7 @@ typedef struct nt_printer_info_level_2
|
||||
fstring sharename;
|
||||
fstring portname;
|
||||
fstring drivername;
|
||||
fstring comment;
|
||||
pstring comment;
|
||||
fstring location;
|
||||
NT_DEVICEMODE *devmode;
|
||||
fstring sepfile;
|
||||
|
@ -1302,6 +1302,9 @@ char *lp_configfile(void);
|
||||
char *lp_smb_passwd_file(void);
|
||||
char *lp_serverstring(void);
|
||||
char *lp_printcapname(void);
|
||||
char *lp_enumports_cmd(void);
|
||||
char *lp_addprinter_cmd(void);
|
||||
char *lp_deleteprinter_cmd(void);
|
||||
char *lp_lockdir(void);
|
||||
char *lp_utmpdir(void);
|
||||
char *lp_rootdir(void);
|
||||
@ -1530,6 +1533,7 @@ BOOL lp_snum_ok(int iService);
|
||||
void lp_add_one_printer(char *name, char *comment);
|
||||
BOOL lp_loaded(void);
|
||||
void lp_killunused(BOOL (*snumused) (int));
|
||||
void lp_killservice(int iServiceIn);
|
||||
BOOL lp_load(char *pszFname, BOOL global_only, BOOL save_defaults,
|
||||
BOOL add_ipc);
|
||||
void lp_resetnumservices(void);
|
||||
@ -1654,6 +1658,7 @@ BOOL trust_password_delete(char *domain);
|
||||
|
||||
/*The following definitions come from printing/load.c */
|
||||
|
||||
void add_all_printers(void);
|
||||
void load_printers(void);
|
||||
|
||||
/*The following definitions come from printing/lpq_parse.c */
|
||||
|
@ -104,6 +104,9 @@ static BOOL defaults_saved = False;
|
||||
typedef struct
|
||||
{
|
||||
char *szPrintcapname;
|
||||
char *szEnumPortsCommand;
|
||||
char *szAddPrinterCommand;
|
||||
char *szDeletePrinterCommand;
|
||||
char *szLockDir;
|
||||
char *szRootdir;
|
||||
char *szDefaultService;
|
||||
@ -793,6 +796,10 @@ static struct parm_struct parm_table[] = {
|
||||
{"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
|
||||
{"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
|
||||
|
||||
{"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, 0},
|
||||
{"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, 0},
|
||||
{"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, 0},
|
||||
|
||||
{"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
|
||||
{"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, 0},
|
||||
{"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL, NULL, FLAG_PRINT},
|
||||
@ -1317,6 +1324,9 @@ FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
|
||||
FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
|
||||
FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
|
||||
FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
|
||||
FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
|
||||
FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
|
||||
FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
|
||||
FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
|
||||
#ifdef WITH_UTMP
|
||||
FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
|
||||
@ -3007,6 +3017,18 @@ void lp_killunused(BOOL (*snumused) (int))
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
unload a service
|
||||
***************************************************************************/
|
||||
void lp_killservice(int iServiceIn)
|
||||
{
|
||||
if (VALID(iServiceIn))
|
||||
{
|
||||
iSERVICE(iServiceIn).valid = False;
|
||||
free_service(pSERVICE(iServiceIn));
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
save the curent values of all global and sDefault parameters into the
|
||||
defaults union. This allows swat and testparm to show only the
|
||||
|
@ -25,7 +25,7 @@
|
||||
/***************************************************************************
|
||||
auto-load printer services
|
||||
***************************************************************************/
|
||||
static void add_all_printers(void)
|
||||
void add_all_printers(void)
|
||||
{
|
||||
int printers = lp_servicenumber(PRINTERS_NAME);
|
||||
|
||||
|
@ -387,7 +387,6 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
|
||||
{
|
||||
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
|
||||
fstring architecture;
|
||||
fstring clean_driver_name;
|
||||
pstring new_dir;
|
||||
pstring old_name;
|
||||
pstring new_name;
|
||||
@ -406,10 +405,6 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
|
||||
|
||||
get_short_archi(architecture, driver->environment);
|
||||
|
||||
/* clean up the driver's name */
|
||||
fstrcpy(clean_driver_name, driver->name);
|
||||
all_string_sub(clean_driver_name, "/", "#", 0);
|
||||
|
||||
/* connect to the print$ share under the same account as the user connected to the rpc pipe */
|
||||
fstrcpy(user_name, uidtoname(user->uid));
|
||||
DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
|
||||
@ -447,18 +442,22 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
|
||||
slprintf(new_dir, sizeof(new_dir), "%s\\%d", architecture, driver->cversion);
|
||||
mkdir_internal(conn, inbuf, outbuf, new_dir);
|
||||
|
||||
slprintf(new_dir, sizeof(new_dir), "%s\\%d\\%s", architecture, driver->cversion, clean_driver_name);
|
||||
mkdir_internal(conn, inbuf, outbuf, new_dir);
|
||||
|
||||
/* move all the files, one by one,
|
||||
* from archi\filexxx.yyy to
|
||||
* archi\version\driver name\filexxx.yyy
|
||||
* archi\version\filexxx.yyy
|
||||
*
|
||||
* Note: drivers may list the same file name in several places. This
|
||||
* causes problems on a second attempt to move the file. JRR
|
||||
*
|
||||
* Note: use the replace flag on rename_internals() call, otherwise it
|
||||
* is very difficult to change previously installed drivers... the Windows
|
||||
* GUI offers the user the choice to replace or keep exisitng driver. JRR
|
||||
*/
|
||||
|
||||
DEBUG(5,("Moving file now !\n"));
|
||||
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->driverpath);
|
||||
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->driverpath);
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
|
||||
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
|
||||
old_name, new_name ));
|
||||
close_cnum(conn, user->vuid);
|
||||
@ -466,45 +465,61 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!strequal(driver->datafile, driver->driverpath)) {
|
||||
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->datafile);
|
||||
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->datafile);
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
|
||||
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
|
||||
old_name, new_name ));
|
||||
close_cnum(conn, user->vuid);
|
||||
unbecome_root();
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strequal(driver->configfile, driver->driverpath) &&
|
||||
!strequal(driver->configfile, driver->datafile)) {
|
||||
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->configfile);
|
||||
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->configfile);
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
|
||||
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
|
||||
old_name, new_name ));
|
||||
close_cnum(conn, user->vuid);
|
||||
unbecome_root();
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strequal(driver->helpfile, driver->driverpath) &&
|
||||
!strequal(driver->helpfile, driver->datafile) &&
|
||||
!strequal(driver->helpfile, driver->configfile)) {
|
||||
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->helpfile);
|
||||
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->helpfile);
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, False)) != 0) {
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
|
||||
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
|
||||
old_name, new_name ));
|
||||
close_cnum(conn, user->vuid);
|
||||
unbecome_root();
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
if (driver->dependentfiles) {
|
||||
for (i=0; *driver->dependentfiles[i]; i++) {
|
||||
if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
|
||||
!strequal(driver->dependentfiles[i], driver->datafile) &&
|
||||
!strequal(driver->dependentfiles[i], driver->configfile) &&
|
||||
!strequal(driver->dependentfiles[i], driver->helpfile)) {
|
||||
slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->dependentfiles[i]);
|
||||
slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->dependentfiles[i]);
|
||||
/*
|
||||
* We don't check the error returns here as several of these
|
||||
* files may have already been moved in the list above...
|
||||
*/
|
||||
rename_internals(conn, inbuf, outbuf, old_name, new_name, False);
|
||||
if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
|
||||
DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
|
||||
old_name, new_name ));
|
||||
close_cnum(conn, user->vuid);
|
||||
unbecome_root();
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,7 +536,6 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
|
||||
int len, buflen;
|
||||
fstring architecture;
|
||||
pstring directory;
|
||||
fstring clean_driver_name;
|
||||
pstring temp_name;
|
||||
pstring key;
|
||||
char *buf;
|
||||
@ -530,16 +544,12 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
|
||||
|
||||
get_short_archi(architecture, driver->environment);
|
||||
|
||||
/* The names are relative. We store them in the form: \print$\arch\version\printer-name\driver.xxx
|
||||
/* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
|
||||
* \\server is added in the rpc server layer.
|
||||
* It does make sense to NOT store the server's name in the printer TDB.
|
||||
*/
|
||||
|
||||
/* clean up the driver's name */
|
||||
fstrcpy(clean_driver_name, driver->name);
|
||||
all_string_sub(clean_driver_name, "/", "#", 0);
|
||||
|
||||
slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\%s\\", architecture, driver->cversion, clean_driver_name);
|
||||
slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
|
||||
|
||||
|
||||
fstrcpy(temp_name, driver->driverpath);
|
||||
@ -752,12 +762,16 @@ uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
|
||||
DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
|
||||
|
||||
/*pstrcat(line, info3->name); pstrcat(line, ":");*/
|
||||
trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
|
||||
pstrcat(line, info3->configfile);
|
||||
pstrcat(line, ":");
|
||||
trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
|
||||
pstrcat(line, info3->datafile);
|
||||
pstrcat(line, ":");
|
||||
trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
|
||||
pstrcat(line, info3->helpfile);
|
||||
pstrcat(line, ":");
|
||||
trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
|
||||
pstrcat(line, info3->monitorname);
|
||||
pstrcat(line, ":");
|
||||
pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
|
||||
@ -766,6 +780,7 @@ uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
|
||||
for (i=0; info3->dependentfiles &&
|
||||
*info3->dependentfiles[i]; i++) {
|
||||
if (i) pstrcat(line, ","); /* don't end in a "," */
|
||||
trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
|
||||
pstrcat(line, info3->dependentfiles[i]);
|
||||
}
|
||||
|
||||
@ -969,7 +984,7 @@ static uint32 add_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
|
||||
|
||||
again:
|
||||
len = 0;
|
||||
len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffffffff",
|
||||
len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
|
||||
info->attributes,
|
||||
info->priority,
|
||||
info->default_priority,
|
||||
@ -1367,7 +1382,7 @@ static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin
|
||||
fstrcpy(info.printername, sharename);
|
||||
fstrcpy(info.portname, sharename);
|
||||
fstrcpy(info.drivername, lp_printerdriver(snum));
|
||||
fstrcpy(info.comment, "");
|
||||
pstrcpy(info.comment, "");
|
||||
fstrcpy(info.printprocessor, "winprint");
|
||||
fstrcpy(info.datatype, "RAW");
|
||||
|
||||
@ -1428,7 +1443,7 @@ static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharen
|
||||
if (!dbuf.dptr) return 1;
|
||||
#endif
|
||||
|
||||
len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffffffff",
|
||||
len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
|
||||
&info.attributes,
|
||||
&info.priority,
|
||||
&info.default_priority,
|
||||
|
@ -867,7 +867,7 @@ BOOL prs_uint16_post(char *name, prs_struct *ps, int depth, uint16 *data16,
|
||||
BOOL prs_uint32_pre(char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset)
|
||||
{
|
||||
*offset = ps->data_offset;
|
||||
if (UNMARSHALLING(ps)) {
|
||||
if (UNMARSHALLING(ps) && (data32 != NULL)) {
|
||||
/* reading. */
|
||||
return prs_uint32(name, ps, depth, data32);
|
||||
} else {
|
||||
|
@ -1778,7 +1778,7 @@ BOOL new_smb_io_printer_info_2(char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 *i
|
||||
{
|
||||
uint32 sec_offset;
|
||||
prs_struct *ps=&buffer->prs;
|
||||
int i = 0;
|
||||
uint32 dummy = 0;
|
||||
|
||||
prs_debug(ps, depth, desc, "new_smb_io_printer_info_2");
|
||||
depth++;
|
||||
@ -1814,7 +1814,7 @@ BOOL new_smb_io_printer_info_2(char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 *i
|
||||
return False;
|
||||
|
||||
#if 1 /* JFMTEST */
|
||||
if (!prs_uint32_pre("secdesc_ptr ", ps, depth, &i, &sec_offset))
|
||||
if (!prs_uint32_pre("secdesc_ptr ", ps, depth, &dummy, &sec_offset))
|
||||
return False;
|
||||
#else
|
||||
if (!new_smb_io_relsecdesc("secdesc", buffer, depth, &info->secdesc))
|
||||
|
@ -28,6 +28,10 @@
|
||||
extern int DEBUGLEVEL;
|
||||
extern pstring global_myname;
|
||||
|
||||
#ifndef SAMBA_PRINTER_PORT_NAME
|
||||
#define SAMBA_PRINTER_PORT_NAME "Samba Printer Port"
|
||||
#endif
|
||||
|
||||
#ifndef MAX_OPEN_PRINTER_EXS
|
||||
#define MAX_OPEN_PRINTER_EXS 50
|
||||
#endif
|
||||
@ -217,6 +221,45 @@ static BOOL delete_printer_handle(POLICY_HND *hnd)
|
||||
return False;
|
||||
}
|
||||
|
||||
if (*lp_deleteprinter_cmd()) {
|
||||
|
||||
pid_t local_pid = sys_getpid();
|
||||
char *cmd = lp_deleteprinter_cmd();
|
||||
char *path;
|
||||
pstring tmp_file;
|
||||
pstring command;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
|
||||
path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
|
||||
else
|
||||
path = tmpdir();
|
||||
|
||||
/* Printer->dev.handlename equals portname equals sharename */
|
||||
slprintf(command, sizeof(command), "%s \"%s\"", cmd,
|
||||
Printer->dev.handlename);
|
||||
slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
|
||||
|
||||
unlink(tmp_file);
|
||||
DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
|
||||
ret = smbrun(command, tmp_file, False);
|
||||
if (ret != 0) {
|
||||
unlink(tmp_file);
|
||||
return False;
|
||||
}
|
||||
DEBUGADD(10,("returned [%d]\n", ret));
|
||||
DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
|
||||
unlink(tmp_file);
|
||||
|
||||
if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
|
||||
lp_remove_service( i );
|
||||
lp_killservice( i );
|
||||
return True;
|
||||
} else
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
@ -3204,7 +3247,7 @@ static uint32 update_printer(POLICY_HND *handle, uint32 level,
|
||||
*/
|
||||
|
||||
if (!check_printer_ok(printer->info_2, snum)) {
|
||||
result = ERROR_ACCESS_DENIED;
|
||||
result = ERROR_INVALID_PARAMETER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -3914,46 +3957,71 @@ static void fill_port_2(PORT_INFO_2 *port, char *name)
|
||||
****************************************************************************/
|
||||
static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
|
||||
{
|
||||
int n_services=lp_numservices();
|
||||
int snum;
|
||||
int i=0;
|
||||
|
||||
PORT_INFO_1 *ports=NULL;
|
||||
int i=0;
|
||||
|
||||
for (snum=0; snum<n_services; snum++)
|
||||
if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
|
||||
(*returned)++;
|
||||
if (*lp_enumports_cmd()) {
|
||||
pid_t local_pid = sys_getpid();
|
||||
char *cmd = lp_enumports_cmd();
|
||||
char *path;
|
||||
char **qlines;
|
||||
pstring tmp_file;
|
||||
pstring command;
|
||||
int numlines;
|
||||
int ret;
|
||||
|
||||
if((ports=(PORT_INFO_1 *)malloc( (*returned+1) * sizeof(PORT_INFO_1) )) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
for (snum=0; snum<n_services; snum++) {
|
||||
if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
|
||||
/*
|
||||
* Ensure this port name is unique.
|
||||
*/
|
||||
int j;
|
||||
if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
|
||||
path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
|
||||
else
|
||||
path = tmpdir();
|
||||
|
||||
DEBUG(10,("enumports_level_1: port name %s\n", PRINTERNAME(snum)));
|
||||
slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
|
||||
slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
|
||||
|
||||
for(j = 0; j < i; j++) {
|
||||
fstring port_name;
|
||||
unistr_to_dos(port_name, (const char *)&ports[j].port_name.buffer[0], sizeof(port_name));
|
||||
unlink(tmp_file);
|
||||
DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
|
||||
ret = smbrun(command, tmp_file, False);
|
||||
DEBUG(10,("Returned [%d]\n", ret));
|
||||
if (ret != 0) {
|
||||
unlink(tmp_file);
|
||||
// Is this the best error to return here?
|
||||
return ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (strequal(port_name, PRINTERNAME(snum)))
|
||||
break;
|
||||
numlines = 0;
|
||||
qlines = file_lines_load(tmp_file, &numlines);
|
||||
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
|
||||
DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
|
||||
DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
|
||||
unlink(tmp_file);
|
||||
|
||||
if(numlines) {
|
||||
if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
|
||||
DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
|
||||
file_lines_free(qlines);
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
if (j < i)
|
||||
continue;
|
||||
for (i=0; i<numlines; i++) {
|
||||
DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
|
||||
fill_port_1(&ports[i], qlines[i]);
|
||||
}
|
||||
|
||||
DEBUGADD(6,("Filling port number [%d]\n", i));
|
||||
fill_port_1(&ports[i], PRINTERNAME(snum));
|
||||
i++;
|
||||
file_lines_free(qlines);
|
||||
}
|
||||
}
|
||||
|
||||
*returned = i;
|
||||
*returned = numlines;
|
||||
|
||||
} else {
|
||||
*returned = 1; /* Sole Samba port returned. */
|
||||
|
||||
if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
|
||||
|
||||
fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
|
||||
}
|
||||
|
||||
/* check the required size. */
|
||||
for (i=0; i<*returned; i++) {
|
||||
@ -3988,46 +4056,72 @@ static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need
|
||||
|
||||
static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
|
||||
{
|
||||
int n_services=lp_numservices();
|
||||
int snum;
|
||||
int i=0;
|
||||
|
||||
PORT_INFO_2 *ports=NULL;
|
||||
int i=0;
|
||||
|
||||
for (snum=0; snum<n_services; snum++)
|
||||
if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
|
||||
(*returned)++;
|
||||
if (*lp_enumports_cmd()) {
|
||||
pid_t local_pid = sys_getpid();
|
||||
char *cmd = lp_enumports_cmd();
|
||||
char *path;
|
||||
char **qlines;
|
||||
pstring tmp_file;
|
||||
pstring command;
|
||||
int numlines;
|
||||
int ret;
|
||||
|
||||
if((ports=(PORT_INFO_2 *)malloc( (*returned+1) * sizeof(PORT_INFO_2) )) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
for (snum=0; snum<n_services; snum++) {
|
||||
if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
|
||||
/*
|
||||
* Ensure this port name is unique.
|
||||
*/
|
||||
int j;
|
||||
if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
|
||||
path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
|
||||
else
|
||||
path = tmpdir();
|
||||
|
||||
DEBUG(10,("enumports_level_2: port name %s\n", PRINTERNAME(snum)));
|
||||
slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
|
||||
slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
|
||||
|
||||
for(j = 0; j < i; j++) {
|
||||
fstring port_name;
|
||||
unistr_to_dos(port_name, (const char *)&ports[j].port_name.buffer[0], sizeof(port_name));
|
||||
unlink(tmp_file);
|
||||
DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
|
||||
ret = smbrun(command, tmp_file, False);
|
||||
DEBUGADD(10,("returned [%d]\n", ret));
|
||||
if (ret != 0) {
|
||||
unlink(tmp_file);
|
||||
// Is this the best error to return here?
|
||||
return ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (strequal(port_name, PRINTERNAME(snum)))
|
||||
break;
|
||||
numlines = 0;
|
||||
qlines = file_lines_load(tmp_file, &numlines);
|
||||
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
|
||||
DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
|
||||
DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
|
||||
unlink(tmp_file);
|
||||
|
||||
if(numlines) {
|
||||
if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
|
||||
DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
|
||||
file_lines_free(qlines);
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
if (j < i)
|
||||
continue;
|
||||
for (i=0; i<numlines; i++) {
|
||||
DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
|
||||
fill_port_2(&(ports[i]), qlines[i]);
|
||||
}
|
||||
|
||||
DEBUGADD(6,("Filling port number [%d]\n", i));
|
||||
fill_port_2(&ports[i], PRINTERNAME(snum));
|
||||
i++;
|
||||
file_lines_free(qlines);
|
||||
}
|
||||
}
|
||||
|
||||
*returned = i;
|
||||
*returned = numlines;
|
||||
|
||||
} else {
|
||||
|
||||
*returned = 1;
|
||||
|
||||
if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
|
||||
DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
|
||||
|
||||
fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
|
||||
}
|
||||
|
||||
/* check the required size. */
|
||||
for (i=0; i<*returned; i++) {
|
||||
@ -4081,6 +4175,68 @@ uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
****************************************************************************/
|
||||
static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
|
||||
{
|
||||
pid_t local_pid = sys_getpid();
|
||||
char *cmd = lp_addprinter_cmd();
|
||||
char *path;
|
||||
char **qlines;
|
||||
pstring tmp_file;
|
||||
pstring command;
|
||||
pstring driverlocation;
|
||||
int numlines;
|
||||
int ret;
|
||||
|
||||
if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
|
||||
path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
|
||||
else
|
||||
path = tmpdir();
|
||||
|
||||
/* build driver path... only 9X architecture is needed for legacy reasons */
|
||||
slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
|
||||
global_myname);
|
||||
/* change \ to \\ for the shell */
|
||||
all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
|
||||
|
||||
slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
|
||||
slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
|
||||
cmd, printer->info_2->printername, printer->info_2->sharename,
|
||||
printer->info_2->portname, printer->info_2->drivername,
|
||||
printer->info_2->location, driverlocation);
|
||||
|
||||
unlink(tmp_file);
|
||||
DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
|
||||
ret = smbrun(command, tmp_file, False);
|
||||
DEBUGADD(10,("returned [%d]\n", ret));
|
||||
|
||||
if ( ret != 0 ) {
|
||||
unlink(tmp_file);
|
||||
free_a_printer(&printer,2);
|
||||
return False;
|
||||
}
|
||||
|
||||
numlines = 0;
|
||||
qlines = file_lines_load(tmp_file, &numlines);
|
||||
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
|
||||
DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
|
||||
DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
|
||||
unlink(tmp_file);
|
||||
|
||||
if(numlines) {
|
||||
// Set the portname to what the script says the portname should be
|
||||
strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
|
||||
|
||||
// Send SIGHUP to process group... is there a better way?
|
||||
kill(0, SIGHUP);
|
||||
add_all_printers();
|
||||
}
|
||||
|
||||
file_lines_free(qlines);
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
****************************************************************************/
|
||||
static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
|
||||
@ -4091,7 +4247,6 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
|
||||
{
|
||||
NT_PRINTER_INFO_LEVEL *printer = NULL;
|
||||
fstring name;
|
||||
fstring share_name;
|
||||
int snum;
|
||||
|
||||
if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
|
||||
@ -4104,11 +4259,14 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
|
||||
/* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
|
||||
convert_printer_info(info, printer, 2);
|
||||
|
||||
unistr2_to_ascii(share_name, &info->info_2->sharename, sizeof(share_name)-1);
|
||||
if (*lp_addprinter_cmd() )
|
||||
if ( !add_printer_hook(printer) )
|
||||
return ERROR_ACCESS_DENIED;
|
||||
|
||||
slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname, share_name);
|
||||
slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
|
||||
printer->info_2->sharename);
|
||||
|
||||
if ((snum = print_queue_snum(share_name)) == -1) {
|
||||
if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
|
||||
free_a_printer(&printer,2);
|
||||
return ERROR_ACCESS_DENIED;
|
||||
}
|
||||
@ -4119,7 +4277,7 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
|
||||
|
||||
if (!check_printer_ok(printer->info_2, snum)) {
|
||||
free_a_printer(&printer,2);
|
||||
return ERROR_ACCESS_DENIED;
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* write the ASCII on disk */
|
||||
@ -4130,7 +4288,7 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
|
||||
|
||||
if (!open_printer_hnd(handle, name)) {
|
||||
/* Handle open failed - remove addition. */
|
||||
del_a_printer(share_name);
|
||||
del_a_printer(printer->info_2->sharename);
|
||||
free_a_printer(&printer,2);
|
||||
return ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
@ -495,11 +495,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
|
||||
print_status_struct* status)
|
||||
{
|
||||
int i;
|
||||
BOOL ok = False;
|
||||
BOOL ok;
|
||||
pstring tok,driver,datafile,langmon,helpfile,datatype;
|
||||
char *p;
|
||||
char **lines;
|
||||
char *line = NULL;
|
||||
char **lines = NULL;
|
||||
pstring gen_line;
|
||||
|
||||
/*
|
||||
@ -512,23 +511,18 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
|
||||
p = gen_line;
|
||||
DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
|
||||
} else {
|
||||
/* didn't find driver in tdb either... oh well */
|
||||
DEBUG(10,("9x driver not found in tdb\n"));
|
||||
}
|
||||
/* didn't find driver in tdb */
|
||||
|
||||
DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
|
||||
snum, lp_printerdriver(snum), lp_driverfile(snum)));
|
||||
|
||||
lines = file_lines_load(lp_driverfile(snum),NULL);
|
||||
|
||||
if (!lines) {
|
||||
DEBUG(3,("fill_printq_info: Can't open %s - %s\n",
|
||||
lp_driverfile(snum),strerror(errno)));
|
||||
DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
|
||||
desc->errcode=NERR_notsupported;
|
||||
return;
|
||||
} else {
|
||||
/* lookup the long printer driver name in the file
|
||||
description */
|
||||
/* lookup the long printer driver name in the file description */
|
||||
for (i=0;lines[i] && !ok;i++) {
|
||||
p = lines[i];
|
||||
if (next_token(&p,tok,":",sizeof(tok)) &&
|
||||
@ -537,16 +531,10 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
|
||||
ok = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
goto err;
|
||||
|
||||
if ((line = strdup(p)) == NULL)
|
||||
goto err;
|
||||
|
||||
p = line;
|
||||
file_lines_free(lines);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
/* driver file name */
|
||||
if (!next_token(&p,driver,":",sizeof(driver)))
|
||||
goto err;
|
||||
@ -588,9 +576,11 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
|
||||
PACKS(desc,"z",datatype); /* default data type */
|
||||
PACKS(desc,"z",helpfile); /* helpfile name */
|
||||
PACKS(desc,"z",driver); /* driver name */
|
||||
DEBUG(3,("lp_printerdriver:%s:\n",lp_printerdriver(snum)));
|
||||
DEBUG(3,("Driver:%s:\n",driver));
|
||||
DEBUG(3,("Data File:%s:\n",datafile));
|
||||
DEBUG(3,("Language Monitor:%s:\n",langmon));
|
||||
DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
|
||||
DEBUG(3,("Data Type:%s:\n",datatype));
|
||||
DEBUG(3,("Help File:%s:\n",helpfile));
|
||||
PACKI(desc,"N",count); /* number of files to copy */
|
||||
@ -607,15 +597,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
|
||||
DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
|
||||
SERVICE(snum),count));
|
||||
|
||||
free(line);
|
||||
desc->errcode=NERR_Success;
|
||||
file_lines_free(lines);
|
||||
return;
|
||||
}
|
||||
|
||||
err:
|
||||
|
||||
DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
|
||||
desc->errcode=NERR_notsupported;
|
||||
if (line)
|
||||
free(line);
|
||||
file_lines_free(lines);
|
||||
}
|
||||
|
||||
|
||||
@ -697,64 +688,67 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
|
||||
/* This function returns the number of files for a given driver */
|
||||
static int get_printerdrivernumber(int snum)
|
||||
{
|
||||
int i=0,ok=0;
|
||||
int i;
|
||||
BOOL ok;
|
||||
pstring tok;
|
||||
char *p;
|
||||
char **lines, *line;
|
||||
char **lines = NULL;
|
||||
pstring gen_line;
|
||||
|
||||
/*
|
||||
* Check in the tdb *first* before checking the legacy
|
||||
* files. This allows an NT upload to take precedence over
|
||||
* the existing fileset. JRA.
|
||||
*/
|
||||
|
||||
if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum))) == True ) {
|
||||
p = gen_line;
|
||||
DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", lp_printerdriver(snum), gen_line));
|
||||
} else {
|
||||
/* didn't find driver in tdb */
|
||||
|
||||
DEBUG(10,("snum: %d\nlp_printerdriver: [%s]\nlp_driverfile: [%s]\n",
|
||||
snum, lp_printerdriver(snum), lp_driverfile(snum)));
|
||||
|
||||
lines = file_lines_load(lp_driverfile(snum), NULL);
|
||||
if (!lines) {
|
||||
DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",
|
||||
lp_driverfile(snum),strerror(errno)));
|
||||
DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* lookup the long printer driver name in the file
|
||||
description */
|
||||
/* lookup the long printer driver name in the file description */
|
||||
for (i=0;lines[i] && !ok;i++) {
|
||||
p = lines[i];
|
||||
if (next_token(&p,tok,":",sizeof(tok)) &&
|
||||
(strlen(lp_printerdriver(snum)) == strlen(tok)) &&
|
||||
(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
|
||||
ok=1;
|
||||
ok = True;
|
||||
}
|
||||
}
|
||||
|
||||
if( !ok ) {
|
||||
/* no printers.def, or driver not found, check the NT driver tdb */
|
||||
if ((ok = get_a_printer_driver_9x_compatible(gen_line, lp_printerdriver(snum)))==True ) {
|
||||
p = gen_line;
|
||||
DEBUG(10,("9x compatable driver line for [%s]: [%s]\n",
|
||||
lp_printerdriver(snum), gen_line));
|
||||
} else {
|
||||
/* didn't find driver in tdb either... oh well */
|
||||
DEBUG(10,("9x driver not found in tdb\n"));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
line = strdup(p);
|
||||
p = line;
|
||||
file_lines_free(lines);
|
||||
|
||||
if (ok) {
|
||||
if( ok ) {
|
||||
/* skip 5 fields */
|
||||
i = 5;
|
||||
while (*p && i) {
|
||||
if (*p++ == ':') i--;
|
||||
}
|
||||
if (!*p || i)
|
||||
return(0);
|
||||
goto err;
|
||||
|
||||
/* count the number of files */
|
||||
while (next_token(&p,tok,",",sizeof(tok)))
|
||||
i++;
|
||||
}
|
||||
free(line);
|
||||
|
||||
file_lines_free(lines);
|
||||
return(i);
|
||||
}
|
||||
|
||||
err:
|
||||
|
||||
DEBUG(3,("Can't determine number of printer driver files\n"));
|
||||
file_lines_free(lines);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static BOOL api_DosPrintQGetInfo(connection_struct *conn,
|
||||
|
@ -136,6 +136,14 @@ size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
|
||||
SIVAL(buf, 0, d);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
s = va_arg(ap,char *);
|
||||
w = strlen(s);
|
||||
len = w + 1;
|
||||
if (bufsize >= len) {
|
||||
memcpy(buf, s, len);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
s = va_arg(ap,char *);
|
||||
w = strlen(s);
|
||||
@ -211,6 +219,12 @@ int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
|
||||
if (bufsize < len) goto no_space;
|
||||
*p = (void *)IVAL(buf, 0);
|
||||
break;
|
||||
case 'P':
|
||||
s = va_arg(ap,char *);
|
||||
len = strlen(buf) + 1;
|
||||
if (bufsize < len || len > sizeof(pstring)) goto no_space;
|
||||
memcpy(s, buf, len);
|
||||
break;
|
||||
case 'f':
|
||||
s = va_arg(ap,char *);
|
||||
len = strlen(buf) + 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user