diff options
Diffstat (limited to 'source/rpc_client/cli_svcctl.c')
-rw-r--r-- | source/rpc_client/cli_svcctl.c | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/source/rpc_client/cli_svcctl.c b/source/rpc_client/cli_svcctl.c new file mode 100644 index 00000000000..9f80bb79a39 --- /dev/null +++ b/source/rpc_client/cli_svcctl.c @@ -0,0 +1,415 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" +#include "rpc_client.h" + +struct svc_state_msg { + uint32 flag; + const char *message; +}; + +static struct svc_state_msg state_msg_table[] = { + { SVCCTL_STOPPED, "stopped" }, + { SVCCTL_START_PENDING, "start pending" }, + { SVCCTL_STOP_PENDING, "stop pending" }, + { SVCCTL_RUNNING, "running" }, + { SVCCTL_CONTINUE_PENDING, "resume pending" }, + { SVCCTL_PAUSE_PENDING, "pause pending" }, + { SVCCTL_PAUSED, "paused" }, + { 0, NULL } +}; + + +/******************************************************************** +********************************************************************/ +const char* svc_status_string( uint32 state ) +{ + static fstring msg; + int i; + + fstr_sprintf( msg, "Unknown State [%d]", state ); + + for ( i=0; state_msg_table[i].message; i++ ) { + if ( state_msg_table[i].flag == state ) { + fstrcpy( msg, state_msg_table[i].message ); + break; + } + } + + return msg; +} + +/******************************************************************** +********************************************************************/ + +WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, uint32 access_desired ) +{ + SVCCTL_Q_OPEN_SCMANAGER in; + SVCCTL_R_OPEN_SCMANAGER out; + prs_struct qbuf, rbuf; + fstring server; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + /* leave the database name NULL to get the default service db */ + + in.database = NULL; + + /* set the server name */ + + if ( !(in.servername = TALLOC_P( mem_ctx, UNISTR2 )) ) + return WERR_NOMEM; + fstr_sprintf( server, "\\\\%s", cli->desthost ); + init_unistr2( in.servername, server, UNI_STR_TERMINATE ); + + in.access = access_desired; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, + in, out, + qbuf, rbuf, + svcctl_io_q_open_scmanager, + svcctl_io_r_open_scmanager, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( hSCM, &out.handle, sizeof(POLICY_HND) ); + + return out.status; +} + +/******************************************************************** +********************************************************************/ + +WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, POLICY_HND *hService, + const char *servicename, uint32 access_desired ) +{ + SVCCTL_Q_OPEN_SERVICE in; + SVCCTL_R_OPEN_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hSCM, sizeof(POLICY_HND) ); + init_unistr2( &in.servicename, servicename, UNI_STR_TERMINATE ); + in.access = access_desired; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, + in, out, + qbuf, rbuf, + svcctl_io_q_open_service, + svcctl_io_r_open_service, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( hService, &out.handle, sizeof(POLICY_HND) ); + + return out.status; +} + +/******************************************************************** +********************************************************************/ + +WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService ) +{ + SVCCTL_Q_CLOSE_SERVICE in; + SVCCTL_R_CLOSE_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, + in, out, + qbuf, rbuf, + svcctl_io_q_close_service, + svcctl_io_r_close_service, + WERR_GENERAL_FAILURE ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, uint32 type, uint32 state, + uint32 *returned, ENUM_SERVICES_STATUS **service_array ) +{ + SVCCTL_Q_ENUM_SERVICES_STATUS in; + SVCCTL_R_ENUM_SERVICES_STATUS out; + prs_struct qbuf, rbuf; + uint32 resume = 0; + ENUM_SERVICES_STATUS *services; + int i; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + /* setup the request */ + + memcpy( &in.handle, hSCM, sizeof(POLICY_HND) ); + + in.type = type; + in.state = state; + in.resume = &resume; + + /* first time is to get the buffer size */ + in.buffer_size = 0; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, + in, out, + qbuf, rbuf, + svcctl_io_q_enum_services_status, + svcctl_io_r_enum_services_status, + WERR_GENERAL_FAILURE ); + + /* second time with correct buffer size...should be ok */ + + if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) { + in.buffer_size = out.needed; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, + in, out, + qbuf, rbuf, + svcctl_io_q_enum_services_status, + svcctl_io_r_enum_services_status, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK(out.status) ) + return out.status; + + /* pull out the data */ + if ( !(services = TALLOC_ARRAY( mem_ctx, ENUM_SERVICES_STATUS, out.returned )) ) + return WERR_NOMEM; + + for ( i=0; i<out.returned; i++ ) { + svcctl_io_enum_services_status( "", &services[i], &out.buffer, 0 ); + } + + *service_array = services; + *returned = out.returned; + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, SERVICE_STATUS *status ) +{ + SVCCTL_Q_QUERY_STATUS in; + SVCCTL_R_QUERY_STATUS out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, + in, out, + qbuf, rbuf, + svcctl_io_q_query_status, + svcctl_io_r_query_status, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, SERVICE_CONFIG *config ) +{ + SVCCTL_Q_QUERY_SERVICE_CONFIG in; + SVCCTL_R_QUERY_SERVICE_CONFIG out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.buffer_size = 0; + + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, + in, out, + qbuf, rbuf, + svcctl_io_q_query_service_config, + svcctl_io_r_query_service_config, + WERR_GENERAL_FAILURE ); + + if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { + in.buffer_size = out.needed; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, + in, out, + qbuf, rbuf, + svcctl_io_q_query_service_config, + svcctl_io_r_query_service_config, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( config, &out.config, sizeof(SERVICE_CONFIG) ); + + config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + + copy_unistr2( config->executablepath, out.config.executablepath ); + copy_unistr2( config->loadordergroup, out.config.loadordergroup ); + copy_unistr2( config->dependencies, out.config.dependencies ); + copy_unistr2( config->startname, out.config.startname ); + copy_unistr2( config->displayname, out.config.displayname ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, + const char **parm_array, uint32 parmcount ) +{ + SVCCTL_Q_START_SERVICE in; + SVCCTL_R_START_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + in.parmcount = 0; + in.parameters = NULL; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W, + in, out, + qbuf, rbuf, + svcctl_io_q_start_service, + svcctl_io_r_start_service, + WERR_GENERAL_FAILURE ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, uint32 control, + SERVICE_STATUS *status ) +{ + SVCCTL_Q_CONTROL_SERVICE in; + SVCCTL_R_CONTROL_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.control = control; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, + in, out, + qbuf, rbuf, + svcctl_io_q_control_service, + svcctl_io_r_control_service, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) ); + + return out.status; +} + + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, fstring displayname ) +{ + SVCCTL_Q_GET_DISPLAY_NAME in; + SVCCTL_R_GET_DISPLAY_NAME out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.display_name_len = 0; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + in, out, + qbuf, rbuf, + svcctl_io_q_get_display_name, + svcctl_io_r_get_display_name, + WERR_GENERAL_FAILURE ); + + /* second time with correct buffer size...should be ok */ + + if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { + in.display_name_len = out.display_name_len; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + in, out, + qbuf, rbuf, + svcctl_io_q_get_display_name, + svcctl_io_r_get_display_name, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + rpcstr_pull( displayname, out.displayname.buffer, sizeof(displayname), -1, STR_TERMINATE ); + + return out.status; +} + |