A quantity dissected as 6 unknown bytes in a logon reply actually
[metze/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.7 2003/04/28 04:44:54 tpot 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                              char *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 };
102
103 /*
104  * IDL long OpenSCManager(
105  * IDL      [in] [string] [unique] char *MachineName,
106  * IDL      [in] [string] [unique] char *DatabaseName,
107  * IDL      [in] long access_mask,
108  * IDL      [out] SC_HANDLE handle,
109  * IDL );
110  */
111 static int
112 svcctl_dissect_OpenSCManager_rqst(tvbuff_t *tvb, int offset, 
113                                   packet_info *pinfo, proto_tree *tree,
114                                   char *drep)
115 {
116         /* MachineName */
117         offset = dissect_ndr_pointer_cb(
118                 tvb, offset, pinfo, tree, drep,
119                 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
120                 "MachineName", hf_svcctl_machinename, cb_str_postprocess,
121                 GINT_TO_POINTER(CB_STR_COL_INFO | CB_STR_SAVE | 1));
122
123         /* DatabaseName */
124         offset = dissect_ndr_pointer_cb(
125                 tvb, offset, pinfo, tree, drep,
126                 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
127                 "Database", hf_svcctl_database, cb_str_postprocess,
128                 GINT_TO_POINTER(CB_STR_COL_INFO | 1));
129
130         /* access mask */
131         offset = dissect_nt_access_mask(
132                 tvb, offset, pinfo, tree, drep, hf_svcctl_access_mask,
133                 &svcctl_scm_access_mask_info);
134
135         return offset;
136 }
137
138 static int
139 svcctl_dissect_OpenSCManager_reply(tvbuff_t *tvb, int offset, 
140                                   packet_info *pinfo, proto_tree *tree,
141                                   char *drep)
142 {
143         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
144         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
145         e_ctx_hnd policy_hnd;
146         guint32 status;
147         int start_offset = offset;
148
149         /* We need the value of the policy handle and status before we
150            can retrieve the policy handle name.  Then we can insert
151            the policy handle with the name in the proto tree. */
152
153         offset = dissect_nt_policy_hnd(
154                 tvb, offset, pinfo, NULL, drep, hf_svcctl_hnd, &policy_hnd,
155                 TRUE, FALSE);
156
157         offset = dissect_ndr_uint32(
158                 tvb, offset, pinfo, NULL, 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, pol_name);
172
173                         g_free(pol_name);
174                         g_free(dcv->private_data);
175                         dcv->private_data = NULL;
176                 }
177         }
178
179         /* Parse packet */
180
181         offset = start_offset;
182
183         offset = dissect_nt_policy_hnd(
184                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
185                 TRUE, FALSE);
186
187         offset = dissect_doserror(
188                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, &status);
189
190         return offset;
191 }
192
193
194
195 /*
196  * IDL BOOL CloseServiceHandle(
197  * IDL      [in][out] SC_HANDLE handle
198  * IDL );
199  */
200 static int
201 svcctl_dissect_CloseServiceHandle_rqst(tvbuff_t *tvb, int offset, 
202                                   packet_info *pinfo, proto_tree *tree,
203                                   char *drep)
204 {
205         e_ctx_hnd policy_hnd;
206         char *pol_name;
207
208         /* Parse packet */
209
210         offset = dissect_nt_policy_hnd(
211                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, &policy_hnd,
212                 FALSE, TRUE);
213
214         dcerpc_smb_fetch_pol(&policy_hnd, &pol_name, NULL, NULL);
215
216         if (check_col(pinfo->cinfo, COL_INFO) && pol_name)
217                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
218                                 pol_name);
219
220         return offset;
221 }
222
223 static int
224 svcctl_dissect_CloseServiceHandle_reply(tvbuff_t *tvb, int offset, 
225                                   packet_info *pinfo, proto_tree *tree,
226                                   char *drep)
227 {
228         offset = dissect_nt_policy_hnd(
229                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
230                 FALSE, TRUE);
231
232         offset = dissect_doserror(
233                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
234
235         return offset;
236 }
237
238
239
240 /*
241  * IDL long LockServiceDatabase(
242  * IDL      [in] SC_HANDLE dbhandle,
243  * IDL      [out] SC_HANDLE lock,
244  * IDL );
245  */
246 static int
247 svcctl_dissect_LockServiceDatabase_rqst(tvbuff_t *tvb, int offset, 
248                                   packet_info *pinfo, proto_tree *tree,
249                                   char *drep)
250 {
251         offset = dissect_nt_policy_hnd(
252                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
253                 FALSE, TRUE);
254
255         return offset;
256 }
257 static int
258 svcctl_dissect_LockServiceDatabase_reply(tvbuff_t *tvb, int offset, 
259                                   packet_info *pinfo, proto_tree *tree,
260                                   char *drep)
261 {
262         offset = dissect_nt_policy_hnd(
263                 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
264                 TRUE, FALSE);
265
266         offset = dissect_doserror(
267                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
268
269         return offset;
270 }
271
272
273
274 /*
275  * IDL long UnlockServiceDatabase(
276  * IDL      [in][out] SC_HANDLE lock,
277  * IDL );
278  */
279 static int
280 svcctl_dissect_UnlockServiceDatabase_rqst(tvbuff_t *tvb, int offset, 
281                                   packet_info *pinfo, proto_tree *tree,
282                                   char *drep)
283 {
284         offset = dissect_nt_policy_hnd(
285                 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
286                 FALSE, TRUE);
287
288         return offset;
289 }
290 static int
291 svcctl_dissect_UnlockServiceDatabase_reply(tvbuff_t *tvb, int offset, 
292                                   packet_info *pinfo, proto_tree *tree,
293                                   char *drep)
294 {
295         offset = dissect_nt_policy_hnd(
296                 tvb, offset, pinfo, tree, drep, hf_svcctl_lock, NULL,
297                 TRUE, FALSE);
298
299         offset = dissect_doserror(
300                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
301
302         return offset;
303 }
304
305
306 /*
307  * IDL typedef struct {
308  * IDL     long is_locked,
309  * IDL     [unique][string] char *lock_owner,
310  * IDL     long lock_duration,
311  * IDL };
312  */ 
313 static int
314 svcctl_dissect_QUERY_SERVICE_LOCK_STATUS(tvbuff_t *tvb, int offset, 
315                                   packet_info *pinfo, proto_tree *tree,
316                                   char *drep)
317 {
318         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
319                                      hf_svcctl_is_locked, NULL);
320
321         offset = dissect_ndr_pointer(
322                 tvb, offset, pinfo, tree, drep,
323                 dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
324                 "Owner", hf_svcctl_lock_owner);
325
326         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
327                                      hf_svcctl_lock_duration, NULL);
328
329         return offset;
330 }
331
332 /*
333  * IDL long QueryServiceLockStatus(
334  * IDL      [in] SC_HANDLE db_handle,
335  * IDL      [in] long buf_size,
336  * IDL      [out][ref] QUERY_SERVICE_LOCK_STATUS *status,
337  * IDL      [out][ref] long *required_buf_size
338  * IDL );
339  */
340 static int
341 svcctl_dissect_QueryServiceLockStatus_rqst(tvbuff_t *tvb, int offset, 
342                                   packet_info *pinfo, proto_tree *tree,
343                                   char *drep)
344 {
345         offset = dissect_nt_policy_hnd(
346                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
347                 FALSE, TRUE);
348
349         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
350                                      hf_svcctl_size, NULL);
351
352         return offset;
353 }
354 static int
355 svcctl_dissect_QueryServiceLockStatus_reply(tvbuff_t *tvb, int offset, 
356                                   packet_info *pinfo, proto_tree *tree,
357                                   char *drep)
358 {
359         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
360                 svcctl_dissect_QUERY_SERVICE_LOCK_STATUS, NDR_POINTER_REF,
361                 "LOCK_STATUS", -1);
362
363         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
364                                      hf_svcctl_required_size, NULL);
365
366         offset = dissect_doserror(
367                 tvb, offset, pinfo, tree, drep, hf_svcctl_rc, NULL);
368
369         return offset;
370 }
371
372
373
374 #define SERVICE_DRIVER  0x0b
375 #define SERVICE_WIN32   0x30
376 static const value_string svcctl_service_type_vals[] = {
377         { SERVICE_DRIVER,       "SERVICE_DRIVER" },
378         { SERVICE_WIN32,        "SERVICE_WIN32" },
379         { 0, NULL }
380 };
381
382 #define SERVICE_ACTIVE          0x01
383 #define SERVICE_INACTIVE        0x02
384 #define SERVICE_STATE_ALL       0x03
385 static const value_string svcctl_service_status_vals[] = {
386         { SERVICE_ACTIVE,       "SERVICE_ACTIVE" },
387         { SERVICE_INACTIVE,     "SERVICE_INACTIVE" },
388         { SERVICE_STATE_ALL,    "SERVICE_STATE_ALL" },
389         { 0, NULL }
390 };
391
392 /*
393  * IDL long EnumServicesStatus(
394  * IDL      [in] SC_HANDLE db_handle,
395  * IDL      [in] long type,
396  * IDL      [in] long status,
397  * IDL      [in] long buf_size,
398  * IDL      [in][unique] long *resume_handle, 
399  * IDL );
400  */
401 static int
402 svcctl_dissect_EnumServicesStatus_rqst(tvbuff_t *tvb, int offset, 
403                                   packet_info *pinfo, proto_tree *tree,
404                                   char *drep)
405 {
406         offset = dissect_nt_policy_hnd(
407                 tvb, offset, pinfo, tree, drep, hf_svcctl_hnd, NULL,
408                 FALSE, TRUE);
409
410         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
411                                      hf_svcctl_service_type, NULL);
412
413         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
414                                      hf_svcctl_service_state, NULL);
415
416         offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
417                                      hf_svcctl_size, NULL);
418
419         offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
420                         svcctl_dissect_pointer_long, NDR_POINTER_UNIQUE,
421                         "Resume Handle", hf_svcctl_resume);
422
423         return offset;
424 }
425
426
427
428
429
430 static dcerpc_sub_dissector dcerpc_svcctl_dissectors[] = {
431         { SVC_CLOSE_SERVICE_HANDLE, "CloseServiceHandle", 
432                 svcctl_dissect_CloseServiceHandle_rqst, 
433                 svcctl_dissect_CloseServiceHandle_reply  },
434         { SVC_STOP_SERVICE, "Stop", NULL, NULL },
435         { SVC_DELETE, "Delete", NULL, NULL },
436         { SVC_LOCK_SERVICE_DATABASE, "LockServiceDatabase",
437                 svcctl_dissect_LockServiceDatabase_rqst, 
438                 svcctl_dissect_LockServiceDatabase_reply  },
439         { SVC_GET_SVC_SEC, "Get security", NULL, NULL },
440         { SVC_UNLOCK_SERVICE_DATABASE, "UnlockServiceDatabase",
441                 svcctl_dissect_UnlockServiceDatabase_rqst, 
442                 svcctl_dissect_UnlockServiceDatabase_reply  },
443         { SVC_CHANGE_SVC_CONFIG, "Change config", NULL, NULL },
444         { SVC_ENUM_SVCS_STATUS, "Enum status", NULL, NULL },
445         { SVC_OPEN_SC_MAN, "Open SC Manager", NULL, NULL },
446         { SVC_OPEN_SERVICE, "Open service", NULL, NULL },
447         { SVC_QUERY_SVC_CONFIG, "Query config", NULL, NULL },
448         { SVC_START_SERVICE, "Start", NULL, NULL },
449         { SVC_QUERY_DISP_NAME, "Query display name", NULL, NULL },
450         { SVC_ENUM_SERVICES_STATUS, "EnumServicesStatus",
451                 svcctl_dissect_EnumServicesStatus_rqst, 
452                 NULL },
453         { SVC_OPEN_SC_MANAGER, "OpenSCManager",
454                 svcctl_dissect_OpenSCManager_rqst,
455                 svcctl_dissect_OpenSCManager_reply },
456         { SVC_OPEN_SERVICE_A, "Open Service A", NULL, NULL },
457         { SVC_QUERY_SERVICE_LOCK_STATUS, "QueryServiceLockStatus",
458                 svcctl_dissect_QueryServiceLockStatus_rqst,
459                 svcctl_dissect_QueryServiceLockStatus_reply },
460         {0, NULL, NULL, NULL}
461 };
462
463 static const value_string svcctl_opnum_vals[] = {
464         { SVC_CLOSE_SERVICE_HANDLE, "CloseServiceHandle" },
465         { SVC_STOP_SERVICE, "StopService" },
466         { SVC_DELETE, "DeleteService" },
467         { SVC_LOCK_SERVICE_DATABASE, "LockServiceDatabase" },
468         { SVC_GET_SVC_SEC, "QueryServiceObjectSecurity" },
469         { SVC_UNLOCK_SERVICE_DATABASE, "UnockServiceDatabase" },
470         { SVC_CHANGE_SVC_CONFIG, "Change config" },
471         { SVC_ENUM_SVCS_STATUS, "Enum status" },
472         { SVC_OPEN_SC_MAN, "Open SC Manager" },
473         { SVC_OPEN_SERVICE, "Open service" },
474         { SVC_QUERY_SVC_CONFIG, "Query config" },
475         { SVC_START_SERVICE, "Start" },
476         { SVC_QUERY_DISP_NAME, "Query display name" },
477         { SVC_ENUM_SERVICES_STATUS, "EnumServicesStatus" },
478         { SVC_OPEN_SC_MANAGER, "OpenSCManager" },
479         { SVC_OPEN_SERVICE_A, "Open Service A" },
480         { SVC_QUERY_SERVICE_LOCK_STATUS, "QueryServiceLockStatus" },
481         { 0, NULL }
482 };
483
484
485 void
486 proto_register_dcerpc_svcctl(void)
487 {
488         static hf_register_info hf[] = {
489           { &hf_svcctl_opnum,
490             { "Operation", "svcctl.opnum", FT_UINT16, BASE_DEC,
491               VALS(svcctl_opnum_vals), 0x0, "Operation", HFILL }},
492           { &hf_svcctl_machinename,
493             { "MachineName", "svcctl.machinename", FT_STRING, BASE_NONE,
494               NULL, 0x0, "Name of the host we want to open the database on", HFILL }},
495           { &hf_svcctl_database,
496             { "Database", "svcctl.database", FT_STRING, BASE_NONE,
497               NULL, 0x0, "Name of the database to open", HFILL }},
498           { &hf_svcctl_access_mask,
499             { "Access Mask", "svcctl.access_mask", FT_UINT32, BASE_HEX,
500               NULL, 0x0, "SVCCTL Access Mask", HFILL }},
501           { &hf_svcctl_scm_rights_connect,
502             { "Connect", "svcctl.scm_rights_connect", FT_BOOLEAN, 32,
503               TFS(&flags_set_truth), 0x00000001, "SVCCTL Rights to connect to SCM", HFILL }},
504           { &hf_svcctl_scm_rights_create_service,
505             { "Create Service", "svcctl.scm_rights_create_service", FT_BOOLEAN, 32,
506               TFS(&flags_set_truth), 0x00000002, "SVCCTL Rights to create services", HFILL }},
507           { &hf_svcctl_scm_rights_enumerate_service,
508             { "Enumerate Service", "svcctl.scm_rights_enumerate_service", FT_BOOLEAN, 32,
509               TFS(&flags_set_truth), 0x00000004, "SVCCTL Rights to enumerate services", HFILL }},
510           { &hf_svcctl_scm_rights_lock,
511             { "Lock", "svcctl.scm_rights_lock", FT_BOOLEAN, 32,
512               TFS(&flags_set_truth), 0x00000008, "SVCCTL Rights to lock database", HFILL }},
513           { &hf_svcctl_scm_rights_query_lock_status,
514             { "Query Lock Status", "svcctl.scm_rights_query_lock_status", FT_BOOLEAN, 32,
515               TFS(&flags_set_truth), 0x00000010, "SVCCTL Rights to query database lock status", HFILL }},
516           { &hf_svcctl_scm_rights_modify_boot_config,
517             { "Modify Boot Config", "svcctl.scm_rights_modify_boot_config", FT_BOOLEAN, 32,
518               TFS(&flags_set_truth), 0x00000020, "SVCCTL Rights to modify boot config", HFILL }},
519           { &hf_svcctl_hnd,
520             { "Context Handle", "svcctl.hnd", FT_BYTES, BASE_NONE,
521               NULL, 0x0, "SVCCTL Context handle", HFILL }},
522           { &hf_svcctl_lock,
523             { "Lock", "svcctl.lock", FT_BYTES, BASE_NONE,
524               NULL, 0x0, "SVCCTL Database Lock", HFILL }},
525           { &hf_svcctl_rc,
526             { "Return code", "svcctl.rc", FT_UINT32, BASE_HEX,
527               VALS(DOS_errors), 0x0, "SVCCTL return code", HFILL }},
528           { &hf_svcctl_size,
529             { "Size", "svcctl.size", FT_UINT32, BASE_DEC,
530               NULL, 0x0, "SVCCTL size of buffer", HFILL }},
531           { &hf_svcctl_required_size,
532             { "Required Size", "svcctl.required_size", FT_UINT32, BASE_DEC,
533               NULL, 0x0, "SVCCTL required size of buffer for data to fit", HFILL }},
534           { &hf_svcctl_is_locked,
535             { "IsLocked", "svcctl.is_locked", FT_UINT32, BASE_DEC,
536               NULL, 0x0, "SVCCTL whether the database is locked or not", HFILL }},
537           { &hf_svcctl_lock_duration,
538             { "Duration", "svcctl.lock_duration", FT_UINT32, BASE_DEC,
539               NULL, 0x0, "SVCCTL number of seconds the database has been locked", HFILL }},
540           { &hf_svcctl_lock_owner,
541             { "Owner", "svcctl.lock_owner", FT_STRING, BASE_NONE,
542               NULL, 0x0, "SVCCTL the user that holds the database lock", HFILL }},
543           { &hf_svcctl_service_type,
544             { "Type", "svcctl.service_type", FT_UINT32, BASE_DEC,
545               VALS(svcctl_service_type_vals), 0x0, "SVCCTL type of service", HFILL }},
546
547           { &hf_svcctl_service_state,
548             { "State", "svcctl.service_state", FT_UINT32, BASE_DEC,
549               VALS(svcctl_service_status_vals), 0x0, "SVCCTL service state", HFILL }},
550           { &hf_svcctl_resume,
551             { "Resume Handle", "svcctl.resume", FT_UINT32, BASE_DEC,
552               NULL, 0x0, "SVCCTL resume handle", HFILL }},
553         };
554
555         static gint *ett[] = {
556                 &ett_dcerpc_svcctl,
557         };
558
559         proto_dcerpc_svcctl = proto_register_protocol(
560                 "Microsoft Service Control", "SVCCTL", "svcctl");
561
562         proto_register_field_array(proto_dcerpc_svcctl, hf, array_length(hf));
563         proto_register_subtree_array(ett, array_length(ett));
564 }
565
566 void
567 proto_reg_handoff_dcerpc_svcctl(void)
568 {
569         /* Register protocol as dcerpc */
570
571         dcerpc_init_uuid(proto_dcerpc_svcctl, ett_dcerpc_svcctl,
572                          &uuid_dcerpc_svcctl, ver_dcerpc_svcctl,
573                          dcerpc_svcctl_dissectors, hf_svcctl_opnum);
574 }