2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (SVCCTL pipe)
4 * Copyright (C) Chris Nicholls 2005.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libsmb_internal.h"
24 #define WAIT_SLEEP_TIME 300000
26 int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm *op) {
28 struct rpc_pipe_client *pipe_hnd = NULL;
31 POLICY_HND *scm_out = NULL;
36 if(!hnd->_internal.ctx) {
37 hnd->status = NT_STATUS_INVALID_HANDLE;
41 if(!op || op->in.access == 0 || !mem_ctx) {
42 hnd->status = NT_STATUS_INVALID_PARAMETER;
46 srv = cac_GetServer(hnd);
48 hnd->status = NT_STATUS_INVALID_CONNECTION;
52 /*initialize for samr pipe if we have to*/
53 if(!hnd->_internal.pipes[PI_SVCCTL]) {
54 if(!(pipe_hnd = cli_rpc_pipe_open_noauth(&srv->cli, PI_SVCCTL, &(hnd->status)))) {
55 hnd->status = NT_STATUS_UNSUCCESSFUL;
59 hnd->_internal.pipes[PI_SVCCTL] = True;
62 scm_out = talloc(mem_ctx, POLICY_HND);
64 hnd->status = NT_STATUS_NO_MEMORY;
68 err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out, op->in.access);
69 hnd->status = werror_to_ntstatus(err);
71 if(!NT_STATUS_IS_OK(hnd->status))
74 op->out.scm_hnd = scm_out;
79 int cac_SvcClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *scm_hnd) {
80 struct rpc_pipe_client *pipe_hnd = NULL;
86 if(!hnd->_internal.ctx) {
87 hnd->status = NT_STATUS_INVALID_HANDLE;
91 if(!scm_hnd || !mem_ctx) {
92 hnd->status = NT_STATUS_INVALID_PARAMETER;
96 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
98 hnd->status = NT_STATUS_INVALID_HANDLE;
102 err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd);
103 hnd->status = werror_to_ntstatus(err);
105 if(!NT_STATUS_IS_OK(hnd->status))
111 int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op) {
112 struct rpc_pipe_client *pipe_hnd = NULL;
116 uint32 state_buf = 0;
118 uint32 num_svc_out = 0;
120 ENUM_SERVICES_STATUS *svc_buf = NULL;
125 if(!hnd->_internal.ctx) {
126 hnd->status = NT_STATUS_INVALID_HANDLE;
130 if(!op || !op->in.scm_hnd || !mem_ctx) {
131 hnd->status = NT_STATUS_INVALID_PARAMETER;
135 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
137 hnd->status = NT_STATUS_INVALID_HANDLE;
141 type_buf = (op->in.type != 0) ? op->in.type : (SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32);
142 state_buf = (op->in.state != 0) ? op->in.state : SVCCTL_STATE_ALL;
144 err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx, op->in.scm_hnd, type_buf, state_buf, &num_svc_out, &svc_buf);
145 hnd->status = werror_to_ntstatus(err);
147 if(!NT_STATUS_IS_OK(hnd->status))
150 op->out.services = cac_MakeServiceArray(mem_ctx, svc_buf, num_svc_out);
152 if(!op->out.services) {
153 hnd->status = NT_STATUS_NO_MEMORY;
157 talloc_free(svc_buf);
159 op->out.num_services = num_svc_out;
164 int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op) {
165 struct rpc_pipe_client *pipe_hnd = NULL;
168 POLICY_HND *svc_hnd_out = NULL;
173 if(!hnd->_internal.ctx) {
174 hnd->status = NT_STATUS_INVALID_HANDLE;
178 if(!op || !op->in.scm_hnd || !op->in.name || !mem_ctx) {
179 hnd->status = NT_STATUS_INVALID_PARAMETER;
183 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
185 hnd->status = NT_STATUS_INVALID_HANDLE;
189 svc_hnd_out = talloc(mem_ctx, POLICY_HND);
191 hnd->status = NT_STATUS_NO_MEMORY;
195 err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd, svc_hnd_out, op->in.name, op->in.access);
196 hnd->status = werror_to_ntstatus(err);
198 if(!NT_STATUS_IS_OK(hnd->status))
201 op->out.svc_hnd = svc_hnd_out;
206 int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op) {
207 struct rpc_pipe_client *pipe_hnd = NULL;
210 SERVICE_STATUS status_out;
215 if(!hnd->_internal.ctx) {
216 hnd->status = NT_STATUS_INVALID_HANDLE;
220 if(!op || !op->in.svc_hnd || !mem_ctx) {
221 hnd->status = NT_STATUS_INVALID_PARAMETER;
225 if(op->in.control < SVCCTL_CONTROL_STOP || op->in.control > SVCCTL_CONTROL_SHUTDOWN) {
226 hnd->status = NT_STATUS_INVALID_PARAMETER;
230 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
232 hnd->status = NT_STATUS_INVALID_HANDLE;
236 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, op->in.control, &status_out);
237 hnd->status = werror_to_ntstatus(err);
239 if(!NT_STATUS_IS_OK(hnd->status))
245 int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op) {
246 struct rpc_pipe_client *pipe_hnd = NULL;
249 SERVICE_STATUS status_out;
254 if(!hnd->_internal.ctx) {
255 hnd->status = NT_STATUS_INVALID_HANDLE;
259 if(!op || !op->in.svc_hnd || !mem_ctx) {
260 hnd->status = NT_STATUS_INVALID_PARAMETER;
264 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
266 hnd->status = NT_STATUS_INVALID_HANDLE;
270 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd, &status_out);
271 hnd->status = werror_to_ntstatus(err);
273 if(!NT_STATUS_IS_OK(hnd->status))
276 op->out.status = status_out;
283 /*Internal function - similar to code found in utils/net_rpc_service.c
284 * Waits for a service to reach a specific state.
285 * svc_hnd - Handle to the service
286 * state - the state we are waiting for
287 * timeout - number of seconds to wait
288 * returns CAC_FAILURE if the state is never reached
289 * or CAC_SUCCESS if the state is reached
291 int cac_WaitForService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *svc_hnd, uint32 state, uint32 timeout, SERVICE_STATUS *status) {
292 struct rpc_pipe_client *pipe_hnd = NULL;
293 /*number of milliseconds we have spent*/
294 uint32 time_spent = 0;
297 if(!hnd || !mem_ctx || !svc_hnd || !status)
300 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
302 hnd->status = NT_STATUS_INVALID_HANDLE;
306 while(status->state != state && time_spent < (timeout * 1000000) && NT_STATUS_IS_OK(hnd->status)) {
307 /*if this is the first call, then we _just_ got the status.. sleep now*/
308 usleep(WAIT_SLEEP_TIME);
309 time_spent += WAIT_SLEEP_TIME;
311 err = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, svc_hnd, status);
312 hnd->status = werror_to_ntstatus(err);
315 if(status->state == state)
321 int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op) {
322 struct rpc_pipe_client *pipe_hnd = NULL;
325 SERVICE_STATUS status_buf;
330 if(!hnd->_internal.ctx) {
331 hnd->status = NT_STATUS_INVALID_HANDLE;
335 if(!op || !op->in.svc_hnd || !mem_ctx) {
336 hnd->status = NT_STATUS_INVALID_PARAMETER;
340 if(op->in.num_parms != 0 && op->in.parms == NULL) {
341 hnd->status = NT_STATUS_INVALID_PARAMETER;
345 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
347 hnd->status = NT_STATUS_INVALID_HANDLE;
351 err = rpccli_svcctl_start_service(pipe_hnd, mem_ctx, op->in.svc_hnd, (const char **)op->in.parms, op->in.num_parms);
352 hnd->status = werror_to_ntstatus(err);
354 if(!NT_STATUS_IS_OK(hnd->status))
357 if(op->in.timeout == 0)
360 return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &status_buf);
363 int cac_SvcStopService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStopService *op) {
364 struct rpc_pipe_client *pipe_hnd = NULL;
367 SERVICE_STATUS status_out;
372 if(!hnd->_internal.ctx) {
373 hnd->status = NT_STATUS_INVALID_HANDLE;
377 if(!op || !op->in.svc_hnd || !mem_ctx) {
378 hnd->status = NT_STATUS_INVALID_PARAMETER;
382 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
384 hnd->status = NT_STATUS_INVALID_HANDLE;
388 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_STOP, &status_out);
389 hnd->status = werror_to_ntstatus(err);
391 if(!NT_STATUS_IS_OK(hnd->status))
394 op->out.status = status_out;
396 if(op->in.timeout == 0)
399 return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_STOPPED, op->in.timeout, &op->out.status);
402 int cac_SvcPauseService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcPauseService *op) {
403 struct rpc_pipe_client *pipe_hnd = NULL;
406 SERVICE_STATUS status_out;
411 if(!hnd->_internal.ctx) {
412 hnd->status = NT_STATUS_INVALID_HANDLE;
416 if(!op || !op->in.svc_hnd || !mem_ctx) {
417 hnd->status = NT_STATUS_INVALID_PARAMETER;
421 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
423 hnd->status = NT_STATUS_INVALID_HANDLE;
427 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_PAUSE, &status_out);
428 hnd->status = werror_to_ntstatus(err);
430 if(!NT_STATUS_IS_OK(hnd->status))
433 op->out.status = status_out;
435 if(op->in.timeout == 0)
438 return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_PAUSED, op->in.timeout, &op->out.status);
441 int cac_SvcContinueService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcContinueService *op) {
442 struct rpc_pipe_client *pipe_hnd = NULL;
445 SERVICE_STATUS status_out;
450 if(!hnd->_internal.ctx) {
451 hnd->status = NT_STATUS_INVALID_HANDLE;
455 if(!op || !op->in.svc_hnd || !mem_ctx) {
456 hnd->status = NT_STATUS_INVALID_PARAMETER;
460 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
462 hnd->status = NT_STATUS_INVALID_HANDLE;
466 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx, op->in.svc_hnd, SVCCTL_CONTROL_CONTINUE, &status_out);
467 hnd->status = werror_to_ntstatus(err);
469 if(!NT_STATUS_IS_OK(hnd->status))
472 op->out.status = status_out;
474 if(op->in.timeout == 0)
477 return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &op->out.status);
480 int cac_SvcGetDisplayName(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetDisplayName *op) {
481 struct rpc_pipe_client *pipe_hnd = NULL;
484 fstring disp_name_out;
489 if(!hnd->_internal.ctx) {
490 hnd->status = NT_STATUS_INVALID_HANDLE;
494 if(!op || !op->in.svc_hnd || !mem_ctx) {
495 hnd->status = NT_STATUS_INVALID_PARAMETER;
499 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
501 hnd->status = NT_STATUS_INVALID_HANDLE;
505 err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd, disp_name_out);
506 hnd->status = werror_to_ntstatus(err);
508 if(!NT_STATUS_IS_OK(hnd->status))
511 op->out.display_name = talloc_strdup(mem_ctx, disp_name_out);
513 if(!op->out.display_name) {
514 hnd->status = NT_STATUS_NO_MEMORY;
522 int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op) {
523 struct rpc_pipe_client *pipe_hnd = NULL;
526 SERVICE_CONFIG config_out;
531 if(!hnd->_internal.ctx) {
532 hnd->status = NT_STATUS_INVALID_HANDLE;
536 if(!op || !op->in.svc_hnd || !mem_ctx) {
537 hnd->status = NT_STATUS_INVALID_PARAMETER;
541 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
543 hnd->status = NT_STATUS_INVALID_HANDLE;
547 err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd, &config_out);
548 hnd->status = werror_to_ntstatus(err);
550 if(!NT_STATUS_IS_OK(hnd->status))
553 if(!cac_InitCacServiceConfig(mem_ctx, &config_out, &op->out.config)) {
554 hnd->status = NT_STATUS_NO_MEMORY;