summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c296
1 files changed, 227 insertions, 69 deletions
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index c9d81e1cba..b675175544 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -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 (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
+ path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
+ else
+ path = tmpdir();
+
+ slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
+ slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
+
+ 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((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;
+ 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;
+ }
- DEBUG(10,("enumports_level_1: port name %s\n", PRINTERNAME(snum)));
+ 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]);
+ }
- 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));
+ file_lines_free(qlines);
+ }
- if (strequal(port_name, PRINTERNAME(snum)))
- break;
- }
+ *returned = numlines;
- if (j < i)
- continue;
+ } else {
+ *returned = 1; /* Sole Samba port returned. */
- DEBUGADD(6,("Filling port number [%d]\n", i));
- fill_port_1(&ports[i], PRINTERNAME(snum));
- i++;
- }
- }
+ 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));
- *returned = i;
+ 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 (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
+ path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
+ else
+ path = tmpdir();
+
+ slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
+ slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
+
+ 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((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;
+ 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;
+ }
- DEBUG(10,("enumports_level_2: port name %s\n", PRINTERNAME(snum)));
+ 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]);
+ }
- 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));
+ file_lines_free(qlines);
+ }
- if (strequal(port_name, PRINTERNAME(snum)))
- break;
- }
+ *returned = numlines;
- if (j < i)
- continue;
+ } else {
- DEBUGADD(6,("Filling port number [%d]\n", i));
- fill_port_2(&ports[i], PRINTERNAME(snum));
- i++;
- }
- }
+ *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));
- *returned = i;
+ fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
+ }
/* check the required size. */
for (i=0; i<*returned; i++) {
@@ -4083,6 +4177,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,
const SPOOL_PRINTER_INFO_LEVEL *info,
uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
@@ -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;
}