librpc: fix IDL for svcctl_ChangeServiceConfigW
[bbaumbach/samba-autobuild/.git] / source4 / torture / rpc / svcctl.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for svcctl rpc operations
4
5    Copyright (C) Jelmer Vernooij 2004
6    Copyright (C) Guenther Deschner 2008,2009,2020
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "librpc/gen_ndr/ndr_svcctl_c.h"
24 #include "librpc/gen_ndr/ndr_svcctl.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "torture/rpc/torture_rpc.h"
27 #include "param/param.h"
28
29 #define TORTURE_DEFAULT_SERVICE "Spooler"
30
31 static bool test_OpenSCManager(struct dcerpc_binding_handle *b,
32                                struct torture_context *tctx,
33                                struct policy_handle *h)
34 {
35         struct svcctl_OpenSCManagerW r;
36
37         r.in.MachineName = NULL;
38         r.in.DatabaseName = NULL;
39         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
40         r.out.handle = h;
41
42         torture_assert_ntstatus_ok(tctx,
43                                    dcerpc_svcctl_OpenSCManagerW_r(b, tctx, &r),
44                                    "OpenSCManager failed!");
45
46         return true;
47 }
48
49 static bool test_CloseServiceHandle(struct dcerpc_binding_handle *b,
50                                     struct torture_context *tctx,
51                                     struct policy_handle *h)
52 {
53         struct svcctl_CloseServiceHandle r;
54
55         r.in.handle = h;
56         r.out.handle = h;
57         torture_assert_ntstatus_ok(tctx,
58                                    dcerpc_svcctl_CloseServiceHandle_r(b, tctx, &r),
59                                    "CloseServiceHandle failed");
60
61         return true;
62 }
63
64 static bool test_OpenService(struct dcerpc_binding_handle *b,
65                              struct torture_context *tctx,
66                              struct policy_handle *h,
67                              const char *name,
68                              struct policy_handle *s)
69 {
70         struct svcctl_OpenServiceW r;
71
72         r.in.scmanager_handle = h;
73         r.in.ServiceName = name;
74         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
75         r.out.handle = s;
76
77         torture_assert_ntstatus_ok(tctx,
78                                    dcerpc_svcctl_OpenServiceW_r(b, tctx, &r),
79                                    "OpenServiceW failed!");
80         torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
81
82         return true;
83
84 }
85
86 static bool test_QueryServiceStatus(struct torture_context *tctx,
87                                     struct dcerpc_pipe *p)
88 {
89         struct svcctl_QueryServiceStatus r;
90         struct policy_handle h, s;
91         struct SERVICE_STATUS service_status;
92         NTSTATUS status;
93         struct dcerpc_binding_handle *b = p->binding_handle;
94
95         if (!test_OpenSCManager(b, tctx, &h))
96                 return false;
97
98         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
99                 return false;
100
101         r.in.handle = &s;
102         r.out.service_status = &service_status;
103
104         status = dcerpc_svcctl_QueryServiceStatus_r(b, tctx, &r);
105         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatus failed!");
106         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatus failed!");
107
108         if (!test_CloseServiceHandle(b, tctx, &s))
109                 return false;
110
111         if (!test_CloseServiceHandle(b, tctx, &h))
112                 return false;
113
114         return true;
115 }
116
117 static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
118 {
119         struct svcctl_QueryServiceStatusEx r;
120         struct policy_handle h, s;
121         NTSTATUS status;
122         struct dcerpc_binding_handle *b = p->binding_handle;
123
124         uint32_t info_level = SVC_STATUS_PROCESS_INFO;
125         uint8_t *buffer;
126         uint32_t offered = 0;
127         uint32_t needed = 0;
128
129         if (!test_OpenSCManager(b, tctx, &h))
130                 return false;
131
132         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
133                 return false;
134
135         buffer = talloc(tctx, uint8_t);
136
137         r.in.handle = &s;
138         r.in.info_level = info_level;
139         r.in.offered = offered;
140         r.out.buffer = buffer;
141         r.out.needed = &needed;
142
143         status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
144         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
145
146         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
147                 r.in.offered = needed;
148                 buffer = talloc_array(tctx, uint8_t, needed);
149                 r.out.buffer = buffer;
150
151                 status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
152                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
153                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatusEx failed!");
154         }
155
156         if (!test_CloseServiceHandle(b, tctx, &s))
157                 return false;
158
159         if (!test_CloseServiceHandle(b, tctx, &h))
160                 return false;
161
162         return true;
163 }
164
165 static bool test_QueryServiceConfigW(struct torture_context *tctx,
166                                      struct dcerpc_pipe *p)
167 {
168         struct svcctl_QueryServiceConfigW r;
169         struct QUERY_SERVICE_CONFIG query;
170         struct policy_handle h, s;
171         NTSTATUS status;
172         struct dcerpc_binding_handle *b = p->binding_handle;
173
174         uint32_t offered = 0;
175         uint32_t needed = 0;
176
177         if (!test_OpenSCManager(b, tctx, &h))
178                 return false;
179
180         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
181                 return false;
182
183         r.in.handle = &s;
184         r.in.offered = offered;
185         r.out.query = &query;
186         r.out.needed = &needed;
187
188         status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
189         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
190
191         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
192                 r.in.offered = needed;
193                 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
194                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
195         }
196
197         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigW failed!");
198
199         if (!test_CloseServiceHandle(b, tctx, &s))
200                 return false;
201
202         if (!test_CloseServiceHandle(b, tctx, &h))
203                 return false;
204
205         return true;
206 }
207
208 static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
209 {
210         struct svcctl_QueryServiceConfig2W r;
211         struct policy_handle h, s;
212         NTSTATUS status;
213         struct dcerpc_binding_handle *b = p->binding_handle;
214
215         uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
216         uint8_t *buffer;
217         uint32_t offered = 0;
218         uint32_t needed = 0;
219
220         if (!test_OpenSCManager(b, tctx, &h))
221                 return false;
222
223         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
224                 return false;
225
226         buffer = talloc(tctx, uint8_t);
227
228         r.in.handle = &s;
229         r.in.info_level = info_level;
230         r.in.offered = offered;
231         r.out.buffer = buffer;
232         r.out.needed = &needed;
233
234         status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
235         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
236
237         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
238                 r.in.offered = needed;
239                 buffer = talloc_array(tctx, uint8_t, needed);
240                 r.out.buffer = buffer;
241
242                 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
243                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
244                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
245         }
246
247         r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
248         r.in.offered = offered;
249         r.out.buffer = buffer;
250         r.out.needed = &needed;
251
252         status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
253         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
254
255         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
256                 r.in.offered = needed;
257                 buffer = talloc_array(tctx, uint8_t, needed);
258                 r.out.buffer = buffer;
259
260                 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
261                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
262                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
263         }
264
265         if (!test_CloseServiceHandle(b, tctx, &s))
266                 return false;
267
268         if (!test_CloseServiceHandle(b, tctx, &h))
269                 return false;
270
271         return true;
272 }
273
274 static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
275                                             struct dcerpc_pipe *p)
276 {
277         struct svcctl_QueryServiceObjectSecurity r;
278         struct policy_handle h, s;
279         struct dcerpc_binding_handle *b = p->binding_handle;
280
281         uint8_t *buffer = NULL;
282         uint32_t needed;
283
284         enum ndr_err_code ndr_err;
285         struct security_descriptor sd;
286         DATA_BLOB blob;
287
288         if (!test_OpenSCManager(b, tctx, &h))
289                 return false;
290
291         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
292                 return false;
293
294         r.in.handle = &s;
295         r.in.security_flags = 0;
296         r.in.offered = 0;
297         r.out.buffer = NULL;
298         r.out.needed = &needed;
299
300         torture_assert_ntstatus_ok(tctx,
301                 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
302                 "QueryServiceObjectSecurity failed!");
303         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
304                 "QueryServiceObjectSecurity failed!");
305
306         r.in.security_flags = SECINFO_DACL;
307
308         torture_assert_ntstatus_ok(tctx,
309                 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
310                 "QueryServiceObjectSecurity failed!");
311
312         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
313                 r.in.offered = needed;
314                 buffer = talloc_array(tctx, uint8_t, needed);
315                 r.out.buffer = buffer;
316                 torture_assert_ntstatus_ok(tctx,
317                         dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
318                         "QueryServiceObjectSecurity failed!");
319         }
320
321         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
322
323         blob = data_blob_const(buffer, needed);
324
325         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,
326                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
327         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
328                 return false;
329         }
330
331         if (DEBUGLEVEL >= 1) {
332                 NDR_PRINT_DEBUG(security_descriptor, &sd);
333         }
334
335         if (!test_CloseServiceHandle(b, tctx, &s))
336                 return false;
337
338         if (!test_CloseServiceHandle(b, tctx, &h))
339                 return false;
340
341         return true;
342 }
343
344 static bool test_SetServiceObjectSecurity(struct torture_context *tctx,
345                                           struct dcerpc_pipe *p)
346 {
347         struct svcctl_QueryServiceObjectSecurity q;
348         struct svcctl_SetServiceObjectSecurity r;
349         struct policy_handle h, s;
350         struct dcerpc_binding_handle *b = p->binding_handle;
351
352         uint8_t *buffer;
353         uint32_t needed;
354
355         if (!test_OpenSCManager(b, tctx, &h))
356                 return false;
357
358         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
359                 return false;
360
361         q.in.handle = &s;
362         q.in.security_flags = SECINFO_DACL;
363         q.in.offered = 0;
364         q.out.buffer = NULL;
365         q.out.needed = &needed;
366
367         torture_assert_ntstatus_ok(tctx,
368                 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
369                 "QueryServiceObjectSecurity failed!");
370
371         if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
372                 q.in.offered = needed;
373                 buffer = talloc_array(tctx, uint8_t, needed);
374                 q.out.buffer = buffer;
375                 torture_assert_ntstatus_ok(tctx,
376                         dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
377                         "QueryServiceObjectSecurity failed!");
378         }
379
380         torture_assert_werr_ok(tctx, q.out.result,
381                 "QueryServiceObjectSecurity failed!");
382
383         r.in.handle = &s;
384         r.in.security_flags = SECINFO_DACL;
385         r.in.buffer = q.out.buffer;
386         r.in.offered = *q.out.needed;
387
388         torture_assert_ntstatus_ok(tctx,
389                 dcerpc_svcctl_SetServiceObjectSecurity_r(b, tctx, &r),
390                 "SetServiceObjectSecurity failed!");
391         torture_assert_werr_ok(tctx, r.out.result,
392                 "SetServiceObjectSecurity failed!");
393
394         if (!test_CloseServiceHandle(b, tctx, &s))
395                 return false;
396
397         if (!test_CloseServiceHandle(b, tctx, &h))
398                 return false;
399
400         return true;
401 }
402
403 static bool test_StartServiceW(struct torture_context *tctx,
404                                struct dcerpc_pipe *p)
405 {
406         struct svcctl_StartServiceW r;
407         struct policy_handle h, s;
408         struct dcerpc_binding_handle *b = p->binding_handle;
409
410         if (!test_OpenSCManager(b, tctx, &h))
411                 return false;
412
413         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
414                 return false;
415
416         r.in.handle = &s;
417         r.in.NumArgs = 0;
418         r.in.Arguments = NULL;
419
420         torture_assert_ntstatus_ok(tctx,
421                 dcerpc_svcctl_StartServiceW_r(b, tctx, &r),
422                 "StartServiceW failed!");
423         torture_assert_werr_equal(tctx, r.out.result,
424                 WERR_SERVICE_ALREADY_RUNNING,
425                 "StartServiceW failed!");
426
427         if (!test_CloseServiceHandle(b, tctx, &s))
428                 return false;
429
430         if (!test_CloseServiceHandle(b, tctx, &h))
431                 return false;
432
433         return true;
434 }
435
436 static bool test_ControlService(struct torture_context *tctx,
437                                 struct dcerpc_pipe *p)
438 {
439         struct svcctl_ControlService r;
440         struct policy_handle h, s;
441         struct SERVICE_STATUS service_status;
442         struct dcerpc_binding_handle *b = p->binding_handle;
443
444         if (!test_OpenSCManager(b, tctx, &h))
445                 return false;
446
447         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
448                 return false;
449
450         r.in.handle = &s;
451         r.in.control = 0;
452         r.out.service_status = &service_status;
453
454         torture_assert_ntstatus_ok(tctx,
455                 dcerpc_svcctl_ControlService_r(b, tctx, &r),
456                 "ControlService failed!");
457         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
458                 "ControlService failed!");
459
460         if (!test_CloseServiceHandle(b, tctx, &s))
461                 return false;
462
463         if (!test_CloseServiceHandle(b, tctx, &h))
464                 return false;
465
466         return true;
467 }
468
469 static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
470 {
471         struct svcctl_EnumServicesStatusW r;
472         struct policy_handle h;
473         int i;
474         NTSTATUS status;
475         uint32_t resume_handle = 0;
476         struct ENUM_SERVICE_STATUSW *service = NULL;
477         uint32_t needed = 0;
478         uint32_t services_returned = 0;
479         struct dcerpc_binding_handle *b = p->binding_handle;
480
481         if (!test_OpenSCManager(b, tctx, &h))
482                 return false;
483
484         r.in.handle = &h;
485         r.in.type = SERVICE_TYPE_WIN32;
486         r.in.state = SERVICE_STATE_ALL;
487         r.in.offered = 0;
488         r.in.resume_handle = &resume_handle;
489         r.out.service = NULL;
490         r.out.resume_handle = &resume_handle;
491         r.out.services_returned = &services_returned;
492         r.out.needed = &needed;
493
494         status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
495
496         torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
497
498         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
499                 r.in.offered = needed;
500                 r.out.service = talloc_array(tctx, uint8_t, needed);
501
502                 status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
503
504                 torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
505                 torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
506         }
507
508         if (services_returned > 0) {
509
510                 enum ndr_err_code ndr_err;
511                 DATA_BLOB blob;
512                 struct ndr_pull *ndr;
513
514                 blob.length = r.in.offered;
515                 blob.data = talloc_steal(tctx, r.out.service);
516
517                 ndr = ndr_pull_init_blob(&blob, tctx);
518
519                 service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
520                 if (!service) {
521                         return false;
522                 }
523
524                 ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
525                                 ndr, services_returned, service);
526                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
527                         return false;
528                 }
529         }
530
531         for(i = 0; i < services_returned; i++) {
532
533                 torture_assert(tctx, service[i].service_name,
534                         "Service without name returned!");
535
536                 printf("%-20s   \"%s\", Type: %d, State: %d\n",
537                         service[i].service_name, service[i].display_name,
538                         service[i].status.type, service[i].status.state);
539         }
540
541         if (!test_CloseServiceHandle(b, tctx, &h))
542                 return false;
543
544         return true;
545 }
546
547 static bool test_EnumDependentServicesW(struct torture_context *tctx,
548                                         struct dcerpc_pipe *p)
549 {
550         struct svcctl_EnumDependentServicesW r;
551         struct policy_handle h, s;
552         uint32_t needed;
553         uint32_t services_returned;
554         uint32_t i;
555         uint32_t states[] = { SERVICE_STATE_ACTIVE,
556                               SERVICE_STATE_INACTIVE,
557                               SERVICE_STATE_ALL };
558         struct dcerpc_binding_handle *b = p->binding_handle;
559
560         if (!test_OpenSCManager(b, tctx, &h))
561                 return false;
562
563         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
564                 return false;
565
566         r.in.service = &s;
567         r.in.offered = 0;
568         r.in.state = 0;
569         r.out.service_status = NULL;
570         r.out.services_returned = &services_returned;
571         r.out.needed = &needed;
572
573         torture_assert_ntstatus_ok(tctx,
574                 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
575                 "EnumDependentServicesW failed!");
576
577         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
578                 "EnumDependentServicesW failed!");
579
580         for (i=0; i<ARRAY_SIZE(states); i++) {
581
582                 r.in.state = states[i];
583
584                 torture_assert_ntstatus_ok(tctx,
585                         dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
586                         "EnumDependentServicesW failed!");
587
588                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
589                         r.in.offered = needed;
590                         r.out.service_status = talloc_array(tctx, uint8_t, needed);
591
592                         torture_assert_ntstatus_ok(tctx,
593                                 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
594                                 "EnumDependentServicesW failed!");
595
596                 }
597
598                 torture_assert_werr_ok(tctx, r.out.result,
599                         "EnumDependentServicesW failed");
600         }
601
602         if (!test_CloseServiceHandle(b, tctx, &s))
603                 return false;
604
605         if (!test_CloseServiceHandle(b, tctx, &h))
606                 return false;
607
608         return true;
609 }
610
611 static bool test_SCManager(struct torture_context *tctx,
612                            struct dcerpc_pipe *p)
613 {
614         struct policy_handle h;
615         struct dcerpc_binding_handle *b = p->binding_handle;
616
617         if (!test_OpenSCManager(b, tctx, &h))
618                 return false;
619
620         if (!test_CloseServiceHandle(b, tctx, &h))
621                 return false;
622
623         return true;
624 }
625
626 static bool test_ChangeServiceConfigW(struct torture_context *tctx,
627                                       struct dcerpc_pipe *p)
628 {
629         struct svcctl_ChangeServiceConfigW r;
630         struct svcctl_QueryServiceConfigW q;
631         struct policy_handle h, s;
632         NTSTATUS status;
633         struct dcerpc_binding_handle *b = p->binding_handle;
634         struct QUERY_SERVICE_CONFIG query;
635         bool ok;
636
637         uint32_t offered = 0;
638         uint32_t needed = 0;
639
640         ok = test_OpenSCManager(b, tctx, &h);
641         if (!ok) {
642                 return false;
643         }
644
645         ok = test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s);
646         if (!ok) {
647                 return false;
648         }
649
650         q.in.handle = &s;
651         q.in.offered = offered;
652         q.out.query = &query;
653         q.out.needed = &needed;
654
655         status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
656         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
657
658         if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
659                 q.in.offered = needed;
660                 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
661                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
662         }
663         torture_assert_werr_ok(tctx, q.out.result, "QueryServiceConfigW failed!");
664
665         r.in.handle = &s;
666         r.in.type               = query.service_type;
667         r.in.start_type         = query.start_type;
668         r.in.error_control      = query.error_control;
669
670         /*
671          * according to MS-SCMR 3.1.4.11 NULL params are supposed to leave the
672          * existing values intact.
673          */
674
675         r.in.binary_path        = NULL;
676         r.in.load_order_group   = NULL;
677         r.in.dependencies       = NULL;
678         r.in.dwDependSize       = 0;
679         r.in.service_start_name = NULL;
680         r.in.password           = NULL;
681         r.in.dwPwSize           = 0;
682         r.in.display_name       = NULL;
683         r.in.tag_id             = NULL;
684         r.out.tag_id            = NULL;
685
686         status = dcerpc_svcctl_ChangeServiceConfigW_r(b, tctx, &r);
687         torture_assert_ntstatus_ok(tctx, status, "ChangeServiceConfigW failed!");
688         torture_assert_werr_ok(tctx, r.out.result, "ChangeServiceConfigW failed!");
689
690         ok = test_CloseServiceHandle(b, tctx, &s);
691         if (!ok) {
692                 return false;
693         }
694
695         ok = test_CloseServiceHandle(b, tctx, &h);
696         if (!ok) {
697                 return false;
698         }
699
700         return true;
701 }
702
703 struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
704 {
705         struct torture_suite *suite = torture_suite_create(mem_ctx, "svcctl");
706         struct torture_rpc_tcase *tcase;
707
708         tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
709
710         torture_rpc_tcase_add_test(tcase, "SCManager",
711                                    test_SCManager);
712         torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
713                                    test_EnumServicesStatus);
714         torture_rpc_tcase_add_test(tcase, "EnumDependentServicesW",
715                                    test_EnumDependentServicesW);
716         torture_rpc_tcase_add_test(tcase, "QueryServiceStatus",
717                                    test_QueryServiceStatus);
718         torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
719                                    test_QueryServiceStatusEx);
720         torture_rpc_tcase_add_test(tcase, "QueryServiceConfigW",
721                                    test_QueryServiceConfigW);
722         torture_rpc_tcase_add_test(tcase, "QueryServiceConfig2W",
723                                    test_QueryServiceConfig2W);
724         torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
725                                    test_QueryServiceObjectSecurity);
726         torture_rpc_tcase_add_test(tcase, "SetServiceObjectSecurity",
727                                    test_SetServiceObjectSecurity);
728         torture_rpc_tcase_add_test(tcase, "StartServiceW",
729                                    test_StartServiceW);
730         torture_rpc_tcase_add_test(tcase, "ControlService",
731                                    test_ControlService);
732         torture_rpc_tcase_add_test(tcase, "ChangeServiceConfigW",
733                                    test_ChangeServiceConfigW);
734
735         return suite;
736 }