added a tooltip to explain the behaviour of the syntax check in the filter string
[obnox/wireshark/wip.git] / packet-dcerpc-svcctl.c
1 /* packet-dcerpc-svcctl.c
2  * Routines for SMB \PIPE\svcctl packet disassembly
3  * Copyright 2003, Tim Potter <tpot@samba.org>
4  * Copyright 2003, Ronnie Sahlberg,  added function dissectors
5  *
6  * $Id: packet-dcerpc-svcctl.c,v 1.14 2004/01/19 20:10:36 jmayer Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include "packet-dcerpc.h"
34 #include "packet-dcerpc-svcctl.h"
35 #include "packet-dcerpc-nt.h"
36 #include "smb.h"
37 #include "packet-smb-common.h"
38
39 static int proto_dcerpc_svcctl = -1;
40 static int hf_svcctl_opnum = -1;
41 static int hf_svcctl_machinename = -1;
42 static int hf_svcctl_database = -1;
43 static int hf_svcctl_access_mask = -1;
44 static int hf_svcctl_scm_rights_connect = -1;
45 static int hf_svcctl_scm_rights_create_service = -1;
46 static int hf_svcctl_scm_rights_enumerate_service = -1;
47 static int hf_svcctl_scm_rights_lock = -1;
48 static int hf_svcctl_scm_rights_query_lock_status = -1;
49 static int hf_svcctl_scm_rights_modify_boot_config = -1;
50 static int hf_svcctl_hnd = -1;
51 static int hf_svcctl_lock = -1;
52 static int hf_svcctl_rc = -1;
53 static int hf_svcctl_size = -1;
54 static int hf_svcctl_required_size = -1;
55 static int hf_svcctl_is_locked = -1;
56 static int hf_svcctl_lock_duration = -1;
57 static int hf_svcctl_lock_owner = -1;
58 static int hf_svcctl_service_type = -1;
59 static int hf_svcctl_service_state = -1;
60 static int hf_svcctl_resume = -1;
61
62 static gint ett_dcerpc_svcctl = -1;
63
64 static e_uuid_t uuid_dcerpc_svcctl = {
65         0x367abb81, 0x9844, 0x35f1,
66         { 0xad, 0x32, 0x98, 0xf0, 0x38, 0x00, 0x10, 0x03 }
67 };
68
69 static guint16 ver_dcerpc_svcctl = 2;
70
71
72
73 static int
74 svcctl_dissect_pointer_long(tvbuff_t *tvb, int offset,
75                              packet_info *pinfo, proto_tree *tree,
76                              guint8 *drep)
77 {
78         dcerpc_info *di;
79
80         di=pinfo->private_data;
81         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
82                                      di->hf_index, NULL);
83         return offset;
84 }
85
86 static void
87 svcctl_scm_specific_rights(tvbuff_t *tvb, gint offset, proto_tree *tree,
88                     guint32 access)
89 {
90         proto_tree_add_boolean(tree, hf_svcctl_scm_rights_modify_boot_config, tvb, offset, 4, access);
91         proto_tree_add_boolean(tree, hf_svcctl_scm_rights_query_lock_status, tvb, offset, 4, access);
92         proto_tree_add_boolean(tree, hf_svcctl_scm_rights_lock, tvb, offset, 4, access);
93         proto_tree_add_boolean(tree, hf_svcctl_scm_rights_enumerate_service, tvb, offset, 4, access);
94         proto_tree_add_boolean(tree, hf_svcctl_scm_rights_create_service, tvb, offset, 4, access);
95         proto_tree_add_boolean(tree, hf_svcctl_scm_rights_connect, tvb, offset, 4, access);
96 }
97
98 struct access_mask_info svcctl_scm_access_mask_info = {
99         "SVCCTL",
100         svcctl_scm_specific_rights,
101         NULL,                   /* Generic mapping table */
102         NULL                    /* Standard mapping table */
103 };
104
105 /*
106  * IDL long OpenSCManager(
107  * IDL      [in] [string] [unique] char *MachineName,
108  * IDL      [in] [string] [unique] char *DatabaseName,
109  * IDL      [in] long access_mask,
110  * IDL      [out] SC_HANDLE handle,
111  * IDL );
112  */
113 static int
114 svcctl_dissect_OpenSCManager_rqst(tvbuff_t *tvb, int offset, 
115                                   packet_info *pinfo, proto_tree *tree,
116                                   guint8 *drep)
117 {
118         /* MachineName */
119         offset = dissect_ndr_pointer_cb(
120                 tvb, offset, pinfo, tree, drep,
121                 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
122                 "MachineName", hf_svcctl_machinename, cb_str_postprocess,
123                 GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
124
125         /* DatabaseName */
126         offset = dissect_ndr_pointer_cb(
127                 tvb, offset, pinfo, tree, drep,
128                 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
129                 "Database", hf_svcctl_database, cb_str_postprocess,
130                 GINT_TO_POINTER(CB_STR_COL_INFO | 1));
131
132         /* access mask */
133         offset = dissect_nt_access_mask(
134                 tvb, offset, pinfo, tree, drep, hf_svcctl_access_mask,
135                 &svcctl_scm_access_mask_info);
136
137         return offset;
138 }
139
140 static int
141 svcctl_dissect_OpenSCManager_reply(tvbuff_t *tvb, int offset, 
142                                   packet_info *pinfo, proto_tree *tree,
143                                   guint8 *drep)
144 {
145         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
146         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
147         e_ctx_hnd policy_hnd;
148         proto_item *hnd_item;
149         guint32 status;
150
151         /* Parse packet */
152
153         offset = dissect_nt_policy_hnd(
154                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
155                 &hnd_item, TRUE, FALSE);
156
157         offset = dissect_doserror(
158                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, &status);
159
160         if (status == 0) {
161
162                 /* Associate the returned svcctl with a name */
163
164                 if (dcv->private_data) {
165                         char *pol_name;
166
167                         pol_name = g_strdup_printf(
168                                 "OpenSCManager(%s)", 
169                                 (char *)dcv->private_data);
170
171                         dcerpc_smb_store_pol_name(&policy_hnd, pinfo, pol_name);
172
173                         g_free(pol_name);
174                         g_free(dcv->private_data);
175                         dcv->private_data = NULL;
176                 }
177
178                 /*
179                  * If we have a name for the handle, attach it to the item.
180                  *
181                  * XXX - we can't just do that above, as this may be called
182                  * twice (see "dissect_pipe_dcerpc()", which calls the
183                  * DCE RPC dissector twice), and in the first call we're
184                  * not building a protocol tree (so we don't have an item
185                  * to which to attach it) and in the second call
186                  * "dcv->private_data" is NULL so we don't construct a
187                  * name.
188                  */
189
190                 if (hnd_item != NULL) {
191                         char *name;
192
193                         if (dcerpc_smb_fetch_pol(&policy_hnd, &name, NULL, NULL,
194                             pinfo->fd->num) && name != NULL)
195                                 proto_item_append_text(hnd_item, ": %s", name);
196                 }
197         }
198
199         return offset;
200 }
201
202
203
204 /*
205  * IDL BOOL CloseServiceHandle(
206  * IDL      [in][out] SC_HANDLE handle
207  * IDL );
208  */
209 static int
210 svcctl_dissect_CloseServiceHandle_rqst(tvbuff_t *tvb, int offset, 
211                                   packet_info *pinfo, proto_tree *tree,
212                                   guint8 *drep)
213 {
214         e_ctx_hnd policy_hnd;
215         char *pol_name;
216
217         /* Parse packet */
218
219         offset = dissect_nt_policy_hnd(
220                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
221                 NULL, FALSE, TRUE);
222
223         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL,
224                              pinfo->fd->num);
225
226         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
227                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
228                                 pol_name);
229
230         return offset;
231 }
232
233 static int
234 svcctl_dissect_CloseServiceHandle_reply(tvbuff_t *tvb, int offset, 
235                                   packet_info *pinfo, proto_tree *tree,
236                                   guint8 *drep)
237 {
238         offset = dissect_nt_policy_hnd(
239                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
240                 NULL, FALSE, TRUE);
241
242         offset = dissect_doserror(
243                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
244
245         return offset;
246 }
247
248
249
250 /*
251  * IDL long LockServiceDatabase(
252  * IDL      [in] SC_HANDLE dbhandle,
253  * IDL      [out] SC_HANDLE lock,
254  * IDL );
255  */
256 static int
257 svcctl_dissect_LockServiceDatabase_rqst(tvbuff_t *tvb, int offset, 
258                                   packet_info *pinfo, proto_tree *tree,
259                                   guint8 *drep)
260 {
261         /* XXX - why is the "is a close" argument TRUE? */
262         offset = dissect_nt_policy_hnd(
263                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
264                 NULL, FALSE, TRUE);
265
266         return offset;
267 }
268 static int
269 svcctl_dissect_LockServiceDatabase_reply(tvbuff_t *tvb, int offset, 
270                                   packet_info *pinfo, proto_tree *tree,
271                                   guint8 *drep)
272 {
273         /* XXX - why is the "is an open" argument TRUE? */
274         offset = dissect_nt_policy_hnd(
275                 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
276                 NULL, TRUE, FALSE);
277
278         offset = dissect_doserror(
279                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
280
281         return offset;
282 }
283
284
285
286 /*
287  * IDL long UnlockServiceDatabase(
288  * IDL      [in][out] SC_HANDLE lock,
289  * IDL );
290  */
291 static int
292 svcctl_dissect_UnlockServiceDatabase_rqst(tvbuff_t *tvb, int offset, 
293                                   packet_info *pinfo, proto_tree *tree,
294                                   guint8 *drep)
295 {
296         /* XXX - why is the "is a close" argument TRUE? */
297         offset = dissect_nt_policy_hnd(
298                 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
299                 NULL, FALSE, TRUE);
300
301         return offset;
302 }
303 static int
304 svcctl_dissect_UnlockServiceDatabase_reply(tvbuff_t *tvb, int offset, 
305                                   packet_info *pinfo, proto_tree *tree,
306                                   guint8 *drep)
307 {
308         /* XXX - why is the "is an open" argument TRUE? */
309         offset = dissect_nt_policy_hnd(
310                 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
311                 NULL, TRUE, FALSE);
312
313         offset = dissect_doserror(
314                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
315
316         return offset;
317 }
318
319
320 /*
321  * IDL typedef struct {
322  * IDL     long is_locked,
323  * IDL     [unique][string] char *lock_owner,
324  * IDL     long lock_duration,
325  * IDL };
326  */ 
327 static int
328 svcctl_dissect_QUERY_SERVICE_LOCK_STATUS(tvbuff_t *tvb, int offset, 
329                                   packet_info *pinfo, proto_tree *tree,
330                                   guint8 *drep)
331 {
332         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
333                                      hf_svcctl_is_locked, NULL);
334
335         offset = dissect_ndr_pointer(
336                 tvb, offset, pinfo, tree, drep,
337                 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
338                 "Owner", hf_svcctl_lock_owner);
339
340         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
341                                      hf_svcctl_lock_duration, NULL);
342
343         return offset;
344 }
345
346 /*
347  * IDL long QueryServiceLockStatus(
348  * IDL      [in] SC_HANDLE db_handle,
349  * IDL      [in] long buf_size,
350  * IDL      [out][ref] QUERY_SERVICE_LOCK_STATUS *status,
351  * IDL      [out][ref] long *required_buf_size
352  * IDL );
353  */
354 static int
355 svcctl_dissect_QueryServiceLockStatus_rqst(tvbuff_t *tvb, int offset, 
356                                   packet_info *pinfo, proto_tree *tree,
357                                   guint8 *drep)
358 {
359         /* XXX - why is the "is a close" argument TRUE? */
360         offset = dissect_nt_policy_hnd(
361                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
362                 NULL, FALSE, TRUE);
363
364         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
365                                      hf_svcctl_size, NULL);
366
367         return offset;
368 }
369 static int
370 svcctl_dissect_QueryServiceLockStatus_reply(tvbuff_t *tvb, int offset, 
371                                   packet_info *pinfo, proto_tree *tree,
372                                   guint8 *drep)
373 {
374         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
375                 svcctl_dissect_QUERY_SERVICE_LOCK_STATUS, NDR_POINTER_REF,
376                 "LOCK_STATUS", -1);
377
378         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
379                                      hf_svcctl_required_size, NULL);
380
381         offset = dissect_doserror(
382                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
383
384         return offset;
385 }
386
387
388
389 #define SVCCTL_SERVICE_DRIVER   0x0b
390 #define SVCCTL_SERVICE_WIN32    0x30
391 static const value_string svcctl_service_type_vals[] = {
392         { SVCCTL_SERVICE_DRIVER,    "SERVICE_DRIVER" },
393         { SVCCTL_SERVICE_WIN32,     "SERVICE_WIN32" },
394         { 0, NULL }
395 };
396
397 #define SVCCTL_SERVICE_ACTIVE       0x01
398 #define SVCCTL_SERVICE_INACTIVE     0x02
399 #define SVCCTL_SERVICE_STATE_ALL    0x03
400 static const value_string svcctl_service_status_vals[] = {
401         { SVCCTL_SERVICE_ACTIVE,    "SERVICE_ACTIVE" },
402         { SVCCTL_SERVICE_INACTIVE,  "SERVICE_INACTIVE" },
403         { SVCCTL_SERVICE_STATE_ALL, "SERVICE_STATE_ALL" },
404         { 0, NULL }
405 };
406
407 /*
408  * IDL long EnumServicesStatus(
409  * IDL      [in] SC_HANDLE db_handle,
410  * IDL      [in] long type,
411  * IDL      [in] long status,
412  * IDL      [in] long buf_size,
413  * IDL      [in][unique] long *resume_handle, 
414  * IDL );
415  */
416 static int
417 svcctl_dissect_EnumServicesStatus_rqst(tvbuff_t *tvb, int offset, 
418                                   packet_info *pinfo, proto_tree *tree,
419                                   guint8 *drep)
420 {
421         /* XXX - why is the "is a close" argument TRUE? */
422         offset = dissect_nt_policy_hnd(
423                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
424                 NULL, FALSE, TRUE);
425
426         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
427                                      hf_svcctl_service_type, NULL);
428
429         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
430                                      hf_svcctl_service_state, NULL);
431
432         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
433                                      hf_svcctl_size, NULL);
434
435         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
436                         svcctl_dissect_pointer_long, NDR_POINTER_UNIQUE,
437                         "Resume Handle", hf_svcctl_resume);
438
439         return offset;
440 }
441
442
443
444
445
446 static dcerpc_sub_dissector dcerpc_svcctl_dissectors[] = {
447         { SVC_CLOSE_SERVICE_HANDLE, "CloseServiceHandle", 
448                 svcctl_dissect_CloseServiceHandle_rqst, 
449                 svcctl_dissect_CloseServiceHandle_reply  },
450         { SVC_CONTROL_SERVICE, "ControlService", NULL, NULL },
451         { SVC_DELETE_SERVICE, "DeleteService", NULL, NULL },
452         { SVC_LOCK_SERVICE_DATABASE, "LockServiceDatabase",
453                 svcctl_dissect_LockServiceDatabase_rqst, 
454                 svcctl_dissect_LockServiceDatabase_reply  },
455         { SVC_QUERY_SERVICE_OBJECT_SECURITY, "QueryServiceObjectSecurity", 
456           NULL, NULL },
457         { SVC_SET_SERVICE_OBJECT_SECURITY, "SetServiceObjectSecurity", 
458           NULL, NULL },
459         { SVC_QUERY_SERVICE_STATUS, "QueryServiceStatus", 
460           NULL, NULL },
461         { SVC_SET_SERVICE_STATUS, "SetServiceStatus", 
462           NULL, NULL },
463         { SVC_UNLOCK_SERVICE_DATABASE, "UnlockServiceDatabase",
464                 svcctl_dissect_UnlockServiceDatabase_rqst, 
465                 svcctl_dissect_UnlockServiceDatabase_reply  },
466         { SVC_NOTIFY_BOOT_CONFIG_STATUS, "NotifyBootConfigStatus", 
467           NULL, NULL },
468         { SVC_SC_SET_SERVICE_BITS_W, "ScSetServiceBitsW",
469           NULL, NULL },
470         { SVC_CHANGE_SERVICE_CONFIG_W, "ChangeServiceConfigW", 
471           NULL, NULL },
472         { SVC_CREATE_SERVICE_W, "CreateServiceW", NULL, NULL },
473         { SVC_ENUM_DEPENDENT_SERVICES_W, "EnumDependentServicesW", 
474           NULL, NULL },
475         { SVC_ENUM_SERVICES_STATUS_W, "EnumServicesStatusW", 
476           NULL, NULL },
477         { SVC_OPEN_SC_MANAGER_W, "OpenSCManagerW", NULL, NULL },
478         { SVC_OPEN_SERVICE_W, "OpenServiceW", NULL, NULL },
479         { SVC_QUERY_SERVICE_CONFIG_W, "QueryServiceConfigW", NULL, NULL },
480         { SVC_QUERY_SERVICE_LOCK_STATUS_W, "QueryServiceLockStatusW", 
481           NULL, NULL },
482         { SVC_START_SERVICE_W, "StartServiceW", NULL, NULL },
483         { SVC_GET_SERVICE_DISPLAY_NAME_W, "GetServiceDisplayNameW", 
484           NULL, NULL },
485         { SVC_GET_SERVICE_KEY_NAME_W, "GetServiceKeyNameW", NULL, NULL },
486         { SVC_SC_SET_SERVICE_BITS_A, "ScSetServiceBitsA", NULL, NULL },
487         { SVC_CHANGE_SERVICE_CONFIG_A, "ChangeServiceConfigA", NULL, NULL },
488         { SVC_CREATE_SERVICE_A, "CreateServiceA", NULL, NULL },
489         { SVC_ENUM_DEPENDENT_SERVICES_A, "EnumDependentServicesA", 
490           NULL, NULL },
491         { SVC_ENUM_SERVICES_STATUS_A, "EnumServicesStatusA",
492                 svcctl_dissect_EnumServicesStatus_rqst, 
493                 NULL },
494         { SVC_OPEN_SC_MANAGER_A, "OpenSCManagerA",
495                 svcctl_dissect_OpenSCManager_rqst,
496                 svcctl_dissect_OpenSCManager_reply },
497         { SVC_OPEN_SERVICE_A, "OpenServiceA", NULL, NULL },
498         { SVC_QUERY_SERVICE_CONFIG_A, "QueryServiceConfigA", NULL, NULL },
499         { SVC_QUERY_SERVICE_LOCK_STATUS_A, "QueryServiceLockStatusA",
500                 svcctl_dissect_QueryServiceLockStatus_rqst,
501                 svcctl_dissect_QueryServiceLockStatus_reply },
502         { SVC_START_SERVICE_A, "StartServiceA", NULL, NULL },
503         { SVC_GET_SERVICE_DISPLAY_NAME_A, "GetServiceDisplayNameA",
504           NULL, NULL },
505         { SVC_GET_SERVICE_KEY_NAME_A, "GetServiceKeyNameA", NULL, NULL },       
506         { SVC_SC_GET_CURRENT_GROUPE_STATE_W, "ScGetCurrentGroupStateW",
507           NULL, NULL },
508         { SVC_ENUM_SERVICE_GROUP_W, "EnumServiceGroupW", 
509           NULL, NULL },
510         { SVC_CHANGE_SERVICE_CONFIG2_A, "ChangeServiceConfig2A", 
511           NULL, NULL },
512         { SVC_CHANGE_SERVICE_CONFIG2_W, "ChangeServiceConfig2W",
513           NULL, NULL },
514         { SVC_QUERY_SERVICE_CONFIG2_A, "QueryServiceConfig2A", 
515           NULL, NULL },
516         { SVC_QUERY_SERVICE_CONFIG2_W, "QueryServiceConfig2W", 
517           NULL, NULL },
518         { SVC_QUERY_SERVICE_STATUS_EX, "QueryServiceStatusEx", 
519           NULL, NULL },
520         { SVC_ENUM_SERVICES_STATUS_EX_A, "EnumServicesStatusExA", 
521           NULL, NULL },
522         { SVC_ENUM_SERVICES_STATUS_EX_W, "EnumServicesStatusExW", 
523           NULL, NULL },
524         { SVC_SC_SEND_TS_MESSAGE, "ScSendTSMessage", 
525           NULL, NULL },
526         {0, NULL, NULL, NULL}
527 };
528
529 void
530 proto_register_dcerpc_svcctl(void)
531 {
532         static hf_register_info hf[] = {
533           { &hf_svcctl_opnum,
534             { "Operation", "svcctl.opnum", FT_UINT16, BASE_DEC,
535               NULL, 0x0, "Operation", HFILL }},
536           { &hf_svcctl_machinename,
537             { "MachineName", "svcctl.machinename", FT_STRING, BASE_NONE,
538               NULL, 0x0, "Name of the host we want to open the database on", HFILL }},
539           { &hf_svcctl_database,
540             { "Database", "svcctl.database", FT_STRING, BASE_NONE,
541               NULL, 0x0, "Name of the database to open", HFILL }},
542           { &hf_svcctl_access_mask,
543             { "Access Mask", "svcctl.access_mask", FT_UINT32, BASE_HEX,
544               NULL, 0x0, "SVCCTL Access Mask", HFILL }},
545           { &hf_svcctl_scm_rights_connect,
546             { "Connect", "svcctl.scm_rights_connect", FT_BOOLEAN, 32,
547               TFS(&flags_set_truth), 0x00000001, "SVCCTL Rights to connect to SCM", HFILL }},
548           { &hf_svcctl_scm_rights_create_service,
549             { "Create Service", "svcctl.scm_rights_create_service", FT_BOOLEAN, 32,
550               TFS(&flags_set_truth), 0x00000002, "SVCCTL Rights to create services", HFILL }},
551           { &hf_svcctl_scm_rights_enumerate_service,
552             { "Enumerate Service", "svcctl.scm_rights_enumerate_service", FT_BOOLEAN, 32,
553               TFS(&flags_set_truth), 0x00000004, "SVCCTL Rights to enumerate services", HFILL }},
554           { &hf_svcctl_scm_rights_lock,
555             { "Lock", "svcctl.scm_rights_lock", FT_BOOLEAN, 32,
556               TFS(&flags_set_truth), 0x00000008, "SVCCTL Rights to lock database", HFILL }},
557           { &hf_svcctl_scm_rights_query_lock_status,
558             { "Query Lock Status", "svcctl.scm_rights_query_lock_status", FT_BOOLEAN, 32,
559               TFS(&flags_set_truth), 0x00000010, "SVCCTL Rights to query database lock status", HFILL }},
560           { &hf_svcctl_scm_rights_modify_boot_config,
561             { "Modify Boot Config", "svcctl.scm_rights_modify_boot_config", FT_BOOLEAN, 32,
562               TFS(&flags_set_truth), 0x00000020, "SVCCTL Rights to modify boot config", HFILL }},
563           { &hf_svcctl_hnd,
564             { "Context Handle", "svcctl.hnd", FT_BYTES, BASE_NONE,
565               NULL, 0x0, "SVCCTL Context handle", HFILL }},
566           { &hf_svcctl_lock,
567             { "Lock", "svcctl.lock", FT_BYTES, BASE_NONE,
568               NULL, 0x0, "SVCCTL Database Lock", HFILL }},
569           { &hf_svcctl_rc,
570             { "Return code", "svcctl.rc", FT_UINT32, BASE_HEX,
571               VALS(DOS_errors), 0x0, "SVCCTL return code", HFILL }},
572           { &hf_svcctl_size,
573             { "Size", "svcctl.size", FT_UINT32, BASE_DEC,
574               NULL, 0x0, "SVCCTL size of buffer", HFILL }},
575           { &hf_svcctl_required_size,
576             { "Required Size", "svcctl.required_size", FT_UINT32, BASE_DEC,
577               NULL, 0x0, "SVCCTL required size of buffer for data to fit", HFILL }},
578           { &hf_svcctl_is_locked,
579             { "IsLocked", "svcctl.is_locked", FT_UINT32, BASE_DEC,
580               NULL, 0x0, "SVCCTL whether the database is locked or not", HFILL }},
581           { &hf_svcctl_lock_duration,
582             { "Duration", "svcctl.lock_duration", FT_UINT32, BASE_DEC,
583               NULL, 0x0, "SVCCTL number of seconds the database has been locked", HFILL }},
584           { &hf_svcctl_lock_owner,
585             { "Owner", "svcctl.lock_owner", FT_STRING, BASE_NONE,
586               NULL, 0x0, "SVCCTL the user that holds the database lock", HFILL }},
587           { &hf_svcctl_service_type,
588             { "Type", "svcctl.service_type", FT_UINT32, BASE_DEC,
589               VALS(svcctl_service_type_vals), 0x0, "SVCCTL type of service", HFILL }},
590
591           { &hf_svcctl_service_state,
592             { "State", "svcctl.service_state", FT_UINT32, BASE_DEC,
593               VALS(svcctl_service_status_vals), 0x0, "SVCCTL service state", HFILL }},
594           { &hf_svcctl_resume,
595             { "Resume Handle", "svcctl.resume", FT_UINT32, BASE_DEC,
596               NULL, 0x0, "SVCCTL resume handle", HFILL }},
597         };
598
599         static gint *ett[] = {
600                 &ett_dcerpc_svcctl,
601         };
602
603         proto_dcerpc_svcctl = proto_register_protocol(
604                 "Microsoft Service Control", "SVCCTL", "svcctl");
605
606         proto_register_field_array(proto_dcerpc_svcctl, hf, array_length(hf));
607         proto_register_subtree_array(ett, array_length(ett));
608 }
609
610 void
611 proto_reg_handoff_dcerpc_svcctl(void)
612 {
613         /* Register protocol as dcerpc */
614
615         dcerpc_init_uuid(proto_dcerpc_svcctl, ett_dcerpc_svcctl,
616                          &uuid_dcerpc_svcctl, ver_dcerpc_svcctl,
617                          dcerpc_svcctl_dissectors, hf_svcctl_opnum);
618 }