Set the svn:eol-style property on all text files to "native", so that
[obnox/wireshark/wip.git] / packet-dcerpc-reg.c
1 /* packet-dcerpc-reg.c
2  * Routines for SMB \PIPE\winreg packet disassembly
3  * Copyright 2001-2003 Tim Potter <tpot@samba.org>
4  *
5  * $Id$
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 static int hf_keytype = -1;
43 static int hf_keydata = -1;
44 static int hf_offered = -1;
45 static int hf_returned = -1;
46 static int hf_reserved = -1;
47 static int hf_unknown = -1;
48
49 /* OpenHKLM */
50
51 static int hf_openhklm_unknown1 = -1;
52 static int hf_openhklm_unknown2 = -1;
53
54 /* QueryInfoKey */
55
56 static int hf_querykey_class = -1;
57 static int hf_querykey_num_subkeys = -1;
58 static int hf_querykey_max_subkey_len = -1;
59 static int hf_querykey_reserved = -1;
60 static int hf_querykey_num_values = -1;
61 static int hf_querykey_max_valname_len = -1;
62 static int hf_querykey_max_valbuf_size = -1;
63 static int hf_querykey_secdesc = -1;
64 static int hf_querykey_modtime = -1;
65
66 /* OpenKey */
67
68 static int hf_keyname = -1;
69 static int hf_openkey_unknown1 = -1;
70
71 /* GetVersion */
72
73 static int hf_getversion_version = -1;
74
75 /* Shutdown */
76 static int hf_shutdown_message = -1;
77 static int hf_shutdown_seconds = -1;
78 static int hf_shutdown_force = -1;
79 static int hf_shutdown_reboot = -1;
80 static int hf_shutdown_server = -1;
81 static int hf_shutdown_reason = -1;
82
83 /* Data that is passed to a open call */
84
85 static int
86 dissect_open_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
87                   proto_tree *tree, guint8 *drep)
88 {
89         offset = dissect_ndr_uint16(
90                 tvb, offset, pinfo, tree, drep,
91                 hf_openhklm_unknown1, NULL);
92
93         offset = dissect_ndr_uint16(
94                 tvb, offset, pinfo, tree, drep,
95                 hf_openhklm_unknown1, NULL);
96
97         offset = dissect_ndr_uint32(
98                 tvb, offset, pinfo, tree, drep,
99                 hf_access_mask, NULL);
100
101         return offset;
102 }
103
104 /*
105  * OpenHKLM
106  */
107
108 static int
109 RegOpenHKLM_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
110               proto_tree *tree, guint8 *drep)
111 {
112         /* Parse packet */
113
114         offset = dissect_ndr_pointer(
115                 tvb, offset, pinfo, tree, drep,
116                 dissect_open_data,
117                 NDR_POINTER_UNIQUE, "Unknown", -1);
118
119         return offset;
120 }
121
122 static int
123 RegOpenHKLM_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
124               proto_tree *tree, guint8 *drep)
125 {
126         e_ctx_hnd policy_hnd;
127         proto_item *hnd_item;
128         guint32 status;
129
130         /* Parse packet */
131
132         offset = dissect_nt_policy_hnd(
133                 tvb, offset, pinfo, tree, drep,
134                 hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
135
136         offset = dissect_ntstatus(tvb, offset, pinfo, tree, drep,
137                                   hf_rc, &status);
138
139         if (status == 0) {
140                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, "HKLM handle");
141                 if (hnd_item != NULL)
142                         proto_item_append_text(hnd_item, ": HKLM handle");
143         }
144
145         return offset;
146 }
147
148 /*
149  * OpenHKU
150  */
151
152 static int
153 RegOpenHKU_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
154              proto_tree *tree, guint8 *drep)
155 {
156         /* Parse packet */
157
158         offset = dissect_ndr_pointer(
159                 tvb, offset, pinfo, tree, drep,
160                 dissect_open_data,
161                 NDR_POINTER_UNIQUE, "Unknown", -1);
162
163         return offset;
164 }
165
166 static int
167 RegOpenHKU_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
168              proto_tree *tree, guint8 *drep)
169 {
170         e_ctx_hnd policy_hnd;
171         proto_item *hnd_item;
172         guint32 status;
173
174         /* Parse packet */
175
176         offset = dissect_nt_policy_hnd(
177                 tvb, offset, pinfo, tree, drep,
178                 hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
179
180         offset = dissect_ntstatus(
181                 tvb, offset, pinfo, tree, drep, hf_rc, &status);
182
183         if (status == 0) {
184                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, "HKU handle");
185                 if (hnd_item != NULL)
186                         proto_item_append_text(hnd_item, ": HKU handle");
187         }
188
189         return offset;
190 }
191
192 /*
193  * OpenHKCR
194  */
195
196 static int
197 RegOpenHKCR_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
198               proto_tree *tree, guint8 *drep)
199 {
200         /* Parse packet */
201
202         offset = dissect_ndr_pointer(
203                 tvb, offset, pinfo, tree, drep,
204                 dissect_open_data,
205                 NDR_POINTER_UNIQUE, "Unknown", -1);
206
207         return offset;
208 }
209
210 static int
211 RegOpenHKCR_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
212               proto_tree *tree, guint8 *drep)
213 {
214         e_ctx_hnd policy_hnd;
215         proto_item *hnd_item;
216         guint32 status;
217
218         /* Parse packet */
219
220         offset = dissect_nt_policy_hnd(
221                 tvb, offset, pinfo, tree, drep,
222                 hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
223
224         offset = dissect_ntstatus(
225                 tvb, offset, pinfo, tree, drep, hf_rc, &status);
226
227         if (status == 0) {
228                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo, "HKCR handle");
229                 if (hnd_item != NULL)
230                         proto_item_append_text(hnd_item, ": HKCR handle");
231         }
232
233         return offset;
234 }
235
236 /*
237  * CloseKey
238  */
239
240 static int
241 RegCloseKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
242            proto_tree *tree, guint8 *drep)
243 {
244         /* Parse packet */
245
246         offset = dissect_nt_policy_hnd(
247                 tvb, offset, pinfo, tree, drep,
248                 hf_hnd, NULL, NULL, FALSE, TRUE);
249
250         return offset;
251 }
252
253 static int
254 RegCloseKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
255            proto_tree *tree, guint8 *drep)
256 {
257         /* Parse packet */
258
259         offset = dissect_nt_policy_hnd(
260                 tvb, offset, pinfo, tree, drep,
261                 hf_hnd, NULL, NULL, FALSE, FALSE);
262
263         offset = dissect_ntstatus(
264                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
265
266         return offset;
267 }
268
269 /*
270  * QueryInfoKey
271  */
272
273 static int
274 RegQueryInfoKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
275               proto_tree *tree, guint8 *drep)
276 {
277         /* Parse packet */
278
279         offset = dissect_nt_policy_hnd(
280                 tvb, offset, pinfo, tree, drep,
281                 hf_hnd, NULL, NULL, FALSE, FALSE);
282
283         offset = dissect_ndr_counted_string(
284                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
285
286         return offset;
287 }
288
289 static int
290 RegQueryInfoKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
291               proto_tree *tree, guint8 *drep)
292 {
293         /* Parse packet */
294
295         offset = dissect_ndr_counted_string(
296                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
297
298         offset = dissect_ndr_uint32(
299                 tvb, offset, pinfo, tree, drep,
300                 hf_querykey_num_subkeys, NULL);
301
302         offset = dissect_ndr_uint32(
303                 tvb, offset, pinfo, tree, drep,
304                 hf_querykey_max_subkey_len, NULL);
305
306         offset = dissect_ndr_uint32(
307                 tvb, offset, pinfo, tree, drep,
308                 hf_querykey_reserved, NULL);
309
310         offset = dissect_ndr_uint32(
311                 tvb, offset, pinfo, tree, drep,
312                 hf_querykey_num_values, NULL);
313
314         offset = dissect_ndr_uint32(
315                 tvb, offset, pinfo, tree, drep,
316                 hf_querykey_max_valname_len, NULL);
317
318         offset = dissect_ndr_uint32(
319                 tvb, offset, pinfo, tree, drep,
320                 hf_querykey_max_valbuf_size, NULL);
321
322         offset = dissect_ndr_uint32(
323                 tvb, offset, pinfo, tree, drep,
324                 hf_querykey_secdesc, NULL);
325
326         offset = dissect_ndr_nt_NTTIME(
327                 tvb, offset, pinfo, tree, drep, hf_querykey_modtime);
328
329         offset = dissect_ntstatus(
330                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
331
332         return offset;
333 }
334
335 /*
336  * OpenKey
337  */
338
339 static int
340 RegOpenKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
341                proto_tree *tree, guint8 *drep)
342 {
343         /* Parse packet */
344
345         offset = dissect_nt_policy_hnd(
346                 tvb, offset, pinfo, tree, drep,
347                 hf_hnd, NULL, NULL, FALSE, FALSE);
348
349         offset = dissect_ndr_counted_string(
350                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
351
352         offset = dissect_ndr_uint32(
353                 tvb, offset, pinfo, tree, drep,
354                 hf_openkey_unknown1, NULL);
355
356         offset = dissect_ndr_uint32(
357                 tvb, offset, pinfo, tree, drep,
358                 hf_access_mask, NULL);
359
360         return offset;
361 }
362
363 static int
364 RegOpenKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
365                proto_tree *tree, guint8 *drep)
366 {
367         e_ctx_hnd policy_hnd;
368         proto_item *hnd_item;
369         guint32 status;
370
371         /* Parse packet */
372
373         offset = dissect_nt_policy_hnd(
374                 tvb, offset, pinfo, tree, drep,
375                 hf_hnd, &policy_hnd, &hnd_item, TRUE, FALSE);
376
377         offset = dissect_ntstatus(
378                 tvb, offset, pinfo, tree, drep, hf_rc, &status);
379
380         if (status == 0) {
381                 dcerpc_smb_store_pol_name(&policy_hnd, pinfo,
382                         "OpenKey handle");
383                 if (hnd_item != NULL)
384                         proto_item_append_text(hnd_item, ": OpenKey handle");
385         }
386
387         return offset;
388 }
389
390 /*
391  * GetVersion
392  */
393
394 static int
395 RegGetVersion_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
396                proto_tree *tree, guint8 *drep)
397 {
398         /* Parse packet */
399
400         offset = dissect_nt_policy_hnd(
401                 tvb, offset, pinfo, tree, drep,
402                 hf_hnd, NULL, NULL, FALSE, FALSE);
403
404         return offset;
405 }
406
407 static int
408 RegGetVersion_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
409                proto_tree *tree, guint8 *drep)
410 {
411         /* Parse packet */
412
413         offset = dissect_ndr_uint32(
414                 tvb, offset, pinfo, tree, drep,
415                 hf_getversion_version, NULL);
416
417         offset = dissect_ntstatus(
418                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
419
420         return offset;
421 }
422
423 /*
424  * EnumKey
425  */
426
427 static int
428 RegEnumKey_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
429              proto_tree *tree, guint8 *drep)
430 {
431         /* Parse packet */
432
433         offset = dissect_nt_policy_hnd(
434                 tvb, offset, pinfo, tree, drep,
435                 hf_hnd, NULL, NULL, FALSE, FALSE);
436
437         return offset;
438 }
439
440 static int
441 RegEnumKey_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
442              proto_tree *tree, guint8 *drep)
443 {
444         /* Parse packet */
445
446         offset = dissect_ntstatus(
447                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
448
449         return offset;
450 }
451
452 /*
453  * RegQueryValue
454  */
455
456 static int
457 dissect_reserved(tvbuff_t *tvb, int offset, packet_info *pinfo,
458                  proto_tree *tree, guint8 *drep)
459 {
460         offset = dissect_ndr_uint32(
461                 tvb, offset, pinfo, tree, drep, hf_reserved, NULL);
462
463         return offset;
464 }
465
466 static int
467 dissect_offered(tvbuff_t *tvb, int offset, packet_info *pinfo,
468                 proto_tree *tree, guint8 *drep)
469 {
470         offset = dissect_ndr_uint32(
471                 tvb, offset, pinfo, tree, drep, hf_offered, NULL);
472
473         return offset;
474 }
475
476 static int
477 dissect_returned(tvbuff_t *tvb, int offset, packet_info *pinfo,
478                  proto_tree *tree, guint8 *drep)
479 {
480         offset = dissect_ndr_uint32(
481                 tvb, offset, pinfo, tree, drep, hf_returned, NULL);
482
483         return offset;
484 }
485
486 static int
487 dissect_unknown(tvbuff_t *tvb, int offset, packet_info *pinfo,
488                 proto_tree *tree, guint8 *drep)
489 {
490         offset = dissect_ndr_uint32(
491                 tvb, offset, pinfo, tree, drep, hf_unknown, NULL);
492
493         return offset;
494 }
495
496 static int
497 RegQueryValue_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
498                 proto_tree *tree, guint8 *drep)
499 {
500         /* Parse packet */
501
502         offset = dissect_nt_policy_hnd(
503                 tvb, offset, pinfo, tree, drep,
504                 hf_hnd, NULL, NULL, FALSE, FALSE);
505
506         offset = dissect_ndr_counted_string(
507                 tvb, offset, pinfo, tree, drep, hf_querykey_class, 0);
508
509         offset = dissect_ndr_pointer(
510                 tvb, offset, pinfo, tree, drep,
511                 dissect_reserved, NDR_POINTER_UNIQUE,
512                 "Reserved", -1);
513
514         offset = dissect_ndr_pointer(
515                 tvb, offset, pinfo, tree, drep,
516                 dissect_offered, NDR_POINTER_UNIQUE,
517                 "Offered", -1);
518
519         offset = dissect_ndr_pointer(
520                 tvb, offset, pinfo, tree, drep,
521                 dissect_unknown, NDR_POINTER_UNIQUE,
522                 "Unknown", -1);
523
524         offset = dissect_ndr_pointer(
525                 tvb, offset, pinfo, tree, drep,
526                 dissect_unknown, NDR_POINTER_UNIQUE,
527                 "Unknown", -1);
528
529         offset = dissect_ndr_pointer(
530                 tvb, offset, pinfo, tree, drep,
531                 dissect_offered, NDR_POINTER_UNIQUE,
532                 "Offered", -1);
533
534         offset = dissect_ndr_pointer(
535                 tvb, offset, pinfo, tree, drep,
536                 dissect_returned, NDR_POINTER_UNIQUE,
537                 "Returned", -1);
538
539         return offset;
540 }
541
542 static int
543 dissect_key_type(tvbuff_t *tvb, int offset, packet_info *pinfo,
544                  proto_tree *tree, guint8 *drep)
545 {
546         offset = dissect_ndr_uint32(
547                 tvb, offset, pinfo, tree, drep, hf_keytype, NULL);
548
549         return offset;
550 }
551
552 static int
553 RegQueryValue_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
554                 proto_tree *tree, guint8 *drep)
555 {
556         /* Parse packet */
557
558         offset = dissect_ndr_pointer(
559                 tvb, offset, pinfo, tree, drep,
560                 dissect_key_type, NDR_POINTER_UNIQUE,
561                 "Key Type", -1);        
562
563         offset = dissect_ndr_pointer(
564                 tvb, offset, pinfo, tree, drep,
565                 dissect_ndr_byte_array, NDR_POINTER_UNIQUE,
566                 "Key Data", -1);
567
568         offset = dissect_ndr_pointer(
569                 tvb, offset, pinfo, tree, drep,
570                 dissect_offered, NDR_POINTER_UNIQUE,
571                 "Offered", -1);
572
573         offset = dissect_ndr_pointer(
574                 tvb, offset, pinfo, tree, drep,
575                 dissect_returned, NDR_POINTER_UNIQUE,
576                 "Returned", -1);
577
578         offset = dissect_ntstatus(
579                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
580
581         return offset;
582 }
583
584 /* Reg Shutdown functions */
585 static int
586 dissect_shutdown_server(tvbuff_t *tvb, int offset, packet_info *pinfo,
587                         proto_tree *tree, guint8 *drep)
588 {
589         offset = dissect_ndr_uint16(
590                 tvb, offset, pinfo, tree, drep, hf_shutdown_server, NULL);
591
592         return offset;
593 }
594
595 static int
596 dissect_shutdown_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
597                         proto_tree *tree, guint8 *drep)
598 {
599         offset = dissect_ndr_counted_string(
600                 tvb, offset, pinfo, tree, drep, hf_shutdown_message, 0);
601
602         return offset;
603 }
604
605 static int
606 RegShutdown_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
607          proto_tree *tree, guint8 *drep)
608 {
609         offset = dissect_ndr_pointer(
610                 tvb, offset, pinfo, tree, drep,
611                 dissect_shutdown_server, NDR_POINTER_UNIQUE,
612                 "Server", -1);
613
614         offset = dissect_ndr_pointer(
615                 tvb, offset, pinfo, tree, drep,
616                 dissect_shutdown_message, NDR_POINTER_UNIQUE,
617                 "message", -1);
618
619         offset = dissect_ndr_uint32(
620                 tvb, offset, pinfo, tree, drep, hf_shutdown_seconds, NULL);
621         
622         offset = dissect_ndr_uint8(
623                 tvb, offset, pinfo, tree, drep, hf_shutdown_force, NULL);
624         offset = dissect_ndr_uint8(
625                 tvb, offset, pinfo, tree, drep, hf_shutdown_reboot, NULL);
626                 
627         return offset;
628 }
629
630 static int
631 RegShutdown_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
632          proto_tree *tree, guint8 *drep)
633 {
634         offset = dissect_ntstatus(
635                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
636
637         return offset;
638 }
639
640 static int
641 RegAbortShutdown_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
642                    proto_tree *tree, guint8 *drep)
643 {
644         offset = dissect_ndr_pointer(
645                 tvb, offset, pinfo, tree, drep,
646                 dissect_shutdown_server, NDR_POINTER_UNIQUE,
647                 "Server", -1);  
648                 
649         return offset;
650 }
651
652 static int
653 RegShutdownEx_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
654                 proto_tree *tree, guint8 *drep)
655 {
656         offset = RegShutdown_q(tvb, offset, pinfo, tree, drep);
657         offset = dissect_ndr_uint32(
658                 tvb, offset, pinfo, tree, drep, hf_shutdown_reason, NULL);
659                 
660         return offset;
661 }
662
663 #if 0
664
665 /* Templates for new subdissectors */
666
667 /*
668  * FOO
669  */
670
671 static int
672 RegFoo_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
673          proto_tree *tree, guint8 *drep)
674 {
675         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
676
677         /* Parse packet */
678
679         return offset;
680 }
681
682 static int
683 RegFoo_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
684          proto_tree *tree, guint8 *drep)
685 {
686         dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
687
688         /* Parse packet */
689
690         offset = dissect_ntstatus(
691                 tvb, offset, pinfo, tree, drep, hf_rc, NULL);
692
693         return offset;
694 }
695
696 #endif
697
698 /* Registry data types */
699
700 const value_string reg_datatypes[] = {
701         { DCERPC_REG_NONE, "REG_NONE" },
702         { DCERPC_REG_SZ, "REG_SZ" },
703         { DCERPC_REG_EXPAND_SZ, "REG_EXPAND_SZ" },
704         { DCERPC_REG_BINARY, "REG_BINARY" },
705         { DCERPC_REG_DWORD, "REG_DWORD" },
706         { DCERPC_REG_DWORD_LE, "REG_DWORD_LE" },
707         { DCERPC_REG_DWORD_BE, "REG_DWORD_BE" },
708         { DCERPC_REG_LINK, "REG_LINK" },
709         { DCERPC_REG_MULTI_SZ, "REG_MULTI_SZ" },
710         { DCERPC_REG_RESOURCE_LIST, "REG_RESOURCE_LIST" },
711         { DCERPC_REG_FULL_RESOURCE_DESCRIPTOR, "REG_FULL_RESOURCE_DESCRIPTOR" },
712         { DCERPC_REG_RESOURCE_REQUIREMENTS_LIST, "REG_RESOURCE_REQUIREMENTS_LIST" },
713         {0, NULL }
714 };
715
716 static int proto_dcerpc_reg = -1;
717 static int hf_reg_opnum = -1;
718 static gint ett_dcerpc_reg = -1;
719
720 static e_uuid_t uuid_dcerpc_reg = {
721         0x338cd001, 0x2244, 0x31f1,
722         { 0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03 }
723 };
724
725 static guint16 ver_dcerpc_reg = 1;
726
727 static dcerpc_sub_dissector dcerpc_reg_dissectors[] = {
728         { REG_OPEN_HKCR, "OpenHKCR", RegOpenHKCR_q, RegOpenHKCR_r },
729         { REG_OPEN_HKCU, "OpenHKCU", NULL, NULL },
730         { REG_OPEN_HKLM, "OpenHKLM", RegOpenHKLM_q, RegOpenHKLM_r },
731         { REG_OPEN_HKPD, "OpenHKPD", NULL, NULL },
732         { REG_OPEN_HKU, "OpenHKU", RegOpenHKU_q, RegOpenHKU_r },
733         { REG_CLOSE_KEY, "CloseKey", RegCloseKey_q, RegCloseKey_r },
734         { REG_CREATE_KEY, "CreateKey", NULL, NULL },
735         { REG_DELETE_KEY, "DeleteKey", NULL, NULL },
736         { REG_DELETE_VALUE, "DeleteValue", NULL, NULL },
737         { REG_ENUM_KEY, "EnumKey", RegEnumKey_q, RegEnumKey_r },
738         { REG_ENUM_VALUE, "EnumValue", NULL, NULL },
739         { REG_FLUSH_KEY, "FlushKey", NULL, NULL },
740         { REG_GET_KEY_SEC, "GetKeySecurity", NULL, NULL },
741         { REG_LOAD_KEY, "LoadKey", NULL, NULL },
742         { REG_NOTIFY_CHANGE_KEY_VALUE, "NotifyChangeKeyValue", NULL, NULL },
743         { REG_OPEN_KEY, "OpenKey", RegOpenKey_q, RegOpenKey_r },
744         { REG_QUERY_INFO_KEY, "QueryInfoKey", RegQueryInfoKey_q, RegQueryInfoKey_r },
745         { REG_QUERY_VALUE, "QueryValue", RegQueryValue_q, RegQueryValue_r },
746         { REG_REPLACE_KEY, "ReplaceKey", NULL, NULL },
747         { REG_RESTORE_KEY, "RestoreKey", NULL, NULL },
748         { REG_SAVE_KEY, "SaveKey", NULL, NULL },
749         { REG_SET_KEY_SEC, "SetKeySecurity", NULL, NULL },
750         { REG_SET_VALUE, "SetValue", NULL, NULL },
751         { REG_UNLOAD_KEY, "UnLoadKey", NULL, NULL },
752         { REG_INITIATE_SYSTEM_SHUTDOWN, "InitiateSystemShutdown", 
753           RegShutdown_q, RegShutdown_r },
754         { REG_ABORT_SYSTEM_SHUTDOWN, "AbortSystemShutdown", 
755           RegAbortShutdown_q, RegShutdown_r },
756         { REG_GET_VERSION, "GetVersion", RegGetVersion_q, RegGetVersion_r },
757         { REG_OPEN_HKCC, "OpenHKCC", NULL, NULL },
758         { REG_OPEN_HKDD, "OpenHKDD", NULL, NULL },
759         { REG_QUERY_MULTIPLE_VALUES, "QueryMultipleValues", NULL, NULL },
760         { REG_INITIATE_SYSTEM_SHUTDOWN_EX, "InitiateSystemShutdownEx", 
761           RegShutdownEx_q, RegShutdown_r },
762         { REG_SAVE_KEY_EX, "SaveKeyEx", NULL, NULL },
763         { REG_OPEN_HKPT, "OpenHKPT", NULL, NULL },
764         { REG_OPEN_HKPN, "OpenHKPN", NULL, NULL },
765         { REG_QUERY_MULTIPLE_VALUES_2, "QueryMultipleValues2", NULL, NULL },
766         { 0, NULL, NULL,  NULL }
767 };
768
769 void
770 proto_register_dcerpc_reg(void)
771 {
772         static hf_register_info hf[] = {
773
774                 /* Global indexes */
775
776                 { &hf_hnd,
777                   { "Context handle", "reg.hnd", FT_BYTES, BASE_NONE,
778                     NULL, 0x0, "REG policy handle", HFILL }},
779
780                 { &hf_rc,
781                   { "Return code", "reg.rc", FT_UINT32, BASE_HEX,
782                     VALS(NT_errors), 0x0, "REG return code", HFILL }},
783
784                 { &hf_reg_opnum,
785                   { "Operation", "reg.opnum", FT_UINT16, BASE_DEC,
786                     NULL, 0x0, "Operation", HFILL }},
787
788                 { &hf_access_mask,
789                   { "Access mask", "reg.access_mask", FT_UINT32, BASE_HEX,
790                     NULL, 0x0, "Access mask", HFILL }},
791
792                 { &hf_keytype,
793                   { "Key type", "reg.type", FT_UINT32, BASE_DEC,
794                     VALS(reg_datatypes), 0x0, "Key type", HFILL }},
795
796                 { &hf_keydata,
797                   { "Key data", "reg.data", FT_BYTES, BASE_HEX,
798                     NULL, 0x0, "Key data", HFILL }},
799
800                 { &hf_offered,
801                   { "Offered", "reg.offered", FT_UINT32, BASE_DEC,
802                     NULL, 0x0, "Offered", HFILL }},
803
804                 { &hf_returned,
805                   { "Returned", "reg.returned", FT_UINT32, BASE_DEC,
806                     NULL, 0x0, "Returned", HFILL }},
807
808                 { &hf_reserved,
809                   { "Reserved", "reg.reserved", FT_UINT32, BASE_HEX,
810                     NULL, 0x0, "Reserved", HFILL }},
811
812                 { &hf_unknown,
813                   { "Unknown", "reg.unknown", FT_UINT32, BASE_HEX,
814                     NULL, 0x0, "Unknown", HFILL }},
815
816                 /* OpenHKLM */
817
818                 { &hf_openhklm_unknown1,
819                   { "Unknown 1", "reg.openhklm.unknown1", FT_UINT16, BASE_HEX,
820                     NULL, 0x0, "Unknown 1", HFILL }},
821
822                 { &hf_openhklm_unknown2,
823                   { "Unknown 2", "reg.openhklm.unknown2", FT_UINT16, BASE_HEX,
824                     NULL, 0x0, "Unknown 2", HFILL }},
825
826                 /* QueryClass */
827
828                 { &hf_querykey_class,
829                   { "Class", "reg.querykey.class", FT_STRING, BASE_NONE,
830                     NULL, 0, "Class", HFILL }},
831
832                 { &hf_querykey_num_subkeys,
833                   { "Num subkeys", "reg.querykey.num_subkeys", FT_UINT32, BASE_DEC,
834                     NULL, 0x0, "Num subkeys", HFILL }},
835
836                 { &hf_querykey_max_subkey_len,
837                   { "Max subkey len", "reg.querykey.max_subkey_len", FT_UINT32, BASE_DEC,
838                     NULL, 0x0, "Max subkey len", HFILL }},
839
840                 { &hf_querykey_reserved,
841                   { "Reserved", "reg.querykey.reserved", FT_UINT32, BASE_DEC,
842                     NULL, 0x0, "Reserved", HFILL }},
843
844                 { &hf_querykey_num_values,
845                   { "Num values", "reg.querykey.num_values", FT_UINT32, BASE_DEC,
846                     NULL, 0x0, "Num values", HFILL }},
847
848                 { &hf_querykey_max_valname_len,
849                   { "Max valnum len", "reg.querykey.max_valname_len", FT_UINT32, BASE_DEC,
850                     NULL, 0x0, "Max valname len", HFILL }},
851
852                 { &hf_querykey_max_valbuf_size,
853                   { "Max valbuf size", "reg.querykey.max_valbuf_size", FT_UINT32, BASE_DEC,
854                     NULL, 0x0, "Max valbuf size", HFILL }},
855
856                 { &hf_querykey_secdesc,
857                   { "Secdesc", "reg.querykey.secdesc", FT_UINT32, BASE_DEC,
858                     NULL, 0x0, "Secdesc", HFILL }},
859
860                 { &hf_querykey_modtime,
861                   { "Mod time", "reg.querykey.modtime", FT_ABSOLUTE_TIME, BASE_NONE,
862                     NULL, 0x0, "Secdesc", HFILL }},
863
864                 /* OpenKey */
865
866                 { &hf_keyname,
867                   { "Key name", "reg.keyname", FT_STRING, BASE_NONE,
868                     NULL, 0x0, "Keyname", HFILL }},
869
870                 { &hf_openkey_unknown1,
871                   { "Unknown 1", "reg.openkey.unknown1", FT_UINT32, BASE_HEX,
872                     NULL, 0x0, "Unknown 1", HFILL }},
873
874                 /* GetVersion */
875
876                 { &hf_getversion_version,
877                   { "Version", "reg.getversion.version", FT_UINT32, BASE_HEX,
878                     NULL, 0x0, "Version", HFILL }},
879
880                 /* Shutdown */
881                 { &hf_shutdown_message,
882                   { "Message", "reg.shutdown.message", FT_STRING, BASE_NONE,
883                     NULL, 0x0, "Message", HFILL }},
884
885                 { &hf_shutdown_seconds,
886                   { "Seconds", "reg.shutdown.seconds", FT_UINT32, BASE_DEC,
887                     NULL, 0x00, "Seconds", HFILL }},
888
889                 { &hf_shutdown_force,
890                   { "Force applications shut", "reg.shutdown.force", FT_UINT8,
891                     BASE_DEC, NULL, 0x00, "Force applications shut", HFILL }},
892
893                 { &hf_shutdown_reboot,
894                   { "Reboot", "reg.shutdown.reboot", FT_UINT8, BASE_DEC, 
895                     NULL, 0x00, "Reboot", HFILL }},
896
897                 { &hf_shutdown_server,
898                   { "Server", "reg.shutdown.server", FT_UINT16, BASE_HEX, 
899                     NULL, 0x00, "Server", HFILL }},
900
901                 { &hf_shutdown_reason,
902                   { "Reason", "reg.shutdown.reason", FT_UINT32, BASE_HEX,
903                     NULL, 0x00, "Reason", HFILL }}
904
905         };
906
907         static gint *ett[] = {
908                 &ett_dcerpc_reg
909         };
910
911         proto_dcerpc_reg = proto_register_protocol(
912                 "Microsoft Registry", "WINREG", "winreg");
913
914         proto_register_field_array(proto_dcerpc_reg, hf, array_length(hf));
915
916         proto_register_subtree_array(ett, array_length(ett));
917 }
918
919 void
920 proto_reg_handoff_dcerpc_reg(void)
921 {
922         /* Register protocol as dcerpc */
923
924         dcerpc_init_uuid(proto_dcerpc_reg, ett_dcerpc_reg, &uuid_dcerpc_reg,
925                          ver_dcerpc_reg, dcerpc_reg_dissectors, hf_reg_opnum);
926 }