r13571: Replace all calls to talloc_free() with thye TALLOC_FREE()
[Samba/gbeck.git] / source3 / libmsrpc / cac_svcctl.c
blob83dc0364930219ad049f7d2fde9109a1e5af4424
1 /*
2 * Unix SMB/CIFS implementation.
3 * MS-RPC client library implementation (SVCCTL pipe)
4 * Copyright (C) Chris Nicholls 2005.
5 *
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.
21 #include "libmsrpc.h"
22 #include "libsmb_internal.h"
24 #define WAIT_SLEEP_TIME 300000
26 int cac_SvcOpenScm(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenScm *op) {
27 SMBCSRV *srv = NULL;
28 struct rpc_pipe_client *pipe_hnd = NULL;
29 WERROR err;
31 POLICY_HND *scm_out = NULL;
33 if(!hnd)
34 return CAC_FAILURE;
36 if(!hnd->_internal.ctx) {
37 hnd->status = NT_STATUS_INVALID_HANDLE;
38 return CAC_FAILURE;
41 if(!op || op->in.access == 0 || !mem_ctx) {
42 hnd->status = NT_STATUS_INVALID_PARAMETER;
43 return CAC_FAILURE;
46 srv = cac_GetServer(hnd);
47 if(!srv) {
48 hnd->status = NT_STATUS_INVALID_CONNECTION;
49 return CAC_FAILURE;
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;
56 return CAC_FAILURE;
59 hnd->_internal.pipes[PI_SVCCTL] = True;
62 scm_out = talloc(mem_ctx, POLICY_HND);
63 if(!scm_out) {
64 hnd->status = NT_STATUS_NO_MEMORY;
65 return CAC_FAILURE;
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))
72 return CAC_FAILURE;
74 op->out.scm_hnd = scm_out;
76 return CAC_SUCCESS;
79 int cac_SvcClose(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, POLICY_HND *scm_hnd) {
80 struct rpc_pipe_client *pipe_hnd = NULL;
81 WERROR err;
83 if(!hnd)
84 return CAC_FAILURE;
86 if(!hnd->_internal.ctx) {
87 hnd->status = NT_STATUS_INVALID_HANDLE;
88 return CAC_FAILURE;
91 if(!scm_hnd || !mem_ctx) {
92 hnd->status = NT_STATUS_INVALID_PARAMETER;
93 return CAC_FAILURE;
96 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
97 if(!pipe_hnd) {
98 hnd->status = NT_STATUS_INVALID_HANDLE;
99 return CAC_FAILURE;
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))
106 return CAC_FAILURE;
108 return CAC_SUCCESS;
111 int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op) {
112 struct rpc_pipe_client *pipe_hnd = NULL;
113 WERROR err;
115 uint32 type_buf = 0;
116 uint32 state_buf = 0;
118 uint32 num_svc_out = 0;
120 ENUM_SERVICES_STATUS *svc_buf = NULL;
122 if(!hnd)
123 return CAC_FAILURE;
125 if(!hnd->_internal.ctx) {
126 hnd->status = NT_STATUS_INVALID_HANDLE;
127 return CAC_FAILURE;
130 if(!op || !op->in.scm_hnd || !mem_ctx) {
131 hnd->status = NT_STATUS_INVALID_PARAMETER;
132 return CAC_FAILURE;
135 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
136 if(!pipe_hnd) {
137 hnd->status = NT_STATUS_INVALID_HANDLE;
138 return CAC_FAILURE;
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))
148 return CAC_FAILURE;
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;
154 return CAC_FAILURE;
157 TALLOC_FREE(svc_buf);
159 op->out.num_services = num_svc_out;
161 return CAC_SUCCESS;
164 int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op) {
165 struct rpc_pipe_client *pipe_hnd = NULL;
166 WERROR err;
168 POLICY_HND *svc_hnd_out = NULL;
170 if(!hnd)
171 return CAC_FAILURE;
173 if(!hnd->_internal.ctx) {
174 hnd->status = NT_STATUS_INVALID_HANDLE;
175 return CAC_FAILURE;
178 if(!op || !op->in.scm_hnd || !op->in.name || !mem_ctx) {
179 hnd->status = NT_STATUS_INVALID_PARAMETER;
180 return CAC_FAILURE;
183 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
184 if(!pipe_hnd) {
185 hnd->status = NT_STATUS_INVALID_HANDLE;
186 return CAC_FAILURE;
189 svc_hnd_out = talloc(mem_ctx, POLICY_HND);
190 if(!svc_hnd_out) {
191 hnd->status = NT_STATUS_NO_MEMORY;
192 return CAC_FAILURE;
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))
199 return CAC_FAILURE;
201 op->out.svc_hnd = svc_hnd_out;
203 return CAC_SUCCESS;
206 int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op) {
207 struct rpc_pipe_client *pipe_hnd = NULL;
208 WERROR err;
210 SERVICE_STATUS status_out;
212 if(!hnd)
213 return CAC_FAILURE;
215 if(!hnd->_internal.ctx) {
216 hnd->status = NT_STATUS_INVALID_HANDLE;
217 return CAC_FAILURE;
220 if(!op || !op->in.svc_hnd || !mem_ctx) {
221 hnd->status = NT_STATUS_INVALID_PARAMETER;
222 return CAC_FAILURE;
225 if(op->in.control < SVCCTL_CONTROL_STOP || op->in.control > SVCCTL_CONTROL_SHUTDOWN) {
226 hnd->status = NT_STATUS_INVALID_PARAMETER;
227 return CAC_FAILURE;
230 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
231 if(!pipe_hnd) {
232 hnd->status = NT_STATUS_INVALID_HANDLE;
233 return CAC_FAILURE;
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))
240 return CAC_FAILURE;
242 return CAC_SUCCESS;
245 int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op) {
246 struct rpc_pipe_client *pipe_hnd = NULL;
247 WERROR err;
249 SERVICE_STATUS status_out;
251 if(!hnd)
252 return CAC_FAILURE;
254 if(!hnd->_internal.ctx) {
255 hnd->status = NT_STATUS_INVALID_HANDLE;
256 return CAC_FAILURE;
259 if(!op || !op->in.svc_hnd || !mem_ctx) {
260 hnd->status = NT_STATUS_INVALID_PARAMETER;
261 return CAC_FAILURE;
264 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
265 if(!pipe_hnd) {
266 hnd->status = NT_STATUS_INVALID_HANDLE;
267 return CAC_FAILURE;
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))
274 return CAC_FAILURE;
276 op->out.status = status_out;
278 return CAC_SUCCESS;
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;
295 WERROR err;
297 if(!hnd || !mem_ctx || !svc_hnd || !status)
298 return CAC_FAILURE;
300 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
301 if(!pipe_hnd) {
302 hnd->status = NT_STATUS_INVALID_HANDLE;
303 return CAC_FAILURE;
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)
316 return CAC_SUCCESS;
318 return CAC_FAILURE;
321 int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op) {
322 struct rpc_pipe_client *pipe_hnd = NULL;
323 WERROR err;
325 SERVICE_STATUS status_buf;
327 if(!hnd)
328 return CAC_FAILURE;
330 if(!hnd->_internal.ctx) {
331 hnd->status = NT_STATUS_INVALID_HANDLE;
332 return CAC_FAILURE;
335 if(!op || !op->in.svc_hnd || !mem_ctx) {
336 hnd->status = NT_STATUS_INVALID_PARAMETER;
337 return CAC_FAILURE;
340 if(op->in.num_parms != 0 && op->in.parms == NULL) {
341 hnd->status = NT_STATUS_INVALID_PARAMETER;
342 return CAC_FAILURE;
345 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
346 if(!pipe_hnd) {
347 hnd->status = NT_STATUS_INVALID_HANDLE;
348 return CAC_FAILURE;
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))
355 return CAC_FAILURE;
357 if(op->in.timeout == 0)
358 return CAC_SUCCESS;
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;
365 WERROR err;
367 SERVICE_STATUS status_out;
369 if(!hnd)
370 return CAC_FAILURE;
372 if(!hnd->_internal.ctx) {
373 hnd->status = NT_STATUS_INVALID_HANDLE;
374 return CAC_FAILURE;
377 if(!op || !op->in.svc_hnd || !mem_ctx) {
378 hnd->status = NT_STATUS_INVALID_PARAMETER;
379 return CAC_FAILURE;
382 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
383 if(!pipe_hnd) {
384 hnd->status = NT_STATUS_INVALID_HANDLE;
385 return CAC_FAILURE;
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))
392 return CAC_FAILURE;
394 op->out.status = status_out;
396 if(op->in.timeout == 0)
397 return CAC_SUCCESS;
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;
404 WERROR err;
406 SERVICE_STATUS status_out;
408 if(!hnd)
409 return CAC_FAILURE;
411 if(!hnd->_internal.ctx) {
412 hnd->status = NT_STATUS_INVALID_HANDLE;
413 return CAC_FAILURE;
416 if(!op || !op->in.svc_hnd || !mem_ctx) {
417 hnd->status = NT_STATUS_INVALID_PARAMETER;
418 return CAC_FAILURE;
421 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
422 if(!pipe_hnd) {
423 hnd->status = NT_STATUS_INVALID_HANDLE;
424 return CAC_FAILURE;
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))
431 return CAC_FAILURE;
433 op->out.status = status_out;
435 if(op->in.timeout == 0)
436 return CAC_SUCCESS;
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;
443 WERROR err;
445 SERVICE_STATUS status_out;
447 if(!hnd)
448 return CAC_FAILURE;
450 if(!hnd->_internal.ctx) {
451 hnd->status = NT_STATUS_INVALID_HANDLE;
452 return CAC_FAILURE;
455 if(!op || !op->in.svc_hnd || !mem_ctx) {
456 hnd->status = NT_STATUS_INVALID_PARAMETER;
457 return CAC_FAILURE;
460 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
461 if(!pipe_hnd) {
462 hnd->status = NT_STATUS_INVALID_HANDLE;
463 return CAC_FAILURE;
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))
470 return CAC_FAILURE;
472 op->out.status = status_out;
474 if(op->in.timeout == 0)
475 return CAC_SUCCESS;
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;
482 WERROR err;
484 fstring disp_name_out;
486 if(!hnd)
487 return CAC_FAILURE;
489 if(!hnd->_internal.ctx) {
490 hnd->status = NT_STATUS_INVALID_HANDLE;
491 return CAC_FAILURE;
494 if(!op || !op->in.svc_hnd || !mem_ctx) {
495 hnd->status = NT_STATUS_INVALID_PARAMETER;
496 return CAC_FAILURE;
499 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
500 if(!pipe_hnd) {
501 hnd->status = NT_STATUS_INVALID_HANDLE;
502 return CAC_FAILURE;
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))
509 return CAC_FAILURE;
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;
515 return CAC_FAILURE;
518 return CAC_SUCCESS;
522 int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op) {
523 struct rpc_pipe_client *pipe_hnd = NULL;
524 WERROR err;
526 SERVICE_CONFIG config_out;
528 if(!hnd)
529 return CAC_FAILURE;
531 if(!hnd->_internal.ctx) {
532 hnd->status = NT_STATUS_INVALID_HANDLE;
533 return CAC_FAILURE;
536 if(!op || !op->in.svc_hnd || !mem_ctx) {
537 hnd->status = NT_STATUS_INVALID_PARAMETER;
538 return CAC_FAILURE;
541 pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
542 if(!pipe_hnd) {
543 hnd->status = NT_STATUS_INVALID_HANDLE;
544 return CAC_FAILURE;
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))
551 return CAC_FAILURE;
553 if(!cac_InitCacServiceConfig(mem_ctx, &config_out, &op->out.config)) {
554 hnd->status = NT_STATUS_NO_MEMORY;
555 return CAC_FAILURE;
558 return CAC_SUCCESS;