s4-smbtorture: fix test for svcctl_EnumServicesStatusW.
[kai/samba.git] / source4 / torture / rpc / svcctl.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for srvsvc rpc operations
4
5    Copyright (C) Jelmer Vernooij 2004
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "librpc/gen_ndr/ndr_svcctl_c.h"
24 #include "torture/rpc/rpc.h"
25
26 static bool test_OpenSCManager(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
27 {
28         struct svcctl_OpenSCManagerW r;
29
30         r.in.MachineName = NULL;
31         r.in.DatabaseName = NULL;
32         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
33         r.out.handle = h;
34
35         torture_assert_ntstatus_ok(tctx,
36                                    dcerpc_svcctl_OpenSCManagerW(p, tctx, &r),
37                                    "OpenSCManager failed!");
38
39         return true;
40 }
41
42 static bool test_CloseServiceHandle(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
43 {
44         struct svcctl_CloseServiceHandle r;
45
46         r.in.handle = h;
47         r.out.handle = h;
48         torture_assert_ntstatus_ok(tctx,
49                                    dcerpc_svcctl_CloseServiceHandle(p, tctx, &r),
50                                    "CloseServiceHandle failed");
51
52         return true;
53 }
54
55 static bool test_OpenService(struct dcerpc_pipe *p, struct torture_context *tctx,
56                              struct policy_handle *h, const char *name, struct policy_handle *s)
57 {
58         struct svcctl_OpenServiceW r;
59
60         r.in.scmanager_handle = h;
61         r.in.ServiceName = name;
62         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
63         r.out.handle = s;
64
65         torture_assert_ntstatus_ok(tctx,
66                                    dcerpc_svcctl_OpenServiceW(p, tctx, &r),
67                                    "OpenServiceW failed!");
68         torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
69
70         return true;
71
72 }
73
74 static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
75 {
76         struct svcctl_QueryServiceStatusEx r;
77         struct policy_handle h, s;
78         NTSTATUS status;
79
80         uint32_t info_level = 0;
81         uint8_t *buffer;
82         uint32_t buf_size = 0;
83         uint32_t bytes_needed = 0;
84
85         if (!test_OpenSCManager(p, tctx, &h))
86                 return false;
87
88         if (!test_OpenService(p, tctx, &h, "Netlogon", &s))
89                 return false;
90
91         buffer = talloc(tctx, uint8_t);
92
93         r.in.handle = &s;
94         r.in.info_level = 0;
95         r.in.buf_size = buf_size;
96         r.out.buffer = buffer;
97         r.out.bytes_needed = &bytes_needed;
98
99         status = dcerpc_svcctl_QueryServiceStatusEx(p, tctx, &r);
100         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
101
102         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
103                 r.in.buf_size = bytes_needed;
104                 buffer = talloc_array(tctx, uint8_t, bytes_needed);
105                 r.out.buffer = buffer;
106
107                 status = dcerpc_svcctl_QueryServiceStatusEx(p, tctx, &r);
108                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
109                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatusEx failed!");
110         }
111
112         if (!test_CloseServiceHandle(p, tctx, &s))
113                 return false;
114
115         if (!test_CloseServiceHandle(p, tctx, &h))
116                 return false;
117
118         return true;
119 }
120
121 static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
122 {
123         struct svcctl_EnumServicesStatusW r;
124         struct policy_handle h;
125         int i;
126         NTSTATUS status;
127         uint32_t resume_handle = 0;
128         struct ENUM_SERVICE_STATUS *service = NULL;
129         uint32_t bytes_needed = 0;
130         uint32_t services_returned = 0;
131
132         if (!test_OpenSCManager(p, tctx, &h))
133                 return false;
134
135         r.in.handle = &h;
136         r.in.type = SERVICE_TYPE_WIN32;
137         r.in.state = SERVICE_STATE_ALL;
138         r.in.buf_size = 0;
139         r.in.resume_handle = &resume_handle;
140         r.out.service = NULL;
141         r.out.resume_handle = &resume_handle;
142         r.out.services_returned = &services_returned;
143         r.out.bytes_needed = &bytes_needed;
144
145         status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);
146
147         torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
148
149         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
150                 r.in.buf_size = bytes_needed;
151                 r.out.service = talloc_array(tctx, uint8_t, bytes_needed);
152
153                 status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);
154
155                 torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
156                 torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
157
158                 service = (struct ENUM_SERVICE_STATUS *)r.out.service;
159         }
160
161         for(i = 0; i < services_returned; i++) {
162                 printf("Type: %d, State: %d\n", service[i].status.type, service[i].status.state);
163         }
164
165         if (!test_CloseServiceHandle(p, tctx, &h))
166                 return false;
167
168         return true;
169 }
170
171 static bool test_SCManager(struct torture_context *tctx,
172                                                    struct dcerpc_pipe *p)
173 {
174         struct policy_handle h;
175
176         if (!test_OpenSCManager(p, tctx, &h))
177                 return false;
178
179         if (!test_CloseServiceHandle(p, tctx, &h))
180                 return false;
181
182         return true;
183 }
184
185 struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
186 {
187         struct torture_suite *suite = torture_suite_create(mem_ctx, "SVCCTL");
188         struct torture_rpc_tcase *tcase;
189
190         tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
191
192         torture_rpc_tcase_add_test(tcase, "SCManager",
193                                    test_SCManager);
194         torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
195                                    test_EnumServicesStatus);
196         torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
197                                    test_QueryServiceStatusEx);
198
199         return suite;
200 }