~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/rpc_server/srv_svcctl_nt.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  RPC Pipe client / server routines
 
4
 *
 
5
 *  Copyright (C) Marcin Krzysztof Porwit           2005.
 
6
 *
 
7
 *  Largely Rewritten (Again) by:
 
8
 *  Copyright (C) Gerald (Jerry) Carter             2005.
 
9
 *  Copyright (C) Guenther Deschner                 2008,2009.
 
10
 *
 
11
 *  This program is free software; you can redistribute it and/or modify
 
12
 *  it under the terms of the GNU General Public License as published by
 
13
 *  the Free Software Foundation; either version 3 of the License, or
 
14
 *  (at your option) any later version.
 
15
 *
 
16
 *  This program is distributed in the hope that it will be useful,
 
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 *  GNU General Public License for more details.
 
20
 *
 
21
 *  You should have received a copy of the GNU General Public License
 
22
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
23
 */
 
24
 
 
25
#include "includes.h"
 
26
 
 
27
#undef DBGC_CLASS
 
28
#define DBGC_CLASS DBGC_RPC_SRV
 
29
 
 
30
struct service_control_op {
 
31
        const char *name;
 
32
        SERVICE_CONTROL_OPS *ops;
 
33
};
 
34
 
 
35
/* handle external services */
 
36
extern SERVICE_CONTROL_OPS rcinit_svc_ops;
 
37
 
 
38
/* builtin services (see service_db.c and services/svc_*.c */
 
39
extern SERVICE_CONTROL_OPS spoolss_svc_ops;
 
40
extern SERVICE_CONTROL_OPS netlogon_svc_ops;
 
41
extern SERVICE_CONTROL_OPS winreg_svc_ops;
 
42
extern SERVICE_CONTROL_OPS wins_svc_ops;
 
43
 
 
44
/* make sure this number patches the number of builtin
 
45
   SERVICE_CONTROL_OPS structure listed above */
 
46
 
 
47
#define SVCCTL_NUM_INTERNAL_SERVICES    4
 
48
 
 
49
struct service_control_op *svcctl_ops;
 
50
 
 
51
static const struct generic_mapping scm_generic_map =
 
52
        { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
 
53
static const struct generic_mapping svc_generic_map =
 
54
        { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
 
55
 
 
56
 
 
57
/********************************************************************
 
58
********************************************************************/
 
59
 
 
60
bool init_service_op_table( void )
 
61
{
 
62
        const char **service_list = lp_svcctl_list();
 
63
        int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length( service_list );
 
64
        int i;
 
65
 
 
66
        if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {
 
67
                DEBUG(0,("init_service_op_table: talloc() failed!\n"));
 
68
                return False;
 
69
        }
 
70
 
 
71
        /* services listed in smb.conf get the rc.init interface */
 
72
 
 
73
        for ( i=0; service_list && service_list[i]; i++ ) {
 
74
                svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );
 
75
                svcctl_ops[i].ops  = &rcinit_svc_ops;
 
76
        }
 
77
 
 
78
        /* add builtin services */
 
79
 
 
80
        svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
 
81
        svcctl_ops[i].ops  = &spoolss_svc_ops;
 
82
        i++;
 
83
 
 
84
        svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
 
85
        svcctl_ops[i].ops  = &netlogon_svc_ops;
 
86
        i++;
 
87
 
 
88
        svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
 
89
        svcctl_ops[i].ops  = &winreg_svc_ops;
 
90
        i++;
 
91
 
 
92
        svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
 
93
        svcctl_ops[i].ops  = &wins_svc_ops;
 
94
        i++;
 
95
 
 
96
        /* NULL terminate the array */
 
97
 
 
98
        svcctl_ops[i].name = NULL;
 
99
        svcctl_ops[i].ops  = NULL;
 
100
 
 
101
        return True;
 
102
}
 
103
 
 
104
/********************************************************************
 
105
********************************************************************/
 
106
 
 
107
static struct service_control_op* find_service_by_name( const char *name )
 
108
{
 
109
        int i;
 
110
 
 
111
        for ( i=0; svcctl_ops[i].name; i++ ) {
 
112
                if ( strequal( name, svcctl_ops[i].name ) )
 
113
                        return &svcctl_ops[i];
 
114
        }
 
115
 
 
116
        return NULL;
 
117
}
 
118
/********************************************************************
 
119
********************************************************************/
 
120
 
 
121
static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
 
122
                                     uint32 access_desired, uint32 *access_granted )
 
123
{
 
124
        if ( geteuid() == sec_initial_uid() ) {
 
125
                DEBUG(5,("svcctl_access_check: using root's token\n"));
 
126
                token = get_root_nt_token();
 
127
        }
 
128
 
 
129
        return se_access_check( sec_desc, token, access_desired, access_granted);
 
130
}
 
131
 
 
132
/********************************************************************
 
133
********************************************************************/
 
134
 
 
135
static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
 
136
{
 
137
        SEC_ACE ace[2];
 
138
        size_t i = 0;
 
139
        SEC_DESC *sd;
 
140
        SEC_ACL *theacl;
 
141
        size_t sd_size;
 
142
 
 
143
        /* basic access for Everyone */
 
144
 
 
145
        init_sec_ace(&ace[i++], &global_sid_World,
 
146
                SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0);
 
147
 
 
148
        /* Full Access 'BUILTIN\Administrators' */
 
149
 
 
150
        init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
 
151
                SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0);
 
152
 
 
153
 
 
154
        /* create the security descriptor */
 
155
 
 
156
        if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
 
157
                return NULL;
 
158
 
 
159
        if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
 
160
                                  SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
 
161
                                  theacl, &sd_size)) )
 
162
                return NULL;
 
163
 
 
164
        return sd;
 
165
}
 
166
 
 
167
/******************************************************************
 
168
 Find a registry key handle and return a SERVICE_INFO
 
169
 *****************************************************************/
 
170
 
 
171
static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, struct policy_handle *hnd)
 
172
{
 
173
        SERVICE_INFO *service_info = NULL;
 
174
 
 
175
        if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) {
 
176
                DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
 
177
                return NULL;
 
178
        }
 
179
 
 
180
        return service_info;
 
181
}
 
182
 
 
183
/******************************************************************
 
184
 *****************************************************************/
 
185
 
 
186
static WERROR create_open_service_handle( pipes_struct *p, struct policy_handle *handle, uint32 type,
 
187
                                          const char *service, uint32 access_granted )
 
188
{
 
189
        SERVICE_INFO *info = NULL;
 
190
        WERROR result = WERR_OK;
 
191
        struct service_control_op *s_op;
 
192
 
 
193
        if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )
 
194
                return WERR_NOMEM;
 
195
 
 
196
        /* the Service Manager has a NULL name */
 
197
 
 
198
        info->type = SVC_HANDLE_IS_SCM;
 
199
 
 
200
        switch ( type ) {
 
201
        case SVC_HANDLE_IS_SCM:
 
202
                info->type = SVC_HANDLE_IS_SCM;
 
203
                break;
 
204
 
 
205
        case SVC_HANDLE_IS_DBLOCK:
 
206
                info->type = SVC_HANDLE_IS_DBLOCK;
 
207
                break;
 
208
 
 
209
        case SVC_HANDLE_IS_SERVICE:
 
210
                info->type = SVC_HANDLE_IS_SERVICE;
 
211
 
 
212
                /* lookup the SERVICE_CONTROL_OPS */
 
213
 
 
214
                if ( !(s_op = find_service_by_name( service )) ) {
 
215
                        result = WERR_NO_SUCH_SERVICE;
 
216
                        goto done;
 
217
                }
 
218
 
 
219
                info->ops = s_op->ops;
 
220
 
 
221
                if ( !(info->name  = talloc_strdup( info, s_op->name )) ) {
 
222
                        result = WERR_NOMEM;
 
223
                        goto done;
 
224
                }
 
225
                break;
 
226
 
 
227
        default:
 
228
                result = WERR_NO_SUCH_SERVICE;
 
229
                goto done;
 
230
        }
 
231
 
 
232
        info->access_granted = access_granted;
 
233
 
 
234
        /* store the SERVICE_INFO and create an open handle */
 
235
 
 
236
        if ( !create_policy_hnd( p, handle, info ) ) {
 
237
                result = WERR_ACCESS_DENIED;
 
238
                goto done;
 
239
        }
 
240
 
 
241
done:
 
242
        if ( !W_ERROR_IS_OK(result) )
 
243
                TALLOC_FREE(info);
 
244
 
 
245
        return result;
 
246
}
 
247
 
 
248
/********************************************************************
 
249
 _svcctl_OpenSCManagerW
 
250
********************************************************************/
 
251
 
 
252
WERROR _svcctl_OpenSCManagerW(pipes_struct *p,
 
253
                              struct svcctl_OpenSCManagerW *r)
 
254
{
 
255
        SEC_DESC *sec_desc;
 
256
        uint32 access_granted = 0;
 
257
        NTSTATUS status;
 
258
 
 
259
        /* perform access checks */
 
260
 
 
261
        if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
 
262
                return WERR_NOMEM;
 
263
 
 
264
        se_map_generic( &r->in.access_mask, &scm_generic_map );
 
265
        status = svcctl_access_check( sec_desc, p->server_info->ptok,
 
266
                                      r->in.access_mask, &access_granted );
 
267
        if ( !NT_STATUS_IS_OK(status) )
 
268
                return ntstatus_to_werror( status );
 
269
 
 
270
        return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
 
271
}
 
272
 
 
273
/********************************************************************
 
274
 _svcctl_OpenServiceW
 
275
********************************************************************/
 
276
 
 
277
WERROR _svcctl_OpenServiceW(pipes_struct *p,
 
278
                            struct svcctl_OpenServiceW *r)
 
279
{
 
280
        SEC_DESC *sec_desc;
 
281
        uint32 access_granted = 0;
 
282
        NTSTATUS status;
 
283
        const char *service = NULL;
 
284
 
 
285
        service = r->in.ServiceName;
 
286
        if (!service) {
 
287
                return WERR_NOMEM;
 
288
        }
 
289
        DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service));
 
290
 
 
291
        /* based on my tests you can open a service if you have a valid scm handle */
 
292
 
 
293
        if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) )
 
294
                return WERR_BADFID;
 
295
 
 
296
        /* perform access checks.  Use the root token in order to ensure that we
 
297
           retrieve the security descriptor */
 
298
 
 
299
        if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) )
 
300
                return WERR_NOMEM;
 
301
 
 
302
        se_map_generic( &r->in.access_mask, &svc_generic_map );
 
303
        status = svcctl_access_check( sec_desc, p->server_info->ptok,
 
304
                                      r->in.access_mask, &access_granted );
 
305
        if ( !NT_STATUS_IS_OK(status) )
 
306
                return ntstatus_to_werror( status );
 
307
 
 
308
        return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
 
309
}
 
310
 
 
311
/********************************************************************
 
312
 _svcctl_CloseServiceHandle
 
313
********************************************************************/
 
314
 
 
315
WERROR _svcctl_CloseServiceHandle(pipes_struct *p,
 
316
                                  struct svcctl_CloseServiceHandle *r)
 
317
{
 
318
        if ( !close_policy_hnd( p, r->in.handle ) )
 
319
                return  WERR_BADFID;
 
320
 
 
321
        ZERO_STRUCTP(r->out.handle);
 
322
 
 
323
        return WERR_OK;
 
324
}
 
325
 
 
326
/********************************************************************
 
327
 _svcctl_GetServiceDisplayNameW
 
328
********************************************************************/
 
329
 
 
330
WERROR _svcctl_GetServiceDisplayNameW(pipes_struct *p,
 
331
                                      struct svcctl_GetServiceDisplayNameW *r)
 
332
{
 
333
        const char *service;
 
334
        const char *display_name;
 
335
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
336
 
 
337
        /* can only use an SCM handle here */
 
338
 
 
339
        if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
 
340
                return WERR_BADFID;
 
341
 
 
342
        service = r->in.service_name;
 
343
 
 
344
        display_name = svcctl_lookup_dispname(p->mem_ctx, service,
 
345
                                              p->server_info->ptok);
 
346
        if (!display_name) {
 
347
                display_name = "";
 
348
        }
 
349
 
 
350
        *r->out.display_name = display_name;
 
351
        *r->out.display_name_length = strlen(display_name);
 
352
 
 
353
        return WERR_OK;
 
354
}
 
355
 
 
356
/********************************************************************
 
357
 _svcctl_QueryServiceStatus
 
358
********************************************************************/
 
359
 
 
360
WERROR _svcctl_QueryServiceStatus(pipes_struct *p,
 
361
                                  struct svcctl_QueryServiceStatus *r)
 
362
{
 
363
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
364
 
 
365
        /* perform access checks */
 
366
 
 
367
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
368
                return WERR_BADFID;
 
369
 
 
370
        if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
 
371
                return WERR_ACCESS_DENIED;
 
372
 
 
373
        /* try the service specific status call */
 
374
 
 
375
        return info->ops->service_status( info->name, r->out.service_status );
 
376
}
 
377
 
 
378
/********************************************************************
 
379
********************************************************************/
 
380
 
 
381
static int enumerate_status( TALLOC_CTX *ctx, struct ENUM_SERVICE_STATUSW **status, NT_USER_TOKEN *token )
 
382
{
 
383
        int num_services = 0;
 
384
        int i;
 
385
        struct ENUM_SERVICE_STATUSW *st;
 
386
        const char *display_name;
 
387
 
 
388
        /* just count */
 
389
        while ( svcctl_ops[num_services].name )
 
390
                num_services++;
 
391
 
 
392
        if ( !(st = TALLOC_ARRAY( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
 
393
                DEBUG(0,("enumerate_status: talloc() failed!\n"));
 
394
                return -1;
 
395
        }
 
396
 
 
397
        for ( i=0; i<num_services; i++ ) {
 
398
                st[i].service_name = talloc_strdup(st, svcctl_ops[i].name );
 
399
 
 
400
                display_name = svcctl_lookup_dispname(ctx, svcctl_ops[i].name, token );
 
401
                st[i].display_name = talloc_strdup(st, display_name ? display_name : "");
 
402
 
 
403
                svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
 
404
        }
 
405
 
 
406
        *status = st;
 
407
 
 
408
        return num_services;
 
409
}
 
410
 
 
411
/********************************************************************
 
412
 _svcctl_EnumServicesStatusW
 
413
********************************************************************/
 
414
 
 
415
WERROR _svcctl_EnumServicesStatusW(pipes_struct *p,
 
416
                                   struct svcctl_EnumServicesStatusW *r)
 
417
{
 
418
        struct ENUM_SERVICE_STATUSW *services = NULL;
 
419
        int num_services;
 
420
        int i = 0;
 
421
        size_t buffer_size = 0;
 
422
        WERROR result = WERR_OK;
 
423
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
424
        NT_USER_TOKEN *token = p->server_info->ptok;
 
425
        DATA_BLOB blob = data_blob_null;
 
426
 
 
427
        /* perform access checks */
 
428
 
 
429
        if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
 
430
                return WERR_BADFID;
 
431
 
 
432
        if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
 
433
                return WERR_ACCESS_DENIED;
 
434
        }
 
435
 
 
436
        num_services = enumerate_status( p->mem_ctx, &services, token );
 
437
        if (num_services == -1 ) {
 
438
                return WERR_NOMEM;
 
439
        }
 
440
 
 
441
        for ( i=0; i<num_services; i++ ) {
 
442
                buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], NULL, 0);
 
443
        }
 
444
 
 
445
        buffer_size += buffer_size % 4;
 
446
 
 
447
        if (buffer_size > r->in.offered) {
 
448
                num_services = 0;
 
449
                result = WERR_MORE_DATA;
 
450
        }
 
451
 
 
452
        if ( W_ERROR_IS_OK(result) ) {
 
453
 
 
454
                enum ndr_err_code ndr_err;
 
455
                struct ndr_push *ndr;
 
456
 
 
457
                ndr = ndr_push_init_ctx(p->mem_ctx, NULL);
 
458
                if (ndr == NULL) {
 
459
                        return WERR_INVALID_PARAM;
 
460
                }
 
461
 
 
462
                ndr_err = ndr_push_ENUM_SERVICE_STATUSW_array(
 
463
                        ndr, num_services, services);
 
464
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
465
                        return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err));
 
466
                }
 
467
                blob = ndr_push_blob(ndr);
 
468
                memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
 
469
        }
 
470
 
 
471
        *r->out.needed                  = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
472
        *r->out.services_returned       = (uint32)num_services;
 
473
        if (r->out.resume_handle) {
 
474
                *r->out.resume_handle   = 0;
 
475
        }
 
476
 
 
477
        return result;
 
478
}
 
479
 
 
480
/********************************************************************
 
481
 _svcctl_StartServiceW
 
482
********************************************************************/
 
483
 
 
484
WERROR _svcctl_StartServiceW(pipes_struct *p,
 
485
                             struct svcctl_StartServiceW *r)
 
486
{
 
487
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
488
 
 
489
        /* perform access checks */
 
490
 
 
491
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
492
                return WERR_BADFID;
 
493
 
 
494
        if ( !(info->access_granted & SC_RIGHT_SVC_START) )
 
495
                return WERR_ACCESS_DENIED;
 
496
 
 
497
        return info->ops->start_service( info->name );
 
498
}
 
499
 
 
500
/********************************************************************
 
501
 _svcctl_ControlService
 
502
********************************************************************/
 
503
 
 
504
WERROR _svcctl_ControlService(pipes_struct *p,
 
505
                              struct svcctl_ControlService *r)
 
506
{
 
507
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
508
 
 
509
        /* perform access checks */
 
510
 
 
511
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
512
                return WERR_BADFID;
 
513
 
 
514
        switch ( r->in.control ) {
 
515
        case SVCCTL_CONTROL_STOP:
 
516
                if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
 
517
                        return WERR_ACCESS_DENIED;
 
518
 
 
519
                return info->ops->stop_service( info->name,
 
520
                                                r->out.service_status );
 
521
 
 
522
        case SVCCTL_CONTROL_INTERROGATE:
 
523
                if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
 
524
                        return WERR_ACCESS_DENIED;
 
525
 
 
526
                return info->ops->service_status( info->name,
 
527
                                                  r->out.service_status );
 
528
        default:
 
529
                return WERR_INVALID_PARAM;
 
530
        }
 
531
}
 
532
 
 
533
/********************************************************************
 
534
 _svcctl_EnumDependentServicesW
 
535
********************************************************************/
 
536
 
 
537
WERROR _svcctl_EnumDependentServicesW(pipes_struct *p,
 
538
                                      struct svcctl_EnumDependentServicesW *r)
 
539
{
 
540
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service );
 
541
 
 
542
        /* perform access checks */
 
543
 
 
544
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
545
                return WERR_BADFID;
 
546
 
 
547
        if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
 
548
                return WERR_ACCESS_DENIED;
 
549
 
 
550
        switch (r->in.state) {
 
551
        case SERVICE_STATE_ACTIVE:
 
552
        case SERVICE_STATE_INACTIVE:
 
553
        case SERVICE_STATE_ALL:
 
554
                break;
 
555
        default:
 
556
                return WERR_INVALID_PARAM;
 
557
        }
 
558
 
 
559
        /* we have to set the outgoing buffer size to the same as the
 
560
           incoming buffer size (even in the case of failure */
 
561
        /* this is done in the autogenerated server already - gd */
 
562
 
 
563
        *r->out.needed = r->in.offered;
 
564
 
 
565
        /* no dependent services...basically a stub function */
 
566
        *r->out.services_returned = 0;
 
567
 
 
568
        return WERR_OK;
 
569
}
 
570
 
 
571
/********************************************************************
 
572
 _svcctl_QueryServiceStatusEx
 
573
********************************************************************/
 
574
 
 
575
WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p,
 
576
                                    struct svcctl_QueryServiceStatusEx *r)
 
577
{
 
578
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
579
        uint32 buffer_size;
 
580
 
 
581
        /* perform access checks */
 
582
 
 
583
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
584
                return WERR_BADFID;
 
585
 
 
586
        if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
 
587
                return WERR_ACCESS_DENIED;
 
588
 
 
589
        /* we have to set the outgoing buffer size to the same as the
 
590
           incoming buffer size (even in the case of failure) */
 
591
        *r->out.needed = r->in.offered;
 
592
 
 
593
        switch ( r->in.info_level ) {
 
594
                case SVC_STATUS_PROCESS_INFO:
 
595
                {
 
596
                        struct SERVICE_STATUS_PROCESS svc_stat_proc;
 
597
                        enum ndr_err_code ndr_err;
 
598
                        DATA_BLOB blob;
 
599
 
 
600
                        /* Get the status of the service.. */
 
601
                        info->ops->service_status( info->name, &svc_stat_proc.status );
 
602
                        svc_stat_proc.process_id     = sys_getpid();
 
603
                        svc_stat_proc.service_flags  = 0x0;
 
604
 
 
605
                        ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL,
 
606
                                                       &svc_stat_proc,
 
607
                                                       (ndr_push_flags_fn_t)ndr_push_SERVICE_STATUS_PROCESS);
 
608
                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
609
                                return WERR_INVALID_PARAM;
 
610
                        }
 
611
 
 
612
                        r->out.buffer = blob.data;
 
613
                        buffer_size = sizeof(struct SERVICE_STATUS_PROCESS);
 
614
                        break;
 
615
                }
 
616
 
 
617
                default:
 
618
                        return WERR_UNKNOWN_LEVEL;
 
619
        }
 
620
 
 
621
 
 
622
        buffer_size += buffer_size % 4;
 
623
        *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
624
 
 
625
        if (buffer_size > r->in.offered ) {
 
626
                return WERR_INSUFFICIENT_BUFFER;
 
627
        }
 
628
 
 
629
        return WERR_OK;
 
630
}
 
631
 
 
632
/********************************************************************
 
633
********************************************************************/
 
634
 
 
635
static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name,
 
636
                               struct QUERY_SERVICE_CONFIG *config,
 
637
                               NT_USER_TOKEN *token )
 
638
{
 
639
        REGVAL_CTR *values;
 
640
        REGISTRY_VALUE *val;
 
641
 
 
642
        /* retrieve the registry values for this service */
 
643
 
 
644
        if ( !(values = svcctl_fetch_regvalues( name, token )) )
 
645
                return WERR_REG_CORRUPT;
 
646
 
 
647
        /* now fill in the individual values */
 
648
 
 
649
        if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL )
 
650
                config->displayname = regval_sz(val);
 
651
        else
 
652
                config->displayname = name;
 
653
 
 
654
        if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) {
 
655
                config->startname = regval_sz(val);
 
656
        }
 
657
 
 
658
        if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) {
 
659
                config->executablepath = regval_sz(val);
 
660
        }
 
661
 
 
662
        /* a few hard coded values */
 
663
        /* loadordergroup and dependencies are empty */
 
664
 
 
665
        config->tag_id           = 0x00000000;                  /* unassigned loadorder group */
 
666
        config->service_type     = SERVICE_TYPE_WIN32_OWN_PROCESS;
 
667
        config->error_control    = SVCCTL_SVC_ERROR_NORMAL;
 
668
 
 
669
        /* set the start type.  NetLogon and WINS are disabled to prevent
 
670
           the client from showing the "Start" button (if of course the services
 
671
           are not running */
 
672
 
 
673
        if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
 
674
                config->start_type = SVCCTL_DISABLED;
 
675
        else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
 
676
                config->start_type = SVCCTL_DISABLED;
 
677
        else
 
678
                config->start_type = SVCCTL_DEMAND_START;
 
679
 
 
680
 
 
681
        TALLOC_FREE( values );
 
682
 
 
683
        return WERR_OK;
 
684
}
 
685
 
 
686
/********************************************************************
 
687
 _svcctl_QueryServiceConfigW
 
688
********************************************************************/
 
689
 
 
690
WERROR _svcctl_QueryServiceConfigW(pipes_struct *p,
 
691
                                   struct svcctl_QueryServiceConfigW *r)
 
692
{
 
693
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
694
        uint32 buffer_size;
 
695
        WERROR wresult;
 
696
 
 
697
        /* perform access checks */
 
698
 
 
699
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
700
                return WERR_BADFID;
 
701
 
 
702
        if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
 
703
                return WERR_ACCESS_DENIED;
 
704
 
 
705
        /* we have to set the outgoing buffer size to the same as the
 
706
           incoming buffer size (even in the case of failure */
 
707
 
 
708
        *r->out.needed = r->in.offered;
 
709
 
 
710
        wresult = fill_svc_config( p->mem_ctx, info->name, r->out.query,
 
711
                                   p->server_info->ptok);
 
712
        if ( !W_ERROR_IS_OK(wresult) )
 
713
                return wresult;
 
714
 
 
715
        buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, NULL, 0);
 
716
        *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
717
 
 
718
        if (buffer_size > r->in.offered ) {
 
719
                ZERO_STRUCTP(r->out.query);
 
720
                return WERR_INSUFFICIENT_BUFFER;
 
721
        }
 
722
 
 
723
        return WERR_OK;
 
724
}
 
725
 
 
726
/********************************************************************
 
727
 _svcctl_QueryServiceConfig2W
 
728
********************************************************************/
 
729
 
 
730
WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p,
 
731
                                    struct svcctl_QueryServiceConfig2W *r)
 
732
{
 
733
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
734
        uint32 buffer_size;
 
735
 
 
736
        /* perform access checks */
 
737
 
 
738
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
 
739
                return WERR_BADFID;
 
740
 
 
741
        if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
 
742
                return WERR_ACCESS_DENIED;
 
743
 
 
744
        /* we have to set the outgoing buffer size to the same as the
 
745
           incoming buffer size (even in the case of failure */
 
746
        *r->out.needed = r->in.offered;
 
747
 
 
748
        switch ( r->in.info_level ) {
 
749
        case SERVICE_CONFIG_DESCRIPTION:
 
750
                {
 
751
                        struct SERVICE_DESCRIPTION desc_buf;
 
752
                        const char *description;
 
753
                        enum ndr_err_code ndr_err;
 
754
                        DATA_BLOB blob;
 
755
 
 
756
                        description = svcctl_lookup_description(
 
757
                                p->mem_ctx, info->name, p->server_info->ptok);
 
758
 
 
759
                        desc_buf.description = description;
 
760
 
 
761
                        ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL,
 
762
                                                       &desc_buf,
 
763
                                                       (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION);
 
764
                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
765
                                return WERR_INVALID_PARAM;
 
766
                        }
 
767
 
 
768
                        buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, NULL, 0);
 
769
                        r->out.buffer = blob.data;
 
770
 
 
771
                        break;
 
772
                }
 
773
                break;
 
774
        case SERVICE_CONFIG_FAILURE_ACTIONS:
 
775
                {
 
776
                        struct SERVICE_FAILURE_ACTIONS actions;
 
777
                        enum ndr_err_code ndr_err;
 
778
                        DATA_BLOB blob;
 
779
 
 
780
                        /* nothing to say...just service the request */
 
781
 
 
782
                        ZERO_STRUCT( actions );
 
783
 
 
784
                        ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL,
 
785
                                                       &actions,
 
786
                                                       (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS);
 
787
                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
788
                                return WERR_INVALID_PARAM;
 
789
                        }
 
790
 
 
791
                        buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, NULL, 0);
 
792
                        r->out.buffer = blob.data;
 
793
 
 
794
                        break;
 
795
                }
 
796
                break;
 
797
 
 
798
        default:
 
799
                return WERR_UNKNOWN_LEVEL;
 
800
        }
 
801
 
 
802
        buffer_size += buffer_size % 4;
 
803
        *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
 
804
 
 
805
        if (buffer_size > r->in.offered)
 
806
                return WERR_INSUFFICIENT_BUFFER;
 
807
 
 
808
        return WERR_OK;
 
809
}
 
810
 
 
811
/********************************************************************
 
812
 _svcctl_LockServiceDatabase
 
813
********************************************************************/
 
814
 
 
815
WERROR _svcctl_LockServiceDatabase(pipes_struct *p,
 
816
                                   struct svcctl_LockServiceDatabase *r)
 
817
{
 
818
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
819
 
 
820
        /* perform access checks */
 
821
 
 
822
        if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
 
823
                return WERR_BADFID;
 
824
 
 
825
        if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
 
826
                return WERR_ACCESS_DENIED;
 
827
 
 
828
        /* Just open a handle.  Doesn't actually lock anything */
 
829
 
 
830
        return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
 
831
}
 
832
 
 
833
/********************************************************************
 
834
 _svcctl_UnlockServiceDatabase
 
835
********************************************************************/
 
836
 
 
837
WERROR _svcctl_UnlockServiceDatabase(pipes_struct *p,
 
838
                                     struct svcctl_UnlockServiceDatabase *r)
 
839
{
 
840
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
 
841
 
 
842
 
 
843
        if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
 
844
                return WERR_BADFID;
 
845
 
 
846
        return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_BADFID;
 
847
}
 
848
 
 
849
/********************************************************************
 
850
 _svcctl_QueryServiceObjectSecurity
 
851
********************************************************************/
 
852
 
 
853
WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p,
 
854
                                          struct svcctl_QueryServiceObjectSecurity *r)
 
855
{
 
856
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
857
        SEC_DESC *sec_desc;
 
858
        NTSTATUS status;
 
859
        uint8_t *buffer = NULL;
 
860
        size_t len = 0;
 
861
 
 
862
 
 
863
        /* only support the SCM and individual services */
 
864
 
 
865
        if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
 
866
                return WERR_BADFID;
 
867
 
 
868
        /* check access reights (according to MSDN) */
 
869
 
 
870
        if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
 
871
                return WERR_ACCESS_DENIED;
 
872
 
 
873
        /* TODO: handle something besides DACL_SECURITY_INFORMATION */
 
874
 
 
875
        if ( (r->in.security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION )
 
876
                return WERR_INVALID_PARAM;
 
877
 
 
878
        /* lookup the security descriptor and marshall it up for a reply */
 
879
 
 
880
        if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) )
 
881
                return WERR_NOMEM;
 
882
 
 
883
        *r->out.needed = ndr_size_security_descriptor( sec_desc, NULL, 0 );
 
884
 
 
885
        if ( *r->out.needed > r->in.offered) {
 
886
                return WERR_INSUFFICIENT_BUFFER;
 
887
        }
 
888
 
 
889
        status = marshall_sec_desc(p->mem_ctx, sec_desc, &buffer, &len);
 
890
        if (!NT_STATUS_IS_OK(status)) {
 
891
                return ntstatus_to_werror(status);
 
892
        }
 
893
 
 
894
        *r->out.needed = len;
 
895
        r->out.buffer = buffer;
 
896
 
 
897
        return WERR_OK;
 
898
}
 
899
 
 
900
/********************************************************************
 
901
 _svcctl_SetServiceObjectSecurity
 
902
********************************************************************/
 
903
 
 
904
WERROR _svcctl_SetServiceObjectSecurity(pipes_struct *p,
 
905
                                        struct svcctl_SetServiceObjectSecurity *r)
 
906
{
 
907
        SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
 
908
        SEC_DESC *sec_desc = NULL;
 
909
        uint32 required_access;
 
910
        NTSTATUS status;
 
911
 
 
912
        if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM))  )
 
913
                return WERR_BADFID;
 
914
 
 
915
        /* can't set the security de4scriptor on the ServiceControlManager */
 
916
 
 
917
        if ( info->type == SVC_HANDLE_IS_SCM )
 
918
                return WERR_ACCESS_DENIED;
 
919
 
 
920
        /* check the access on the open handle */
 
921
 
 
922
        switch ( r->in.security_flags ) {
 
923
                case DACL_SECURITY_INFORMATION:
 
924
                        required_access = STD_RIGHT_WRITE_DAC_ACCESS;
 
925
                        break;
 
926
 
 
927
                case OWNER_SECURITY_INFORMATION:
 
928
                case GROUP_SECURITY_INFORMATION:
 
929
                        required_access = STD_RIGHT_WRITE_OWNER_ACCESS;
 
930
                        break;
 
931
 
 
932
                case SACL_SECURITY_INFORMATION:
 
933
                        return WERR_INVALID_PARAM;
 
934
                default:
 
935
                        return WERR_INVALID_PARAM;
 
936
        }
 
937
 
 
938
        if ( !(info->access_granted & required_access) )
 
939
                return WERR_ACCESS_DENIED;
 
940
 
 
941
        /* read the security descfriptor */
 
942
 
 
943
        status = unmarshall_sec_desc(p->mem_ctx,
 
944
                                     r->in.buffer,
 
945
                                     r->in.offered,
 
946
                                     &sec_desc);
 
947
        if (!NT_STATUS_IS_OK(status)) {
 
948
                return ntstatus_to_werror(status);
 
949
        }
 
950
 
 
951
        /* store the new SD */
 
952
 
 
953
        if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc,
 
954
                                  p->server_info->ptok) )
 
955
                return WERR_ACCESS_DENIED;
 
956
 
 
957
        return WERR_OK;
 
958
}
 
959
 
 
960
 
 
961
WERROR _svcctl_DeleteService(pipes_struct *p, struct svcctl_DeleteService *r)
 
962
{
 
963
        p->rng_fault_state = True;
 
964
        return WERR_NOT_SUPPORTED;
 
965
}
 
966
 
 
967
WERROR _svcctl_SetServiceStatus(pipes_struct *p, struct svcctl_SetServiceStatus *r)
 
968
{
 
969
        p->rng_fault_state = True;
 
970
        return WERR_NOT_SUPPORTED;
 
971
}
 
972
 
 
973
WERROR _svcctl_NotifyBootConfigStatus(pipes_struct *p, struct svcctl_NotifyBootConfigStatus *r)
 
974
{
 
975
        p->rng_fault_state = True;
 
976
        return WERR_NOT_SUPPORTED;
 
977
}
 
978
 
 
979
WERROR _svcctl_SCSetServiceBitsW(pipes_struct *p, struct svcctl_SCSetServiceBitsW *r)
 
980
{
 
981
        p->rng_fault_state = True;
 
982
        return WERR_NOT_SUPPORTED;
 
983
}
 
984
 
 
985
WERROR _svcctl_ChangeServiceConfigW(pipes_struct *p, struct svcctl_ChangeServiceConfigW *r)
 
986
{
 
987
        p->rng_fault_state = True;
 
988
        return WERR_NOT_SUPPORTED;
 
989
}
 
990
 
 
991
WERROR _svcctl_CreateServiceW(pipes_struct *p, struct svcctl_CreateServiceW *r)
 
992
{
 
993
        p->rng_fault_state = True;
 
994
        return WERR_NOT_SUPPORTED;
 
995
}
 
996
 
 
997
WERROR _svcctl_QueryServiceLockStatusW(pipes_struct *p, struct svcctl_QueryServiceLockStatusW *r)
 
998
{
 
999
        p->rng_fault_state = True;
 
1000
        return WERR_NOT_SUPPORTED;
 
1001
}
 
1002
 
 
1003
WERROR _svcctl_GetServiceKeyNameW(pipes_struct *p, struct svcctl_GetServiceKeyNameW *r)
 
1004
{
 
1005
        p->rng_fault_state = True;
 
1006
        return WERR_NOT_SUPPORTED;
 
1007
}
 
1008
 
 
1009
WERROR _svcctl_SCSetServiceBitsA(pipes_struct *p, struct svcctl_SCSetServiceBitsA *r)
 
1010
{
 
1011
        p->rng_fault_state = True;
 
1012
        return WERR_NOT_SUPPORTED;
 
1013
}
 
1014
 
 
1015
WERROR _svcctl_ChangeServiceConfigA(pipes_struct *p, struct svcctl_ChangeServiceConfigA *r)
 
1016
{
 
1017
        p->rng_fault_state = True;
 
1018
        return WERR_NOT_SUPPORTED;
 
1019
}
 
1020
 
 
1021
WERROR _svcctl_CreateServiceA(pipes_struct *p, struct svcctl_CreateServiceA *r)
 
1022
{
 
1023
        p->rng_fault_state = True;
 
1024
        return WERR_NOT_SUPPORTED;
 
1025
}
 
1026
 
 
1027
WERROR _svcctl_EnumDependentServicesA(pipes_struct *p, struct svcctl_EnumDependentServicesA *r)
 
1028
{
 
1029
        p->rng_fault_state = True;
 
1030
        return WERR_NOT_SUPPORTED;
 
1031
}
 
1032
 
 
1033
WERROR _svcctl_EnumServicesStatusA(pipes_struct *p, struct svcctl_EnumServicesStatusA *r)
 
1034
{
 
1035
        p->rng_fault_state = True;
 
1036
        return WERR_NOT_SUPPORTED;
 
1037
}
 
1038
 
 
1039
WERROR _svcctl_OpenSCManagerA(pipes_struct *p, struct svcctl_OpenSCManagerA *r)
 
1040
{
 
1041
        p->rng_fault_state = True;
 
1042
        return WERR_NOT_SUPPORTED;
 
1043
}
 
1044
 
 
1045
WERROR _svcctl_OpenServiceA(pipes_struct *p, struct svcctl_OpenServiceA *r)
 
1046
{
 
1047
        p->rng_fault_state = True;
 
1048
        return WERR_NOT_SUPPORTED;
 
1049
}
 
1050
 
 
1051
WERROR _svcctl_QueryServiceConfigA(pipes_struct *p, struct svcctl_QueryServiceConfigA *r)
 
1052
{
 
1053
        p->rng_fault_state = True;
 
1054
        return WERR_NOT_SUPPORTED;
 
1055
}
 
1056
 
 
1057
WERROR _svcctl_QueryServiceLockStatusA(pipes_struct *p, struct svcctl_QueryServiceLockStatusA *r)
 
1058
{
 
1059
        p->rng_fault_state = True;
 
1060
        return WERR_NOT_SUPPORTED;
 
1061
}
 
1062
 
 
1063
WERROR _svcctl_StartServiceA(pipes_struct *p, struct svcctl_StartServiceA *r)
 
1064
{
 
1065
        p->rng_fault_state = True;
 
1066
        return WERR_NOT_SUPPORTED;
 
1067
}
 
1068
 
 
1069
WERROR _svcctl_GetServiceDisplayNameA(pipes_struct *p, struct svcctl_GetServiceDisplayNameA *r)
 
1070
{
 
1071
        p->rng_fault_state = True;
 
1072
        return WERR_NOT_SUPPORTED;
 
1073
}
 
1074
 
 
1075
WERROR _svcctl_GetServiceKeyNameA(pipes_struct *p, struct svcctl_GetServiceKeyNameA *r)
 
1076
{
 
1077
        p->rng_fault_state = True;
 
1078
        return WERR_NOT_SUPPORTED;
 
1079
}
 
1080
 
 
1081
WERROR _svcctl_GetCurrentGroupeStateW(pipes_struct *p, struct svcctl_GetCurrentGroupeStateW *r)
 
1082
{
 
1083
        p->rng_fault_state = True;
 
1084
        return WERR_NOT_SUPPORTED;
 
1085
}
 
1086
 
 
1087
WERROR _svcctl_EnumServiceGroupW(pipes_struct *p, struct svcctl_EnumServiceGroupW *r)
 
1088
{
 
1089
        p->rng_fault_state = True;
 
1090
        return WERR_NOT_SUPPORTED;
 
1091
}
 
1092
 
 
1093
WERROR _svcctl_ChangeServiceConfig2A(pipes_struct *p, struct svcctl_ChangeServiceConfig2A *r)
 
1094
{
 
1095
        p->rng_fault_state = True;
 
1096
        return WERR_NOT_SUPPORTED;
 
1097
}
 
1098
 
 
1099
WERROR _svcctl_ChangeServiceConfig2W(pipes_struct *p, struct svcctl_ChangeServiceConfig2W *r)
 
1100
{
 
1101
        p->rng_fault_state = True;
 
1102
        return WERR_NOT_SUPPORTED;
 
1103
}
 
1104
 
 
1105
WERROR _svcctl_QueryServiceConfig2A(pipes_struct *p, struct svcctl_QueryServiceConfig2A *r)
 
1106
{
 
1107
        p->rng_fault_state = True;
 
1108
        return WERR_NOT_SUPPORTED;
 
1109
}
 
1110
 
 
1111
WERROR _EnumServicesStatusExA(pipes_struct *p, struct EnumServicesStatusExA *r)
 
1112
{
 
1113
        p->rng_fault_state = True;
 
1114
        return WERR_NOT_SUPPORTED;
 
1115
}
 
1116
 
 
1117
WERROR _EnumServicesStatusExW(pipes_struct *p, struct EnumServicesStatusExW *r)
 
1118
{
 
1119
        p->rng_fault_state = True;
 
1120
        return WERR_NOT_SUPPORTED;
 
1121
}
 
1122
 
 
1123
WERROR _svcctl_SCSendTSMessage(pipes_struct *p, struct svcctl_SCSendTSMessage *r)
 
1124
{
 
1125
        p->rng_fault_state = True;
 
1126
        return WERR_NOT_SUPPORTED;
 
1127
}
 
1128