source: trunk-3.0/source/libmsrpc/cac_svcctl.c@ 102

Last change on this file since 102 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 14.3 KB
Line 
1
2/*
3 * Unix SMB/CIFS implementation.
4 * MS-RPC client library implementation (SVCCTL pipe)
5 * Copyright (C) Chris Nicholls 2005.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "libmsrpc.h"
23#include "libsmb_internal.h"
24
25#define WAIT_SLEEP_TIME 300000
26
27int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
28 POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
29 SERVICE_STATUS * status );
30
31int cac_SvcOpenScm( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
32 struct SvcOpenScm *op )
33{
34 SMBCSRV *srv = NULL;
35 struct rpc_pipe_client *pipe_hnd = NULL;
36 WERROR err;
37
38 POLICY_HND *scm_out = NULL;
39
40 if ( !hnd )
41 return CAC_FAILURE;
42
43 if ( !hnd->_internal.ctx ) {
44 hnd->status = NT_STATUS_INVALID_HANDLE;
45 return CAC_FAILURE;
46 }
47
48 if ( !op || op->in.access == 0 || !mem_ctx ) {
49 hnd->status = NT_STATUS_INVALID_PARAMETER;
50 return CAC_FAILURE;
51 }
52
53 srv = cac_GetServer( hnd );
54 if ( !srv ) {
55 hnd->status = NT_STATUS_INVALID_CONNECTION;
56 return CAC_FAILURE;
57 }
58
59 /*initialize for samr pipe if we have to */
60 if ( !hnd->_internal.pipes[PI_SVCCTL] ) {
61 if ( !
62 ( pipe_hnd =
63 cli_rpc_pipe_open_noauth( srv->cli, PI_SVCCTL,
64 &( hnd->status ) ) ) ) {
65 hnd->status = NT_STATUS_UNSUCCESSFUL;
66 return CAC_FAILURE;
67 }
68
69 hnd->_internal.pipes[PI_SVCCTL] = True;
70 }
71
72 scm_out = talloc( mem_ctx, POLICY_HND );
73 if ( !scm_out ) {
74 hnd->status = NT_STATUS_NO_MEMORY;
75 return CAC_FAILURE;
76 }
77
78 err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out,
79 op->in.access );
80 hnd->status = werror_to_ntstatus( err );
81
82 if ( !NT_STATUS_IS_OK( hnd->status ) )
83 return CAC_FAILURE;
84
85 op->out.scm_hnd = scm_out;
86
87 return CAC_SUCCESS;
88}
89
90int cac_SvcClose( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
91 POLICY_HND * scm_hnd )
92{
93 struct rpc_pipe_client *pipe_hnd = NULL;
94 WERROR err;
95
96 if ( !hnd )
97 return CAC_FAILURE;
98
99 if ( !hnd->_internal.ctx ) {
100 hnd->status = NT_STATUS_INVALID_HANDLE;
101 return CAC_FAILURE;
102 }
103
104 if ( !scm_hnd || !mem_ctx ) {
105 hnd->status = NT_STATUS_INVALID_PARAMETER;
106 return CAC_FAILURE;
107 }
108
109 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
110 if ( !pipe_hnd ) {
111 hnd->status = NT_STATUS_INVALID_HANDLE;
112 return CAC_FAILURE;
113 }
114
115 err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd );
116 hnd->status = werror_to_ntstatus( err );
117
118 if ( !NT_STATUS_IS_OK( hnd->status ) )
119 return CAC_FAILURE;
120
121 return CAC_SUCCESS;
122}
123
124int cac_SvcEnumServices( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
125 struct SvcEnumServices *op )
126{
127 struct rpc_pipe_client *pipe_hnd = NULL;
128 WERROR err;
129
130 uint32 type_buf = 0;
131 uint32 state_buf = 0;
132
133 uint32 num_svc_out = 0;
134
135 ENUM_SERVICES_STATUS *svc_buf = NULL;
136
137 if ( !hnd )
138 return CAC_FAILURE;
139
140 if ( !hnd->_internal.ctx ) {
141 hnd->status = NT_STATUS_INVALID_HANDLE;
142 return CAC_FAILURE;
143 }
144
145 if ( !op || !op->in.scm_hnd || !mem_ctx ) {
146 hnd->status = NT_STATUS_INVALID_PARAMETER;
147 return CAC_FAILURE;
148 }
149
150 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
151 if ( !pipe_hnd ) {
152 hnd->status = NT_STATUS_INVALID_HANDLE;
153 return CAC_FAILURE;
154 }
155
156 type_buf =
157 ( op->in.type !=
158 0 ) ? op->in.
159 type : ( SVCCTL_TYPE_DRIVER | SVCCTL_TYPE_WIN32 );
160 state_buf = ( op->in.state != 0 ) ? op->in.state : SVCCTL_STATE_ALL;
161
162 err = rpccli_svcctl_enumerate_services( pipe_hnd, mem_ctx,
163 op->in.scm_hnd, type_buf,
164 state_buf, &num_svc_out,
165 &svc_buf );
166 hnd->status = werror_to_ntstatus( err );
167
168 if ( !NT_STATUS_IS_OK( hnd->status ) )
169 return CAC_FAILURE;
170
171 op->out.services =
172 cac_MakeServiceArray( mem_ctx, svc_buf, num_svc_out );
173
174 if ( !op->out.services ) {
175 hnd->status = NT_STATUS_NO_MEMORY;
176 return CAC_FAILURE;
177 }
178
179 TALLOC_FREE( svc_buf );
180
181 op->out.num_services = num_svc_out;
182
183 return CAC_SUCCESS;
184}
185
186int cac_SvcOpenService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
187 struct SvcOpenService *op )
188{
189 struct rpc_pipe_client *pipe_hnd = NULL;
190 WERROR err;
191
192 POLICY_HND *svc_hnd_out = NULL;
193
194 if ( !hnd )
195 return CAC_FAILURE;
196
197 if ( !hnd->_internal.ctx ) {
198 hnd->status = NT_STATUS_INVALID_HANDLE;
199 return CAC_FAILURE;
200 }
201
202 if ( !op || !op->in.scm_hnd || !op->in.name || !mem_ctx ) {
203 hnd->status = NT_STATUS_INVALID_PARAMETER;
204 return CAC_FAILURE;
205 }
206
207 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
208 if ( !pipe_hnd ) {
209 hnd->status = NT_STATUS_INVALID_HANDLE;
210 return CAC_FAILURE;
211 }
212
213 svc_hnd_out = talloc( mem_ctx, POLICY_HND );
214 if ( !svc_hnd_out ) {
215 hnd->status = NT_STATUS_NO_MEMORY;
216 return CAC_FAILURE;
217 }
218
219 err = rpccli_svcctl_open_service( pipe_hnd, mem_ctx, op->in.scm_hnd,
220 svc_hnd_out, op->in.name,
221 op->in.access );
222 hnd->status = werror_to_ntstatus( err );
223
224 if ( !NT_STATUS_IS_OK( hnd->status ) )
225 return CAC_FAILURE;
226
227 op->out.svc_hnd = svc_hnd_out;
228
229 return CAC_SUCCESS;
230}
231
232int cac_SvcControlService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
233 struct SvcControlService *op )
234{
235 struct rpc_pipe_client *pipe_hnd = NULL;
236 WERROR err;
237
238 SERVICE_STATUS status_out;
239
240 if ( !hnd )
241 return CAC_FAILURE;
242
243 if ( !hnd->_internal.ctx ) {
244 hnd->status = NT_STATUS_INVALID_HANDLE;
245 return CAC_FAILURE;
246 }
247
248 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
249 hnd->status = NT_STATUS_INVALID_PARAMETER;
250 return CAC_FAILURE;
251 }
252
253 if ( op->in.control < SVCCTL_CONTROL_STOP
254 || op->in.control > SVCCTL_CONTROL_SHUTDOWN ) {
255 hnd->status = NT_STATUS_INVALID_PARAMETER;
256 return CAC_FAILURE;
257 }
258
259 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
260 if ( !pipe_hnd ) {
261 hnd->status = NT_STATUS_INVALID_HANDLE;
262 return CAC_FAILURE;
263 }
264
265 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
266 op->in.svc_hnd, op->in.control,
267 &status_out );
268 hnd->status = werror_to_ntstatus( err );
269
270 if ( !NT_STATUS_IS_OK( hnd->status ) )
271 return CAC_FAILURE;
272
273 return CAC_SUCCESS;
274}
275
276int cac_SvcGetStatus( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
277 struct SvcGetStatus *op )
278{
279 struct rpc_pipe_client *pipe_hnd = NULL;
280 WERROR err;
281
282 SERVICE_STATUS status_out;
283
284 if ( !hnd )
285 return CAC_FAILURE;
286
287 if ( !hnd->_internal.ctx ) {
288 hnd->status = NT_STATUS_INVALID_HANDLE;
289 return CAC_FAILURE;
290 }
291
292 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
293 hnd->status = NT_STATUS_INVALID_PARAMETER;
294 return CAC_FAILURE;
295 }
296
297 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
298 if ( !pipe_hnd ) {
299 hnd->status = NT_STATUS_INVALID_HANDLE;
300 return CAC_FAILURE;
301 }
302
303 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd,
304 &status_out );
305 hnd->status = werror_to_ntstatus( err );
306
307 if ( !NT_STATUS_IS_OK( hnd->status ) )
308 return CAC_FAILURE;
309
310 op->out.status = status_out;
311
312 return CAC_SUCCESS;
313}
314
315
316
317/*Internal function - similar to code found in utils/net_rpc_service.c
318 * Waits for a service to reach a specific state.
319 * svc_hnd - Handle to the service
320 * state - the state we are waiting for
321 * timeout - number of seconds to wait
322 * returns CAC_FAILURE if the state is never reached
323 * or CAC_SUCCESS if the state is reached
324 */
325int cac_WaitForService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
326 POLICY_HND * svc_hnd, uint32 state, uint32 timeout,
327 SERVICE_STATUS * status )
328{
329 struct rpc_pipe_client *pipe_hnd = NULL;
330
331 /*number of milliseconds we have spent */
332 uint32 time_spent = 0;
333 WERROR err;
334
335 if ( !hnd || !mem_ctx || !svc_hnd || !status )
336 return CAC_FAILURE;
337
338 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
339 if ( !pipe_hnd ) {
340 hnd->status = NT_STATUS_INVALID_HANDLE;
341 return CAC_FAILURE;
342 }
343
344 while ( status->state != state && time_spent < ( timeout * 1000000 )
345 && NT_STATUS_IS_OK( hnd->status ) ) {
346 /*if this is the first call, then we _just_ got the status.. sleep now */
347 usleep( WAIT_SLEEP_TIME );
348 time_spent += WAIT_SLEEP_TIME;
349
350 err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, svc_hnd,
351 status );
352 hnd->status = werror_to_ntstatus( err );
353 }
354
355 if ( status->state == state )
356 return CAC_SUCCESS;
357
358 return CAC_FAILURE;
359}
360
361int cac_SvcStartService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
362 struct SvcStartService *op )
363{
364 struct rpc_pipe_client *pipe_hnd = NULL;
365 WERROR err;
366
367 SERVICE_STATUS status_buf;
368
369 if ( !hnd )
370 return CAC_FAILURE;
371
372 if ( !hnd->_internal.ctx ) {
373 hnd->status = NT_STATUS_INVALID_HANDLE;
374 return CAC_FAILURE;
375 }
376
377 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
378 hnd->status = NT_STATUS_INVALID_PARAMETER;
379 return CAC_FAILURE;
380 }
381
382 if ( op->in.num_parms != 0 && op->in.parms == NULL ) {
383 hnd->status = NT_STATUS_INVALID_PARAMETER;
384 return CAC_FAILURE;
385 }
386
387 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
388 if ( !pipe_hnd ) {
389 hnd->status = NT_STATUS_INVALID_HANDLE;
390 return CAC_FAILURE;
391 }
392
393 err = rpccli_svcctl_start_service( pipe_hnd, mem_ctx, op->in.svc_hnd,
394 ( const char ** ) op->in.parms,
395 op->in.num_parms );
396 hnd->status = werror_to_ntstatus( err );
397
398 if ( !NT_STATUS_IS_OK( hnd->status ) )
399 return CAC_FAILURE;
400
401 if ( op->in.timeout == 0 )
402 return CAC_SUCCESS;
403
404 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
405 SVCCTL_RUNNING, op->in.timeout,
406 &status_buf );
407}
408
409int cac_SvcStopService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
410 struct SvcStopService *op )
411{
412 struct rpc_pipe_client *pipe_hnd = NULL;
413 WERROR err;
414
415 SERVICE_STATUS status_out;
416
417 if ( !hnd )
418 return CAC_FAILURE;
419
420 if ( !hnd->_internal.ctx ) {
421 hnd->status = NT_STATUS_INVALID_HANDLE;
422 return CAC_FAILURE;
423 }
424
425 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
426 hnd->status = NT_STATUS_INVALID_PARAMETER;
427 return CAC_FAILURE;
428 }
429
430 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
431 if ( !pipe_hnd ) {
432 hnd->status = NT_STATUS_INVALID_HANDLE;
433 return CAC_FAILURE;
434 }
435
436 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
437 op->in.svc_hnd,
438 SVCCTL_CONTROL_STOP,
439 &status_out );
440 hnd->status = werror_to_ntstatus( err );
441
442 if ( !NT_STATUS_IS_OK( hnd->status ) )
443 return CAC_FAILURE;
444
445 op->out.status = status_out;
446
447 if ( op->in.timeout == 0 )
448 return CAC_SUCCESS;
449
450 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
451 SVCCTL_STOPPED, op->in.timeout,
452 &op->out.status );
453}
454
455int cac_SvcPauseService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
456 struct SvcPauseService *op )
457{
458 struct rpc_pipe_client *pipe_hnd = NULL;
459 WERROR err;
460
461 SERVICE_STATUS status_out;
462
463 if ( !hnd )
464 return CAC_FAILURE;
465
466 if ( !hnd->_internal.ctx ) {
467 hnd->status = NT_STATUS_INVALID_HANDLE;
468 return CAC_FAILURE;
469 }
470
471 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
472 hnd->status = NT_STATUS_INVALID_PARAMETER;
473 return CAC_FAILURE;
474 }
475
476 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
477 if ( !pipe_hnd ) {
478 hnd->status = NT_STATUS_INVALID_HANDLE;
479 return CAC_FAILURE;
480 }
481
482 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
483 op->in.svc_hnd,
484 SVCCTL_CONTROL_PAUSE,
485 &status_out );
486 hnd->status = werror_to_ntstatus( err );
487
488 if ( !NT_STATUS_IS_OK( hnd->status ) )
489 return CAC_FAILURE;
490
491 op->out.status = status_out;
492
493 if ( op->in.timeout == 0 )
494 return CAC_SUCCESS;
495
496 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
497 SVCCTL_PAUSED, op->in.timeout,
498 &op->out.status );
499}
500
501int cac_SvcContinueService( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
502 struct SvcContinueService *op )
503{
504 struct rpc_pipe_client *pipe_hnd = NULL;
505 WERROR err;
506
507 SERVICE_STATUS status_out;
508
509 if ( !hnd )
510 return CAC_FAILURE;
511
512 if ( !hnd->_internal.ctx ) {
513 hnd->status = NT_STATUS_INVALID_HANDLE;
514 return CAC_FAILURE;
515 }
516
517 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
518 hnd->status = NT_STATUS_INVALID_PARAMETER;
519 return CAC_FAILURE;
520 }
521
522 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
523 if ( !pipe_hnd ) {
524 hnd->status = NT_STATUS_INVALID_HANDLE;
525 return CAC_FAILURE;
526 }
527
528 err = rpccli_svcctl_control_service( pipe_hnd, mem_ctx,
529 op->in.svc_hnd,
530 SVCCTL_CONTROL_CONTINUE,
531 &status_out );
532 hnd->status = werror_to_ntstatus( err );
533
534 if ( !NT_STATUS_IS_OK( hnd->status ) )
535 return CAC_FAILURE;
536
537 op->out.status = status_out;
538
539 if ( op->in.timeout == 0 )
540 return CAC_SUCCESS;
541
542 return cac_WaitForService( hnd, mem_ctx, op->in.svc_hnd,
543 SVCCTL_RUNNING, op->in.timeout,
544 &op->out.status );
545}
546
547int cac_SvcGetDisplayName( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
548 struct SvcGetDisplayName *op )
549{
550 struct rpc_pipe_client *pipe_hnd = NULL;
551 WERROR err;
552
553 fstring disp_name_out;
554
555 if ( !hnd )
556 return CAC_FAILURE;
557
558 if ( !hnd->_internal.ctx ) {
559 hnd->status = NT_STATUS_INVALID_HANDLE;
560 return CAC_FAILURE;
561 }
562
563 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
564 hnd->status = NT_STATUS_INVALID_PARAMETER;
565 return CAC_FAILURE;
566 }
567
568 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
569 if ( !pipe_hnd ) {
570 hnd->status = NT_STATUS_INVALID_HANDLE;
571 return CAC_FAILURE;
572 }
573
574 err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd,
575 disp_name_out );
576 hnd->status = werror_to_ntstatus( err );
577
578 if ( !NT_STATUS_IS_OK( hnd->status ) )
579 return CAC_FAILURE;
580
581 op->out.display_name = talloc_strdup( mem_ctx, disp_name_out );
582
583 if ( !op->out.display_name ) {
584 hnd->status = NT_STATUS_NO_MEMORY;
585 return CAC_FAILURE;
586 }
587
588 return CAC_SUCCESS;
589}
590
591
592int cac_SvcGetServiceConfig( CacServerHandle * hnd, TALLOC_CTX * mem_ctx,
593 struct SvcGetServiceConfig *op )
594{
595 struct rpc_pipe_client *pipe_hnd = NULL;
596 WERROR err;
597
598 SERVICE_CONFIG config_out;
599
600 if ( !hnd )
601 return CAC_FAILURE;
602
603 if ( !hnd->_internal.ctx ) {
604 hnd->status = NT_STATUS_INVALID_HANDLE;
605 return CAC_FAILURE;
606 }
607
608 if ( !op || !op->in.svc_hnd || !mem_ctx ) {
609 hnd->status = NT_STATUS_INVALID_PARAMETER;
610 return CAC_FAILURE;
611 }
612
613 pipe_hnd = cac_GetPipe( hnd, PI_SVCCTL );
614 if ( !pipe_hnd ) {
615 hnd->status = NT_STATUS_INVALID_HANDLE;
616 return CAC_FAILURE;
617 }
618
619 err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd,
620 &config_out );
621 hnd->status = werror_to_ntstatus( err );
622
623 if ( !NT_STATUS_IS_OK( hnd->status ) )
624 return CAC_FAILURE;
625
626 if ( !cac_InitCacServiceConfig
627 ( mem_ctx, &config_out, &op->out.config ) ) {
628 hnd->status = NT_STATUS_NO_MEMORY;
629 return CAC_FAILURE;
630 }
631
632 return CAC_SUCCESS;
633
634}
Note: See TracBrowser for help on using the repository browser.