Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-dcerpc-reg.c
1 /* packet-dcerpc-reg.c
2  * Routines for SMB \PIPE\winreg packet disassembly
3  * Copyright 2001, 2002 Tim Potter <tpot@samba.org>
4  *
5  * $Id: packet-dcerpc-reg.c,v 1.11 2002/08/28 21:00:10 jmayer Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (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, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <glib.h>
31 #include <epan/packet.h>
32 #include "packet-dcerpc.h"
33 #include "packet-dcerpc-nt.h"
34 #include "packet-dcerpc-reg.h"
35 #include "smb.h"
36
37 /* Global hf index fields */
38
39 static int hf_rc = -1;
40 static int hf_hnd = -1;
41 static int hf_access_mask = -1;
42
43 /* OpenHKLM */
44
45 static int hf_openhklm_unknown1 = -1;
46 static int hf_openhklm_unknown2 = -1;
47
48 /* QueryKey */
49
50 static int hf_querykey_class = -1;
51 static int hf_querykey_num_subkeys = -1;
52 static int hf_querykey_max_subkey_len = -1;
53 static int hf_querykey_reserved = -1;
54 static int hf_querykey_num_values = -1;
55 static int hf_querykey_max_valname_len = -1;
56 static int hf_querykey_max_valbuf_size = -1;
57 static int hf_querykey_secdesc = -1;
58 static int hf_querykey_modtime = -1;
59
60 /* OpenEntry */
61
62 static int hf_keyname = -1;
63 static int hf_openentry_unknown1 = -1;
64
65 /* Unknown 0x1A */
66
67 static int hf_unknown1A_unknown1 = -1;
68
69 /* Data that is passed to a open call */
70
71 static int
72 dissect_open_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
73                   proto_tree *tree, char *drep)
74 {
75         offset = dissect_ndr_uint16(
76                 tvb, offset, pinfo, tree, drep,
77                 hf_openhklm_unknown1, NULL);
78
79         offset = dissect_ndr_uint16(
80                 tvb, offset, pinfo, tree, drep,
81                 hf_openhklm_unknown1, NULL);
82
83         offset = dissect_ndr_uint32(
84                 tvb, offset, pinfo, tree, drep,
85                 hf_access_mask, NULL);
86
87         return offset;
88 }
89
90 /*
91  * OpenHKLM
92  */
93
94 static int
95 RegOpenHKLM_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
96               proto_tree *tree, char *drep)
97 {
98         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
99         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
100
101         if (dcv->rep_frame != 0)
102                 proto_tree_add_text(tree, tvb, offset, 0,
103                                     "Reply in frame %u", dcv->rep_frame);
104
105         /* Parse packet */
106
107         offset = dissect_ndr_pointer(
108                 tvb, offset, pinfo, tree, drep,
109                 dissect_open_data,
110                 NDR_POINTER_UNIQUE, "Unknown", -1, 0);
111
112         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
113
114         return offset;
115 }
116
117 static int
118 RegOpenHKLM_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
119               proto_tree *tree, char *drep)
120 {
121         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
122         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
123         e_ctx_hnd policy_hnd;
124
125         if (dcv->req_frame != 0)
126                 proto_tree_add_text(tree, tvb, offset, 0,
127                                     "Request in frame %u", dcv->req_frame);
128
129         /* Parse packet */
130
131         offset = dissect_nt_policy_hnd(
132                 tvb, offset, pinfo, tree, drep,
133                 hf_hnd, &policy_hnd, TRUE, FALSE);
134
135         dcerpc_smb_store_pol_name(&policy_hnd, "HKLM handle");
136
137         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
138                                   hf_rc, NULL);
139
140         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
141
142         return offset;
143 }
144
145 /*
146  * OpenHKU
147  */
148
149 static int
150 RegOpenHKU_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
151              proto_tree *tree, char *drep)
152 {
153         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
154         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
155
156         if (dcv->rep_frame != 0)
157                 proto_tree_add_text(tree, tvb, offset, 0,
158                                     "Reply in frame %u", dcv->rep_frame);
159
160         /* Parse packet */
161
162         offset = dissect_ndr_pointer(
163                 tvb, offset, pinfo, tree, drep,
164                 dissect_open_data,
165                 NDR_POINTER_UNIQUE, "Unknown", -1, 0);
166
167         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
168
169         return offset;
170 }
171
172 static int
173 RegOpenHKU_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
174              proto_tree *tree, char *drep)
175 {
176         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
177         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
178         e_ctx_hnd policy_hnd;
179
180         if (dcv->req_frame != 0)
181                 proto_tree_add_text(tree, tvb, offset, 0,
182                                     "Request in frame %u", dcv->req_frame);
183
184         /* Parse packet */
185
186         offset = dissect_nt_policy_hnd(
187                 tvb, offset, pinfo, tree, drep,
188                 hf_hnd, &policy_hnd, TRUE, FALSE);
189
190         dcerpc_smb_store_pol_name(&policy_hnd, "HKU handle");
191
192         offset = dissect_ntstatus(
193                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
194
195         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
196
197         return offset;
198 }
199
200 /*
201  * OpenHKCR
202  */
203
204 static int
205 RegOpenHKCR_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
206               proto_tree *tree, char *drep)
207 {
208         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
209         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
210
211         if (dcv->rep_frame != 0)
212                 proto_tree_add_text(tree, tvb, offset, 0,
213                                     "Reply in frame %u", dcv->rep_frame);
214
215         /* Parse packet */
216
217         offset = dissect_ndr_pointer(
218                 tvb, offset, pinfo, tree, drep,
219                 dissect_open_data,
220                 NDR_POINTER_UNIQUE, "Unknown", -1, 0);
221
222         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
223
224         return offset;
225 }
226
227 static int
228 RegOpenHKCR_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
229               proto_tree *tree, char *drep)
230 {
231         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
232         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
233         e_ctx_hnd policy_hnd;
234
235         if (dcv->req_frame != 0)
236                 proto_tree_add_text(tree, tvb, offset, 0,
237                                     "Request in frame %u", dcv->req_frame);
238
239         /* Parse packet */
240
241         offset = dissect_nt_policy_hnd(
242                 tvb, offset, pinfo, tree, drep,
243                 hf_hnd, &policy_hnd, TRUE, FALSE);
244
245         dcerpc_smb_store_pol_name(&policy_hnd, "HKCR handle");
246
247         offset = dissect_ntstatus(
248                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
249
250         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
251
252         return offset;
253 }
254
255 /*
256  * RegClose
257  */
258
259 static int
260 RegClose_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
261            proto_tree *tree, char *drep)
262 {
263         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
264         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
265
266         if (dcv->rep_frame != 0)
267                 proto_tree_add_text(tree, tvb, offset, 0,
268                                     "Reply in frame %u", dcv->rep_frame);
269
270         /* Parse packet */
271
272         offset = dissect_nt_policy_hnd(
273                 tvb, offset, pinfo, tree, drep,
274                 hf_hnd, NULL, FALSE, TRUE);
275
276         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
277
278         return offset;
279 }
280
281 static int
282 RegClose_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
283            proto_tree *tree, char *drep)
284 {
285         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
286         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
287
288         if (dcv->req_frame != 0)
289                 proto_tree_add_text(tree, tvb, offset, 0,
290                                     "Request in frame %u", dcv->req_frame);
291
292         /* Parse packet */
293
294         offset = dissect_nt_policy_hnd(
295                 tvb, offset, pinfo, tree, drep,
296                 hf_hnd, NULL, FALSE, FALSE);
297
298         offset = dissect_ntstatus(
299                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
300
301         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
302
303         return offset;
304 }
305
306 /*
307  * RegQueryKey
308  */
309
310 static int
311 RegQueryKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
312               proto_tree *tree, char *drep)
313 {
314         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
315         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
316
317         if (dcv->rep_frame != 0)
318                 proto_tree_add_text(tree, tvb, offset, 0,
319                                     "Reply in frame %u", dcv->rep_frame);
320
321         /* Parse packet */
322
323         offset = dissect_nt_policy_hnd(
324                 tvb, offset, pinfo, tree, drep,
325                 hf_hnd, NULL, FALSE, FALSE);
326
327         offset = dissect_ndr_nt_UNICODE_STRING(
328                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
329
330         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
331
332         return offset;
333 }
334
335 static int
336 RegQueryKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
337               proto_tree *tree, char *drep)
338 {
339         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
340         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
341
342         if (dcv->req_frame != 0)
343                 proto_tree_add_text(tree, tvb, offset, 0,
344                                     "Request in frame %u", dcv->req_frame);
345
346         /* Parse packet */
347
348         offset = dissect_ndr_nt_UNICODE_STRING(
349                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
350
351         offset = dissect_ndr_uint32(
352                 tvb, offset, pinfo, tree, drep,
353                 hf_querykey_num_subkeys, NULL);
354
355         offset = dissect_ndr_uint32(
356                 tvb, offset, pinfo, tree, drep,
357                 hf_querykey_max_subkey_len, NULL);
358
359         offset = dissect_ndr_uint32(
360                 tvb, offset, pinfo, tree, drep,
361                 hf_querykey_reserved, NULL);
362
363         offset = dissect_ndr_uint32(
364                 tvb, offset, pinfo, tree, drep,
365                 hf_querykey_num_values, NULL);
366
367         offset = dissect_ndr_uint32(
368                 tvb, offset, pinfo, tree, drep,
369                 hf_querykey_max_valname_len, NULL);
370
371         offset = dissect_ndr_uint32(
372                 tvb, offset, pinfo, tree, drep,
373                 hf_querykey_max_valbuf_size, NULL);
374
375         offset = dissect_ndr_uint32(
376                 tvb, offset, pinfo, tree, drep,
377                 hf_querykey_secdesc, NULL);
378
379         offset = dissect_ndr_nt_NTTIME(
380                 tvb, offset, pinfo, tree, drep, hf_querykey_modtime);
381
382         offset = dissect_ntstatus(
383                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
384
385         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
386
387         return offset;
388 }
389
390 /*
391  * OpenEntry
392  */
393
394 static int
395 RegOpenEntry_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
396                proto_tree *tree, char *drep)
397 {
398         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
399         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
400
401         if (dcv->rep_frame != 0)
402                 proto_tree_add_text(tree, tvb, offset, 0,
403                                     "Reply in frame %u", dcv->rep_frame);
404
405         /* Parse packet */
406
407         offset = dissect_nt_policy_hnd(
408                 tvb, offset, pinfo, tree, drep,
409                 hf_hnd, NULL, FALSE, FALSE);
410
411         offset = dissect_ndr_nt_UNICODE_STRING(
412                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
413
414         offset = dissect_ndr_uint32(
415                 tvb, offset, pinfo, tree, drep,
416                 hf_openentry_unknown1, NULL);
417
418         offset = dissect_ndr_uint32(
419                 tvb, offset, pinfo, tree, drep,
420                 hf_access_mask, NULL);
421
422         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
423
424         return offset;
425 }
426
427 static int
428 RegOpenEntry_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
429                proto_tree *tree, char *drep)
430 {
431         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
432         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
433         e_ctx_hnd policy_hnd;
434
435         if (dcv->req_frame != 0)
436                 proto_tree_add_text(tree, tvb, offset, 0,
437                                     "Request in frame %u", dcv->req_frame);
438
439         /* Parse packet */
440
441         offset = dissect_nt_policy_hnd(
442                 tvb, offset, pinfo, tree, drep,
443                 hf_hnd, &policy_hnd, TRUE, FALSE);
444
445         dcerpc_smb_store_pol_name(&policy_hnd, "OpenEntry handle");
446
447         offset = dissect_ntstatus(
448                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
449
450         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
451
452         return offset;
453 }
454
455 /*
456  * Unknown1A
457  */
458
459 static int
460 RegUnknown1A_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
461                proto_tree *tree, char *drep)
462 {
463         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
464         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
465
466         if (dcv->rep_frame != 0)
467                 proto_tree_add_text(tree, tvb, offset, 0,
468                                     "Reply in frame %u", dcv->rep_frame);
469
470         /* Parse packet */
471
472         offset = dissect_nt_policy_hnd(
473                 tvb, offset, pinfo, tree, drep,
474                 hf_hnd, NULL, FALSE, FALSE);
475
476         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
477
478         return offset;
479 }
480
481 static int
482 RegUnknown1A_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
483                proto_tree *tree, char *drep)
484 {
485         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
486         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
487
488         if (dcv->req_frame != 0)
489                 proto_tree_add_text(tree, tvb, offset, 0,
490                                     "Request in frame %u", dcv->req_frame);
491
492         /* Parse packet */
493
494         offset = dissect_ndr_uint32(
495                 tvb, offset, pinfo, tree, drep,
496                 hf_unknown1A_unknown1, NULL);
497
498         offset = dissect_ntstatus(
499                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
500
501         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
502
503         return offset;
504 }
505
506 /*
507  * EnumKey
508  */
509
510 static int
511 RegEnumKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
512              proto_tree *tree, char *drep)
513 {
514         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
515         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
516
517         if (dcv->rep_frame != 0)
518                 proto_tree_add_text(tree, tvb, offset, 0,
519                                     "Reply in frame %u", dcv->rep_frame);
520
521         /* Parse packet */
522
523         offset = dissect_nt_policy_hnd(
524                 tvb, offset, pinfo, tree, drep,
525                 hf_hnd, NULL, FALSE, FALSE);
526
527         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
528
529         return offset;
530 }
531
532 static int
533 RegEnumKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
534              proto_tree *tree, char *drep)
535 {
536         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
537         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
538
539         if (dcv->req_frame != 0)
540                 proto_tree_add_text(tree, tvb, offset, 0,
541                                     "Request in frame %u", dcv->req_frame);
542
543         /* Parse packet */
544
545         offset = dissect_ntstatus(
546                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
547
548         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
549
550         return offset;
551 }
552
553 #if 0
554
555 /* Templates for new subdissectors */
556
557 /*
558  * FOO
559  */
560
561 static int
562 RegFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
563          proto_tree *tree, char *drep)
564 {
565         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
566         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
567
568         if (dcv->rep_frame != 0)
569                 proto_tree_add_text(tree, tvb, offset, 0,
570                                     "Reply in frame %u", dcv->rep_frame);
571
572         /* Parse packet */
573
574         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
575
576         return offset;
577 }
578
579 static int
580 RegFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
581          proto_tree *tree, char *drep)
582 {
583         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
584         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
585
586         if (dcv->req_frame != 0)
587                 proto_tree_add_text(tree, tvb, offset, 0,
588                                     "Request in frame %u", dcv->req_frame);
589
590         /* Parse packet */
591
592         offset = dissect_ntstatus(
593                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
594
595         dcerpc_smb_check_long_frame(tvb, offset, pinfo, tree);
596
597         return offset;
598 }
599
600 #endif
601
602 /* Registry data types */
603
604 const value_string reg_datatypes[] = {
605         { REG_NONE, "REG_NONE" },
606         { REG_SZ, "REG_SZ" },
607         { REG_EXPAND_SZ, "REG_EXPAND_SZ" },
608         { REG_BINARY, "REG_BINARY" },
609         { REG_DWORD, "REG_DWORD" },
610         { REG_DWORD_LE, "REG_DWORD_LE" },
611         { REG_DWORD_BE, "REG_DWORD_BE" },
612         { REG_LINK, "REG_LINK" },
613         { REG_MULTI_SZ, "REG_MULTI_SZ" },
614         { REG_RESOURCE_LIST, "REG_RESOURCE_LIST" },
615         { REG_FULL_RESOURCE_DESCRIPTOR, "REG_FULL_RESOURCE_DESCRIPTOR" },
616         { REG_RESOURCE_REQUIREMENTS_LIST, "REG_RESOURCE_REQUIREMENTS_LIST" },
617         {0, NULL }
618 };
619
620 static int proto_dcerpc_reg = -1;
621 static int hf_reg_opnum = -1;
622 static gint ett_dcerpc_reg = -1;
623
624 static e_uuid_t uuid_dcerpc_reg = {
625         0x338cd001, 0x2244, 0x31f1,
626         { 0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03 }
627 };
628
629 static guint16 ver_dcerpc_reg = 1;
630
631 static dcerpc_sub_dissector dcerpc_reg_dissectors[] = {
632         { REG_OPEN_HKCR, "OpenHKCR", RegOpenHKCR_q, RegOpenHKCR_r },
633         { _REG_UNK_01, "Unknown01", NULL, NULL },
634         { REG_OPEN_HKLM, "OpenHKLM", RegOpenHKLM_q, RegOpenHKLM_r },
635         { _REG_UNK_03, "Unknown03", NULL, NULL },
636         { REG_OPEN_HKU, "OpenHKU", RegOpenHKU_q, RegOpenHKU_r },
637         { REG_CLOSE, "Close", RegClose_q, RegClose_r },
638         { REG_CREATE_KEY, "CreateKey", NULL, NULL },
639         { REG_DELETE_KEY, "DeleteKey", NULL, NULL },
640         { REG_DELETE_VALUE, "DeleteValue", NULL, NULL },
641         { REG_ENUM_KEY, "EnumKey", RegEnumKey_q, RegEnumKey_r },
642         { REG_ENUM_VALUE, "EnumValue", NULL, NULL },
643         { REG_FLUSH_KEY, "FlushKey", NULL, NULL },
644         { REG_GET_KEY_SEC, "GetKeySecurity", NULL, NULL },
645         { _REG_UNK_0D, "Unknown0d", NULL, NULL },
646         { _REG_UNK_0E, "Unknown0e", NULL, NULL },
647         { REG_OPEN_ENTRY, "OpenEntry", RegOpenEntry_q, RegOpenEntry_r },
648         { REG_QUERY_KEY, "QueryKey", RegQueryKey_q, RegQueryKey_r },
649         { REG_INFO, "Info", NULL, NULL },
650         { _REG_UNK_12, "Unknown12", NULL, NULL },
651         { _REG_UNK_13, "Unknown13", NULL, NULL },
652         { _REG_UNK_14, "Unknown14", NULL, NULL },
653         { REG_SET_KEY_SEC, "SetKeySecurity", NULL, NULL },
654         { REG_CREATE_VALUE, "CreateValue", NULL, NULL },
655         { _REG_UNK_17, "Unknown17", NULL, NULL },
656         { REG_SHUTDOWN, "Shutdown", NULL, NULL },
657         { REG_ABORT_SHUTDOWN, "AbortShutdown", NULL, NULL },
658         { REG_UNK_1A, "Unknown1A", RegUnknown1A_q, RegUnknown1A_r },
659
660         { 0, NULL, NULL,  NULL }
661 };
662
663 static const value_string reg_opnum_vals[] = {
664         { REG_OPEN_HKCR, "OpenHKCR" },
665         { _REG_UNK_01, "Unknown01" },
666         { REG_OPEN_HKLM, "OpenHKLM" },
667         { _REG_UNK_03, "Unknown03" },
668         { REG_OPEN_HKU, "OpenHKU" },
669         { REG_CLOSE, "Close" },
670         { REG_CREATE_KEY, "CreateKey" },
671         { REG_DELETE_KEY, "DeleteKey" },
672         { REG_DELETE_VALUE, "DeleteValue" },
673         { REG_ENUM_KEY, "EnumKey" },
674         { REG_ENUM_VALUE, "EnumValue" },
675         { REG_FLUSH_KEY, "FlushKey" },
676         { REG_GET_KEY_SEC, "GetKeySecurity" },
677         { _REG_UNK_0D, "Unknown0d" },
678         { _REG_UNK_0E, "Unknown0e" },
679         { REG_OPEN_ENTRY, "OpenEntry" },
680         { REG_QUERY_KEY, "QueryKey" },
681         { REG_INFO, "Info" },
682         { _REG_UNK_12, "Unknown12" },
683         { _REG_UNK_13, "Unknown13" },
684         { _REG_UNK_14, "Unknown14" },
685         { REG_SET_KEY_SEC, "SetKeySecurity" },
686         { REG_CREATE_VALUE, "CreateValue" },
687         { _REG_UNK_17, "Unknown17" },
688         { REG_SHUTDOWN, "Shutdown" },
689         { REG_ABORT_SHUTDOWN, "AbortShutdown" },
690         { REG_UNK_1A, "Unknown1A" },
691         { 0, NULL }
692 };
693
694 void
695 proto_register_dcerpc_reg(void)
696 {
697         static hf_register_info hf[] = {
698
699                 /* Global indexes */
700
701                 { &hf_hnd,
702                   { "Context handle", "reg.hnd", FT_BYTES, BASE_NONE,
703                     NULL, 0x0, "REG policy handle", HFILL }},
704
705                 { &hf_rc,
706                   { "Return code", "reg.rc", FT_UINT32, BASE_HEX,
707                     VALS(NT_errors), 0x0, "REG return code", HFILL }},
708
709                 { &hf_reg_opnum,
710                   { "Operation", "reg.opnum", FT_UINT16, BASE_DEC,
711                     VALS(reg_opnum_vals), 0x0, "Operation", HFILL }},
712
713                 { &hf_access_mask,
714                   { "Access mask", "reg.access_mask", FT_UINT32, BASE_HEX,
715                     NULL, 0x0, "Access mask", HFILL }},
716
717                 /* OpenHKLM */
718
719                 { &hf_openhklm_unknown1,
720                   { "Unknown 1", "reg.openhklm.unknown1", FT_UINT16, BASE_HEX,
721                     NULL, 0x0, "Unknown 1", HFILL }},
722
723                 { &hf_openhklm_unknown2,
724                   { "Unknown 2", "reg.openhklm.unknown2", FT_UINT16, BASE_HEX,
725                     NULL, 0x0, "Unknown 2", HFILL }},
726
727                 /* QueryClass */
728
729                 { &hf_querykey_class,
730                   { "Class", "reg.querykey.class", FT_STRING, BASE_NONE,
731                     NULL, 0, "Class", HFILL }},
732
733                 { &hf_querykey_num_subkeys,
734                   { "Num subkeys", "reg.querykey.num_subkeys", FT_UINT32, BASE_DEC,
735                     NULL, 0x0, "Num subkeys", HFILL }},
736
737                 { &hf_querykey_max_subkey_len,
738                   { "Max subkey len", "reg.querykey.max_subkey_len", FT_UINT32, BASE_DEC,
739                     NULL, 0x0, "Max subkey len", HFILL }},
740
741                 { &hf_querykey_reserved,
742                   { "Reserved", "reg.querykey.reserved", FT_UINT32, BASE_DEC,
743                     NULL, 0x0, "Reserved", HFILL }},
744
745                 { &hf_querykey_num_values,
746                   { "Num values", "reg.querykey.num_values", FT_UINT32, BASE_DEC,
747                     NULL, 0x0, "Num values", HFILL }},
748
749                 { &hf_querykey_max_valname_len,
750                   { "Max valnum len", "reg.querykey.max_valname_len", FT_UINT32, BASE_DEC,
751                     NULL, 0x0, "Max valname len", HFILL }},
752
753                 { &hf_querykey_max_valbuf_size,
754                   { "Max valbuf size", "reg.querykey.max_valbuf_size", FT_UINT32, BASE_DEC,
755                     NULL, 0x0, "Max valbuf size", HFILL }},
756
757                 { &hf_querykey_secdesc,
758                   { "Secdesc", "reg.querykey.secdesc", FT_UINT32, BASE_DEC,
759                     NULL, 0x0, "Secdesc", HFILL }},
760
761                 { &hf_querykey_modtime,
762                   { "Mod time", "reg.querykey.modtime", FT_ABSOLUTE_TIME, BASE_NONE,
763                     NULL, 0x0, "Secdesc", HFILL }},
764
765                 /* OpenEntry */
766
767                 { &hf_keyname,
768                   { "Key name", "reg.keyname", FT_STRING, BASE_NONE,
769                     NULL, 0x0, "Keyname", HFILL }},
770
771                 { &hf_openentry_unknown1,
772                   { "Unknown 1", "reg.openentry.unknown1", FT_UINT32, BASE_HEX,
773                     NULL, 0x0, "Unknown 1", HFILL }},
774
775                 /* Unknown1A */
776
777                 { &hf_unknown1A_unknown1,
778                   { "Unknown 1", "reg.unknown1A.unknown1", FT_UINT32, BASE_HEX,
779                     NULL, 0x0, "Unknown 1", HFILL }},
780
781         };
782
783         static gint *ett[] = {
784                 &ett_dcerpc_reg
785         };
786
787         proto_dcerpc_reg = proto_register_protocol(
788                 "Microsoft Registry", "WINREG", "winreg");
789
790         proto_register_field_array(proto_dcerpc_reg, hf, array_length(hf));
791
792         proto_register_subtree_array(ett, array_length(ett));
793 }
794
795 void
796 proto_reg_handoff_dcerpc_reg(void)
797 {
798         /* Register protocol as dcerpc */
799
800         dcerpc_init_uuid(proto_dcerpc_reg, ett_dcerpc_reg, &uuid_dcerpc_reg,
801                          ver_dcerpc_reg, dcerpc_reg_dissectors, hf_reg_opnum);
802 }