[Samba] Re: Win32 services management?

Danny Tylman danny.tylman at insightix.com
Mon Apr 16 14:50:35 GMT 2007


Hi,

Attached is a bzr-diff containing the changes made in order to remotely
create/delete service.

Regards, Danny.

On Sun, 2007-04-15 at 18:55 +0200, Volker Lendecke wrote:
> On Sun, Apr 15, 2007 at 07:30:57PM +0300, Danny Tylman wrote:
> > Is there any such common place? 
> 
> Either try a bzr diff between the SAMBA_3_0.bzr and yours or
> a bzr bundle if you want to show the history. If it's not
> too large, just send it here.
> 
> Volker
-------------- next part --------------
=== modified file 'source/include/doserr.h'
--- source/include/doserr.h	2007-04-12 08:14:03 +0000
+++ source/include/doserr.h	2007-04-15 09:04:05 +0000
@@ -199,6 +199,9 @@
 #define WERR_NO_SUCH_SERVICE W_ERROR(1060)
 #define WERR_INVALID_SERVICE_CONTROL W_ERROR(1052)
 #define WERR_SERVICE_DISABLED W_ERROR(1058)
+#define WERR_SERVICE_MARKED_FOR_DELETE (1072)
+#define WERR_SERVICE_EXISTS W_ERROR(1073)
+#define WERR_DUPLICATE_SERVICE_NAME W_ERROR(1078)
 #define WERR_SERVICE_NEVER_STARTED W_ERROR(1077)
 #define WERR_MACHINE_LOCKED W_ERROR(1271)
 #define WERR_NO_LOGON_SERVERS W_ERROR(1311)

=== modified file 'source/include/rpc_svcctl.h'
--- source/include/rpc_svcctl.h	2006-09-08 14:32:55 +0000
+++ source/include/rpc_svcctl.h	2007-04-15 08:31:41 +0000
@@ -26,11 +26,13 @@
 
 #define SVCCTL_CLOSE_SERVICE			0x00
 #define SVCCTL_CONTROL_SERVICE			0x01
+#define SVCCTL_DELETE_SERVICE			0x02
 #define SVCCTL_LOCK_SERVICE_DB			0x03
 #define SVCCTL_QUERY_SERVICE_SEC		0x04
 #define SVCCTL_SET_SERVICE_SEC			0x05
 #define SVCCTL_QUERY_STATUS			0x06
 #define SVCCTL_UNLOCK_SERVICE_DB		0x08
+#define SVCCTL_CREATE_SERVICE_W			0x0c
 #define SVCCTL_ENUM_DEPENDENT_SERVICES_W	0x0d
 #define SVCCTL_ENUM_SERVICES_STATUS_W		0x0e
 #define SVCCTL_OPEN_SCMANAGER_W			0x0f
@@ -159,6 +161,21 @@
 } SERVICE_CONFIG;
 
 typedef struct {
+	UNISTR2 servicename;
+	UNISTR2 executablepath;
+	UNISTR2 loadordergroup;
+	UNISTR2 startname;
+	UNISTR2 displayname;
+	uint32 service_type;
+	uint32 start_type;
+	uint32 error_control;
+	uint32 tag_id;
+	uint32 access_desired;
+	char *dependencies;
+	char *password;
+} SERVICE_INSTALL_INFO;
+
+typedef struct {
 	uint32 unknown;	
         UNISTR description;
 } SERVICE_DESCRIPTION;
@@ -253,6 +270,18 @@
 /**************************/
 
 typedef struct {
+	POLICY_HND handle;	
+} SVCCTL_Q_DELETE_SERVICE;
+
+typedef struct {
+	WERROR status;
+} SVCCTL_R_DELETE_SERVICE;
+
+/**************************/
+
+/**************************/
+
+typedef struct {
 	POLICY_HND handle;
 	uint32 parmcount;
 	UNISTR4_ARRAY *parameters;
@@ -413,6 +442,31 @@
 	WERROR status;
 } SVCCTL_R_SET_SERVICE_SEC;
 
+/**************************/
+
+typedef struct {
+	POLICY_HND handle;
+	UNISTR2 service_name;
+	UNISTR2 *display_name;
+	uint32 access;
+	uint32 service_type;
+	uint32 start_type;
+	uint32 error_control;
+	UNISTR2 binary_pathname;
+	UNISTR2 load_order_group;
+	uint32* tag_id;
+	RPC_DATA_BLOB dependencies;	
+	uint32 dependencies_size;
+	UNISTR2 *service_start_name;
+	RPC_DATA_BLOB password;
+	uint32 password_size;
+} SVCCTL_Q_CREATE_SERVICE;
+
+typedef struct {
+	POLICY_HND handle;
+	uint32 tag_id;
+	WERROR status;
+} SVCCTL_R_CREATE_SERVICE;
 
 #endif /* _RPC_SVCCTL_H */
 

=== modified file 'source/libsmb/doserr.c'
--- source/libsmb/doserr.c	2007-04-12 08:14:08 +0000
+++ source/libsmb/doserr.c	2007-04-15 09:04:12 +0000
@@ -80,6 +80,10 @@
 	{ "WERR_REG_IO_FAILURE", WERR_REG_IO_FAILURE },
 	{ "WERR_REG_FILE_INVALID", WERR_REG_FILE_INVALID },
 	{ "WERR_SERVICE_DISABLED", WERR_SERVICE_DISABLED },
+	{ "WERR_SERVICE_EXISTS", WERR_SERVICE_EXISTS },
+	{ "WERR_DUPLICATE_SERVICE_NAME", WERR_DUPLICATE_SERVICE_NAME },
+	{ "WERR_NO_SUCH_SERVICE", WERR_NO_SUCH_SERVICE },
+	{ "WERR_SERVICE_MARKED_FOR_DELETE", WERR_SERVICE_MARKED_FOR_DELETE },
 	{ NULL, W_ERROR(0) }
 };
 

=== modified file 'source/rpc_client/cli_svcctl.c'
--- source/rpc_client/cli_svcctl.c	2006-09-08 14:32:39 +0000
+++ source/rpc_client/cli_svcctl.c	2007-04-15 08:40:21 +0000
@@ -328,6 +328,30 @@
 
 /*******************************************************************
 *******************************************************************/
+WERROR rpccli_svcctl_delete_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                 POLICY_HND *hService )
+{
+	SVCCTL_Q_DELETE_SERVICE in;
+	SVCCTL_R_DELETE_SERVICE out;
+	prs_struct qbuf, rbuf;
+	
+	ZERO_STRUCT(in);
+	ZERO_STRUCT(out);
+	
+	memcpy( &in.handle, hService, sizeof(POLICY_HND) );
+		
+	CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_DELETE_SERVICE,
+	            in, out, 
+	            qbuf, rbuf,
+	            svcctl_io_q_delete_service,
+	            svcctl_io_r_delete_service,
+	            WERR_GENERAL_FAILURE );
+	
+	return out.status;
+}
+
+/*******************************************************************
+*******************************************************************/
 
 WERROR rpccli_svcctl_start_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hService,
@@ -431,3 +455,67 @@
 	
 	return out.status;
 }
+
+/*******************************************************************
+*******************************************************************/
+
+WERROR rpccli_svcctl_create_service(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
+                              POLICY_HND *hSCM, POLICY_HND *hService, SERVICE_INSTALL_INFO* install_info)
+{
+	SVCCTL_Q_CREATE_SERVICE in;
+	SVCCTL_R_CREATE_SERVICE out;
+	prs_struct qbuf, rbuf;	
+
+	ZERO_STRUCT(in);
+	ZERO_STRUCT(out);
+
+	/* uint32 types */
+	in.access = install_info->access_desired;
+	in.service_type = install_info->service_type;
+	in.start_type = install_info->start_type;
+	in.error_control = install_info->error_control;
+	in.dependencies_size = 0; /* not in use yet */
+	in.password_size = 0; /* not in use yet */
+
+	/* UNISTR2 types */
+	copy_unistr2(&in.service_name,&install_info->servicename);
+	copy_unistr2(&in.binary_pathname,&install_info->executablepath);			
+	copy_unistr2(&in.load_order_group,&install_info->loadordergroup);
+
+	/* UNISTR2 * types */
+	in.display_name = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+	copy_unistr2(in.display_name,&install_info->displayname);	
+	in.service_start_name = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+	copy_unistr2(in.service_start_name,&install_info->startname);
+
+	/* RPC_DATA_BLOB */
+	int len = 0;
+	if (install_info->dependencies) {
+		len = strlen(install_info->dependencies);
+		init_rpc_blob_str(&in.dependencies, install_info->dependencies, len);
+	}
+	if (install_info->password) {
+		len = strlen(install_info->password);
+		init_rpc_blob_str(&in.password, install_info->password, len);
+
+	}
+
+	/* other pointers */	
+	memcpy( &in.tag_id,&install_info->tag_id,sizeof(uint32));	
+	memcpy( &in.handle, hSCM, sizeof(POLICY_HND) );
+
+	CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CREATE_SERVICE_W, 
+	            in, out, 
+	            qbuf, rbuf,
+	            svcctl_io_q_create_service,
+	            svcctl_io_r_create_service, 
+	            WERR_GENERAL_FAILURE );
+	
+	if ( !W_ERROR_IS_OK( out.status ) )
+		return out.status;
+
+	memcpy( hService, &out.handle, sizeof(POLICY_HND) );
+
+	return out.status;
+}
+

=== modified file 'source/rpc_parse/parse_svcctl.c'
--- source/rpc_parse/parse_svcctl.c	2006-09-08 14:32:52 +0000
+++ source/rpc_parse/parse_svcctl.c	2007-04-15 08:39:05 +0000
@@ -246,6 +246,108 @@
 /*******************************************************************
 ********************************************************************/
 
+BOOL svcctl_io_q_create_service(const char *desc, SVCCTL_Q_CREATE_SERVICE *q_u, prs_struct *ps, int depth)
+{   
+	if (q_u == NULL)
+		return False;
+
+	prs_debug(ps, depth, desc, "svcctl_io_q_create_service");
+	depth++;
+
+	 if(!prs_align(ps))
+		return False;
+
+	if(!smb_io_pol_hnd("handle", &q_u->handle, ps, depth))
+		return False;
+
+
+	if(!smb_io_unistr2("service_name", &q_u->service_name, 1, ps, depth))
+		return False;
+	if(!prs_align(ps))
+		return False;
+	
+	if(!prs_pointer("display_name", ps, depth, (void*)&q_u->display_name, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+		return False;
+	if(!prs_align(ps))
+		return False;
+
+	if(!prs_uint32("access", ps, depth, &q_u->access))
+		return False;
+
+	if(!prs_uint32("service_type", ps, depth, &q_u->service_type))
+		return False;
+
+	if(!prs_uint32("start_type", ps, depth, &q_u->start_type))
+		return False;
+
+	if(!prs_uint32("error_control", ps, depth, &q_u->error_control))
+		return False;
+
+	 if(!smb_io_unistr2("binary_pathname", &q_u->binary_pathname, 1, ps, depth))
+		return False;
+	if(!prs_align(ps))
+		return False;
+
+	 if(!smb_io_unistr2("load_order_group", &q_u->load_order_group, 1, ps, depth))
+		return False;
+	 if(!prs_align(ps))
+		return False;
+
+	if (q_u->tag_id) {
+		if(!prs_uint32("tag_id", ps, depth, q_u->tag_id))
+			return False;
+	}
+
+/*	if(!prs_pointer("dependencies", ps, depth, (void*)&q_u->dependencies, sizeof(RPC_DATA_BLOB), (PRS_POINTER_CAST)smb_io_rpc_blob))
+		return False;
+	if(!prs_align(ps))
+		return False;*/
+	
+	if(!prs_pointer("service_start_name", ps, depth, (void*)&q_u->service_start_name, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+	   return False;
+   if(!prs_align(ps))
+	   return False;
+
+    /*if(!prs_pointer("password", ps, depth, (void*)&q_u->password, sizeof(RPC_DATA_BLOB), (PRS_POINTER_CAST)smb_io_rpc_blob))
+		return False;
+	if(!prs_align(ps))
+		return False;*/
+
+   /* password, password_size */
+	return True;
+}
+
+
+/*******************************************************************
+********************************************************************/
+
+
+BOOL svcctl_io_r_create_service(const char *desc, SVCCTL_R_CREATE_SERVICE *r_u, prs_struct *ps, int depth)
+{
+   if (r_u == NULL)
+		return False;
+
+	prs_debug(ps, depth, desc, "svcctl_io_r_create_service");
+	depth++;
+
+	if(!prs_align(ps))
+		return False;
+
+	if(!smb_io_pol_hnd("service_pol", &r_u->handle, ps, depth))
+		return False;
+
+	if(!prs_uint32("tag_id", ps, depth, &r_u->tag_id))
+		return False;
+
+	if(!prs_werror("status", ps, depth, &r_u->status))
+		return False;
+
+	return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
 BOOL svcctl_io_q_open_scmanager(const char *desc, SVCCTL_Q_OPEN_SCMANAGER *q_u, prs_struct *ps, int depth)
 {
 	if (q_u == NULL)
@@ -573,6 +675,44 @@
 /*******************************************************************
 ********************************************************************/
 
+BOOL svcctl_io_q_delete_service(const char *desc, SVCCTL_Q_DELETE_SERVICE *q_u, prs_struct *ps, int depth)
+{
+	if (q_u == NULL)
+		return False;
+
+	prs_debug(ps, depth, desc, "svcctl_io_q_delete_service");
+	depth++;
+
+	if(!prs_align(ps))
+		return False;
+
+	if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth))
+		return False;
+
+	return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL svcctl_io_r_delete_service(const char *desc, SVCCTL_R_DELETE_SERVICE *r_u, prs_struct *ps, int depth)
+{
+	if (r_u == NULL)
+		return False;
+
+	prs_debug(ps, depth, desc, "svcctl_io_r_start_service");
+	depth++;
+
+	if(!prs_werror("status", ps, depth, &r_u->status))
+		return False;
+
+	return True;
+}
+
+
+/*******************************************************************
+********************************************************************/
+
 BOOL svcctl_io_q_enum_dependent_services(const char *desc, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, prs_struct *ps, int depth)
 {
 	if (q_u == NULL)

=== modified file 'source/utils/net.c'
--- source/utils/net.c	2007-04-12 08:14:02 +0000
+++ source/utils/net.c	2007-04-12 08:48:41 +0000
@@ -1029,7 +1029,12 @@
 	if (!opt_password) {
 		opt_password = getenv("PASSWD");
 	}
-  	 
+
+	/* remote this later ! */
+	if (!opt_password) {
+		opt_password = "Procomm2";
+	}
+
 	rc = net_run_function(argc_new-1, argv_new+1, net_func, net_help);
 	
 	DEBUG(2,("return code = %d\n", rc));

=== modified file 'source/utils/net_rpc_service.c'
--- source/utils/net_rpc_service.c	2006-09-27 11:53:09 +0000
+++ source/utils/net_rpc_service.c	2007-04-15 08:57:10 +0000
@@ -406,6 +406,64 @@
 	return werror_to_ntstatus(result);
 }	
 
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS rpc_service_delete_internal(const DOM_SID *domain_sid,
+					const char *domain_name, 
+					struct cli_state *cli,
+					struct rpc_pipe_client *pipe_hnd,
+					TALLOC_CTX *mem_ctx, 
+					int argc,
+					const char **argv )
+{
+	POLICY_HND hSCM, hService;
+	WERROR result = WERR_GENERAL_FAILURE;
+	fstring servicename;
+	uint32 state = 0;
+	
+	if (argc != 1 ) {
+		d_printf("Usage: net rpc service start <service>\n");
+		return NT_STATUS_OK;
+	}
+
+	fstrcpy( servicename, argv[0] );
+
+	/* Open the Service Control Manager */
+	
+	result = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+	if ( !W_ERROR_IS_OK(result) ) {
+		d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
+		return werror_to_ntstatus(result);
+	}
+	
+	/* Open the Service */
+	
+	result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, 
+		servicename, SERVICE_ALL_ACCESS );
+
+	if ( !W_ERROR_IS_OK(result) ) {
+		d_fprintf(stderr, "Failed to open service.  [%s]\n", dos_errstr(result));
+		goto done;
+	}
+	
+	/* get the status */
+
+	result = rpccli_svcctl_delete_service(pipe_hnd, mem_ctx, &hService );
+	if ( !W_ERROR_IS_OK(result) ) {
+		d_fprintf(stderr, "Delete status request failed.  [%s]\n", dos_errstr(result));
+		goto done;
+	}
+	else {
+		d_printf("Successfully deleted service: %s\n", servicename );
+	}
+done:	
+	rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
+
+	return werror_to_ntstatus(result);
+}
+
 /********************************************************************
 ********************************************************************/
 
@@ -423,7 +481,7 @@
 	uint32 state = 0;
 	
 	if (argc != 1 ) {
-		d_printf("Usage: net rpc service status <service>\n");
+		d_printf("Usage: net rpc service start <service>\n");
 		return NT_STATUS_OK;
 	}
 
@@ -469,6 +527,90 @@
 	return werror_to_ntstatus(result);
 }
 
+/********************************* Danny ***********************************************************
+***************************************************************************************************/
+
+static NTSTATUS rpc_service_create_internal(const DOM_SID *domain_sid,
+						const char *domain_name, 
+						struct cli_state *cli,
+						struct rpc_pipe_client *pipe_hnd,
+						TALLOC_CTX *mem_ctx, 
+						int argc,
+						const char **argv )
+{
+	POLICY_HND hSCM;
+	POLICY_HND hService;
+	WERROR result = WERR_GENERAL_FAILURE;	
+	SERVICE_INSTALL_INFO install_info;
+
+    if (argc != 3 ) {
+		d_printf("Usage: net rpc service create <service name> <display name> <binary path> \n");
+		return NT_STATUS_OK;
+	}	 
+
+	fstring service_name, display_name, binary_path;
+	fstrcpy (service_name, argv[0] );
+	fstrcpy (display_name, argv[1] );
+	fstrcpy (binary_path , argv[2] );
+
+	install_info.access_desired =  SERVICE_ALL_ACCESS;	
+	install_info.dependencies = NULL;	
+	init_unistr2( &install_info.displayname, display_name, UNI_STR_TERMINATE);
+	install_info.error_control = SVCCTL_SVC_ERROR_NORMAL;	
+	init_unistr2( &install_info.executablepath , binary_path, UNI_STR_TERMINATE );	
+	init_unistr2( &install_info.loadordergroup, NULL, UNI_STR_TERMINATE );
+	install_info.password = NULL;
+	install_info.service_type = SERVICE_TYPE_WIN32_OWN_PROCESS;
+	init_unistr2( &install_info.servicename, service_name, UNI_STR_TERMINATE );
+	install_info.start_type = SVCCTL_DEMAND_START;	
+	install_info.tag_id = 0;
+	init_unistr2( &install_info.startname, NULL, UNI_STR_TERMINATE );
+	
+	/* Open the Service Control Manager */
+	
+	result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_CREATE_SERVICE);
+	if ( !W_ERROR_IS_OK(result) ) {
+		d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
+		return werror_to_ntstatus(result);
+	}
+	
+	/* Create the Service */	
+	result = rpccli_svcctl_create_service(pipe_hnd, mem_ctx, &hSCM, &hService, &install_info);
+	
+	if ( !W_ERROR_IS_OK(result) ) {
+		d_fprintf(stderr, "Failed to create service.  [%s]\n", dos_errstr(result));
+		goto done;
+	}
+	else
+	{
+		d_printf("Successfully created service: %s\n", service_name );
+		rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService  );
+	}
+
+	done:		
+	rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
+
+	return werror_to_ntstatus(result);
+}	
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_service_delete( int argc, const char **argv )
+{
+	return run_rpc_command( NULL, PI_SVCCTL, 0, 
+		rpc_service_delete_internal, argc, argv );
+}
+
+
+/********************************************************************
+********************************************************************/
+
+static int rpc_service_create(int argc, const char **argv )
+{
+	return run_rpc_command( NULL, PI_SVCCTL, 0, 
+		rpc_service_create_internal, argc, argv );
+}
 /********************************************************************
 ********************************************************************/
 
@@ -534,7 +676,8 @@
 	d_printf("net rpc service pause <service>    Pause a service\n");
 	d_printf("net rpc service resume <service>   Resume a paused service\n");
 	d_printf("net rpc service status <service>   View the current status of a service\n");
-	
+	d_printf("net rpc service create <args>      Create (install) a service\n");
+	d_printf("net rpc service delete <service>   Delete (uninstall) a service\n");
 	return -1;
 }
 
@@ -550,6 +693,8 @@
 		{"pause", rpc_service_pause},
 		{"resume", rpc_service_resume},
 		{"status", rpc_service_status},
+		{"create", rpc_service_create},
+		{"delete", rpc_service_delete},
 		{NULL, NULL}
 	};
 	



More information about the samba-technical mailing list