~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/libmsrpc/cac_svcctl.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
10
 
 *  
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.
15
 
 *  
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.
19
 
 */
20
 
 
21
 
#include "libmsrpc.h"
22
 
#include "libsmb_internal.h"
23
 
 
24
 
#define WAIT_SLEEP_TIME 300000
25
 
 
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;
30
 
 
31
 
   POLICY_HND *scm_out = NULL;
32
 
 
33
 
   if(!hnd) 
34
 
      return CAC_FAILURE;
35
 
 
36
 
   if(!hnd->_internal.ctx) {
37
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
38
 
      return CAC_FAILURE;
39
 
   }
40
 
 
41
 
   if(!op || op->in.access == 0 || !mem_ctx) {
42
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
43
 
      return CAC_FAILURE;
44
 
   }
45
 
   
46
 
   srv = cac_GetServer(hnd);
47
 
   if(!srv) {
48
 
      hnd->status = NT_STATUS_INVALID_CONNECTION;
49
 
      return CAC_FAILURE;
50
 
   }
51
 
 
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;
57
 
      }
58
 
 
59
 
      hnd->_internal.pipes[PI_SVCCTL] = True;
60
 
   }
61
 
 
62
 
   scm_out = talloc(mem_ctx, POLICY_HND);
63
 
   if(!scm_out) {
64
 
      hnd->status = NT_STATUS_NO_MEMORY;
65
 
      return CAC_FAILURE;
66
 
   }
67
 
 
68
 
   err = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, scm_out, op->in.access);
69
 
   hnd->status = werror_to_ntstatus(err);
70
 
 
71
 
   if(!NT_STATUS_IS_OK(hnd->status))
72
 
      return CAC_FAILURE;
73
 
 
74
 
   op->out.scm_hnd = scm_out;
75
 
 
76
 
   return CAC_SUCCESS;
77
 
}
78
 
 
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;
82
 
 
83
 
   if(!hnd) 
84
 
      return CAC_FAILURE;
85
 
 
86
 
   if(!hnd->_internal.ctx) {
87
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
88
 
      return CAC_FAILURE;
89
 
   }
90
 
 
91
 
   if(!scm_hnd || !mem_ctx) {
92
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
93
 
      return CAC_FAILURE;
94
 
   }
95
 
 
96
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
97
 
   if(!pipe_hnd) {
98
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
99
 
      return CAC_FAILURE;
100
 
   }
101
 
 
102
 
   err = rpccli_svcctl_close_service( pipe_hnd, mem_ctx, scm_hnd);
103
 
   hnd->status = werror_to_ntstatus(err);
104
 
 
105
 
   if(!NT_STATUS_IS_OK(hnd->status))
106
 
      return CAC_FAILURE;
107
 
 
108
 
   return CAC_SUCCESS;
109
 
}
110
 
 
111
 
int cac_SvcEnumServices(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcEnumServices *op) {
112
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
113
 
   WERROR err;
114
 
 
115
 
   uint32 type_buf  = 0;
116
 
   uint32 state_buf = 0;
117
 
 
118
 
   uint32 num_svc_out = 0;
119
 
 
120
 
   ENUM_SERVICES_STATUS *svc_buf = NULL;
121
 
 
122
 
   if(!hnd) 
123
 
      return CAC_FAILURE;
124
 
 
125
 
   if(!hnd->_internal.ctx) {
126
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
127
 
      return CAC_FAILURE;
128
 
   }
129
 
 
130
 
   if(!op || !op->in.scm_hnd || !mem_ctx) {
131
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
132
 
      return CAC_FAILURE;
133
 
   }
134
 
 
135
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
136
 
   if(!pipe_hnd) {
137
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
138
 
      return CAC_FAILURE;
139
 
   }
140
 
 
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;
143
 
 
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);
146
 
 
147
 
   if(!NT_STATUS_IS_OK(hnd->status))
148
 
      return CAC_FAILURE;
149
 
 
150
 
   op->out.services = cac_MakeServiceArray(mem_ctx, svc_buf, num_svc_out);
151
 
 
152
 
   if(!op->out.services) {
153
 
      hnd->status = NT_STATUS_NO_MEMORY;
154
 
      return CAC_FAILURE;
155
 
   }
156
 
 
157
 
   TALLOC_FREE(svc_buf);
158
 
 
159
 
   op->out.num_services = num_svc_out;
160
 
 
161
 
   return CAC_SUCCESS;
162
 
}
163
 
 
164
 
int cac_SvcOpenService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcOpenService *op) {
165
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
166
 
   WERROR err;
167
 
 
168
 
   POLICY_HND *svc_hnd_out = NULL;
169
 
 
170
 
   if(!hnd) 
171
 
      return CAC_FAILURE;
172
 
 
173
 
   if(!hnd->_internal.ctx) {
174
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
175
 
      return CAC_FAILURE;
176
 
   }
177
 
 
178
 
   if(!op || !op->in.scm_hnd || !op->in.name || !mem_ctx) {
179
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
180
 
      return CAC_FAILURE;
181
 
   }
182
 
 
183
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
184
 
   if(!pipe_hnd) {
185
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
186
 
      return CAC_FAILURE;
187
 
   }
188
 
 
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;
193
 
   }
194
 
 
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);
197
 
 
198
 
   if(!NT_STATUS_IS_OK(hnd->status))
199
 
      return CAC_FAILURE;
200
 
 
201
 
   op->out.svc_hnd = svc_hnd_out;
202
 
 
203
 
   return CAC_SUCCESS;
204
 
}
205
 
 
206
 
int cac_SvcControlService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcControlService *op) {
207
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
208
 
   WERROR err;
209
 
 
210
 
   SERVICE_STATUS status_out;
211
 
 
212
 
   if(!hnd) 
213
 
      return CAC_FAILURE;
214
 
 
215
 
   if(!hnd->_internal.ctx) {
216
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
217
 
      return CAC_FAILURE;
218
 
   }
219
 
 
220
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
221
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
222
 
      return CAC_FAILURE;
223
 
   }
224
 
 
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;
228
 
   }
229
 
 
230
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
231
 
   if(!pipe_hnd) {
232
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
233
 
      return CAC_FAILURE;
234
 
   }
235
 
 
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);
238
 
 
239
 
   if(!NT_STATUS_IS_OK(hnd->status))
240
 
      return CAC_FAILURE;
241
 
 
242
 
   return CAC_SUCCESS;
243
 
}
244
 
 
245
 
int cac_SvcGetStatus(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetStatus *op) {
246
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
247
 
   WERROR err;
248
 
 
249
 
   SERVICE_STATUS status_out;
250
 
 
251
 
   if(!hnd) 
252
 
      return CAC_FAILURE;
253
 
 
254
 
   if(!hnd->_internal.ctx) {
255
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
256
 
      return CAC_FAILURE;
257
 
   }
258
 
 
259
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
260
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
261
 
      return CAC_FAILURE;
262
 
   }
263
 
 
264
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
265
 
   if(!pipe_hnd) {
266
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
267
 
      return CAC_FAILURE;
268
 
   }
269
 
 
270
 
   err = rpccli_svcctl_query_status( pipe_hnd, mem_ctx, op->in.svc_hnd, &status_out);
271
 
   hnd->status = werror_to_ntstatus(err);
272
 
 
273
 
   if(!NT_STATUS_IS_OK(hnd->status))
274
 
      return CAC_FAILURE;
275
 
 
276
 
   op->out.status = status_out;
277
 
 
278
 
   return CAC_SUCCESS;
279
 
}
280
 
 
281
 
 
282
 
 
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
290
 
 */
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;
296
 
 
297
 
   if(!hnd || !mem_ctx || !svc_hnd || !status)
298
 
      return CAC_FAILURE;
299
 
 
300
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
301
 
   if(!pipe_hnd) {
302
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
303
 
      return CAC_FAILURE;
304
 
   }
305
 
 
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;
310
 
 
311
 
      err = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, svc_hnd, status);
312
 
      hnd->status = werror_to_ntstatus(err);
313
 
   }
314
 
 
315
 
   if(status->state == state) 
316
 
      return CAC_SUCCESS;
317
 
 
318
 
   return CAC_FAILURE;
319
 
}
320
 
 
321
 
int cac_SvcStartService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStartService *op) {
322
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
323
 
   WERROR err;
324
 
 
325
 
   SERVICE_STATUS status_buf;
326
 
 
327
 
   if(!hnd) 
328
 
      return CAC_FAILURE;
329
 
 
330
 
   if(!hnd->_internal.ctx) {
331
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
332
 
      return CAC_FAILURE;
333
 
   }
334
 
 
335
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
336
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
337
 
      return CAC_FAILURE;
338
 
   }
339
 
 
340
 
   if(op->in.num_parms != 0 && op->in.parms == NULL) {
341
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
342
 
      return CAC_FAILURE;
343
 
   }
344
 
 
345
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
346
 
   if(!pipe_hnd) {
347
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
348
 
      return CAC_FAILURE;
349
 
   }
350
 
 
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);
353
 
 
354
 
   if(!NT_STATUS_IS_OK(hnd->status))
355
 
      return CAC_FAILURE;
356
 
 
357
 
   if(op->in.timeout == 0)
358
 
      return CAC_SUCCESS;
359
 
 
360
 
   return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &status_buf);
361
 
}
362
 
 
363
 
int cac_SvcStopService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcStopService *op) {
364
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
365
 
   WERROR err;
366
 
 
367
 
   SERVICE_STATUS status_out;
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
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
383
 
   if(!pipe_hnd) {
384
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
385
 
      return CAC_FAILURE;
386
 
   }
387
 
 
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);
390
 
 
391
 
   if(!NT_STATUS_IS_OK(hnd->status))
392
 
      return CAC_FAILURE;
393
 
 
394
 
   op->out.status = status_out;
395
 
 
396
 
   if(op->in.timeout == 0)
397
 
      return CAC_SUCCESS;
398
 
 
399
 
   return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_STOPPED, op->in.timeout, &op->out.status);
400
 
}
401
 
 
402
 
int cac_SvcPauseService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcPauseService *op) {
403
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
404
 
   WERROR err;
405
 
 
406
 
   SERVICE_STATUS status_out;
407
 
 
408
 
   if(!hnd) 
409
 
      return CAC_FAILURE;
410
 
 
411
 
   if(!hnd->_internal.ctx) {
412
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
413
 
      return CAC_FAILURE;
414
 
   }
415
 
 
416
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
417
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
418
 
      return CAC_FAILURE;
419
 
   }
420
 
 
421
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
422
 
   if(!pipe_hnd) {
423
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
424
 
      return CAC_FAILURE;
425
 
   }
426
 
 
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);
429
 
 
430
 
   if(!NT_STATUS_IS_OK(hnd->status))
431
 
      return CAC_FAILURE;
432
 
 
433
 
   op->out.status = status_out;
434
 
 
435
 
   if(op->in.timeout == 0)
436
 
      return CAC_SUCCESS;
437
 
 
438
 
   return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_PAUSED, op->in.timeout, &op->out.status);
439
 
}
440
 
 
441
 
int cac_SvcContinueService(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcContinueService *op) {
442
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
443
 
   WERROR err;
444
 
 
445
 
   SERVICE_STATUS status_out;
446
 
 
447
 
   if(!hnd) 
448
 
      return CAC_FAILURE;
449
 
 
450
 
   if(!hnd->_internal.ctx) {
451
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
452
 
      return CAC_FAILURE;
453
 
   }
454
 
 
455
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
456
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
457
 
      return CAC_FAILURE;
458
 
   }
459
 
 
460
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
461
 
   if(!pipe_hnd) {
462
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
463
 
      return CAC_FAILURE;
464
 
   }
465
 
 
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);
468
 
 
469
 
   if(!NT_STATUS_IS_OK(hnd->status))
470
 
      return CAC_FAILURE;
471
 
 
472
 
   op->out.status = status_out;
473
 
 
474
 
   if(op->in.timeout == 0)
475
 
      return CAC_SUCCESS;
476
 
 
477
 
   return cac_WaitForService(hnd, mem_ctx, op->in.svc_hnd, SVCCTL_RUNNING, op->in.timeout, &op->out.status);
478
 
}
479
 
 
480
 
int cac_SvcGetDisplayName(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetDisplayName *op) {
481
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
482
 
   WERROR err;
483
 
 
484
 
   fstring disp_name_out;
485
 
 
486
 
   if(!hnd) 
487
 
      return CAC_FAILURE;
488
 
 
489
 
   if(!hnd->_internal.ctx) {
490
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
491
 
      return CAC_FAILURE;
492
 
   }
493
 
 
494
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
495
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
496
 
      return CAC_FAILURE;
497
 
   }
498
 
 
499
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
500
 
   if(!pipe_hnd) {
501
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
502
 
      return CAC_FAILURE;
503
 
   }
504
 
 
505
 
   err = rpccli_svcctl_get_dispname( pipe_hnd, mem_ctx, op->in.svc_hnd, disp_name_out);
506
 
   hnd->status = werror_to_ntstatus(err);
507
 
 
508
 
   if(!NT_STATUS_IS_OK(hnd->status))
509
 
      return CAC_FAILURE;
510
 
 
511
 
   op->out.display_name = talloc_strdup(mem_ctx, disp_name_out);
512
 
 
513
 
   if(!op->out.display_name) {
514
 
      hnd->status = NT_STATUS_NO_MEMORY;
515
 
      return CAC_FAILURE;
516
 
   }
517
 
 
518
 
   return CAC_SUCCESS;
519
 
}
520
 
 
521
 
 
522
 
int cac_SvcGetServiceConfig(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct SvcGetServiceConfig *op) {
523
 
   struct rpc_pipe_client *pipe_hnd        = NULL;
524
 
   WERROR err;
525
 
 
526
 
   SERVICE_CONFIG config_out;
527
 
   
528
 
   if(!hnd) 
529
 
      return CAC_FAILURE;
530
 
 
531
 
   if(!hnd->_internal.ctx) {
532
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
533
 
      return CAC_FAILURE;
534
 
   }
535
 
 
536
 
   if(!op || !op->in.svc_hnd || !mem_ctx) {
537
 
      hnd->status = NT_STATUS_INVALID_PARAMETER;
538
 
      return CAC_FAILURE;
539
 
   }
540
 
 
541
 
   pipe_hnd = cac_GetPipe(hnd, PI_SVCCTL);
542
 
   if(!pipe_hnd) {
543
 
      hnd->status = NT_STATUS_INVALID_HANDLE;
544
 
      return CAC_FAILURE;
545
 
   }
546
 
 
547
 
   err = rpccli_svcctl_query_config( pipe_hnd, mem_ctx, op->in.svc_hnd, &config_out);
548
 
   hnd->status = werror_to_ntstatus(err);
549
 
 
550
 
   if(!NT_STATUS_IS_OK(hnd->status))
551
 
      return CAC_FAILURE;
552
 
 
553
 
   if(!cac_InitCacServiceConfig(mem_ctx, &config_out, &op->out.config)) {
554
 
      hnd->status = NT_STATUS_NO_MEMORY;
555
 
      return CAC_FAILURE;
556
 
   }
557
 
 
558
 
   return CAC_SUCCESS;
559
 
 
560
 
}