Windows Registry patch

Jeremy Cooper jeremy at ncircle.com
Tue Jun 29 23:17:47 GMT 2004


Attached is a patch against Samba 3.0.4's RPC code which makes it possible
to interact with the Windows registry.  Most of this code is in
rpc_client/cli_reg.c and rpc_parse/parse_reg.c and came from the Samba-TNG
project.

It has been modified to fit the current Samba project style, mostly in
that all the RPC functions return NT error codes, and they all allocate
memory from memory pool handles (TALLOC_CTX).

This patch does not include any corresponding hooks to the rpcclient CLI,
but they should not be hard to write.  I have tested this code with a CLI
of my own that I am using for another project and it seems to work well.

If you have any questions please feel free to contact me at this e-mail
address.

Thank you,
Jeremy Cooper
-------------- next part --------------
--- source/include/rpc_reg.h	2004/06/18 17:39:19	1.1.1.1
+++ source/include/rpc_reg.h	2004/06/29 22:38:49
@@ -28,34 +28,34 @@
 /* winreg pipe defines 
    NOT IMPLEMENTED !!
 #define _REG_UNK_01		0x01
-#define _REG_UNK_03		0x03
-#define REG_CREATE_KEY		0x06
-#define REG_DELETE_KEY		0x07
-#define REG_DELETE_VALUE	0x08
-#define REG_FLUSH_KEY		0x0b
-#define REG_GET_KEY_SEC		0x0c
 #define	_REG_UNK_0D		0x0d
 #define _REG_UNK_0E		0x0e
 #define	_REG_UNK_12		0x12
 #define _REG_UNK_13		0x13
-#define REG_SET_KEY_SEC		0x15
-#define REG_CREATE_VALUE	0x16
 #define	_REG_UNK_17		0x17
 */
 
 /* Implemented */
 #define REG_OPEN_HKCR		0x00
 #define REG_OPEN_HKLM		0x02
+#define REG_OPEN_HKPD		0x03
 #define REG_OPEN_HKU		0x04
 #define REG_CLOSE		0x05
+#define REG_CREATE_KEY		0x06
+#define REG_DELETE_KEY		0x07
+#define REG_DELETE_VALUE	0x08
 #define REG_ENUM_KEY		0x09
 #define REG_ENUM_VALUE		0x0a
+#define REG_FLUSH_KEY		0x0b
+#define REG_GET_KEY_SEC		0x0c
 #define REG_OPEN_ENTRY		0x0f
 #define REG_QUERY_KEY		0x10
 #define REG_INFO		0x11
+#define REG_SAVE_KEY		0x14	/* no idea what the real name is */
+#define REG_SET_KEY_SEC		0x15
+#define REG_CREATE_VALUE	0x16
 #define REG_SHUTDOWN		0x18
 #define REG_ABORT_SHUTDOWN	0x19
-#define	REG_SAVE_KEY		0x14	/* no idea what the real name is */
 #define REG_UNKNOWN_1A		0x1a
 
 
@@ -63,6 +63,7 @@
 #define HKEY_CURRENT_USER	0x80000001
 #define HKEY_LOCAL_MACHINE 	0x80000002
 #define HKEY_USERS         	0x80000003
+#define HKEY_PERFORMANCE_DATA	0x80000004
 
 #define KEY_HKLM	"HKLM"
 #define KEY_HKU		"HKU"
@@ -144,64 +145,23 @@
 } REGISTRY_KEY;
 
 
-/* REG_Q_OPEN_HKCR   */
-typedef struct q_reg_open_hkcr_info
+/* REG_Q_OPEN_HIVE   */
+typedef struct q_reg_open_hive_info
 {
 	uint32 ptr;
-	uint16 unknown_0; /* 0x5428      - 16 bit unknown */
+	uint16 unknown_0; /* varies depending on hive */
 	uint16 unknown_1; /* random.  changes */
-	uint32 level;     /* 0x0000 0002 - 32 bit unknown */
+	uint32 level;
 
-} REG_Q_OPEN_HKCR  ;
+} REG_Q_OPEN_HIVE  ;
 
-/* REG_R_OPEN_HKCR   */
-typedef struct r_reg_open_hkcr_info
+/* REG_R_OPEN_HIVE   */
+typedef struct r_reg_open_hive_info
 {
 	POLICY_HND pol;       /* policy handle */
 	NTSTATUS status;         /* return status */
-
-} REG_R_OPEN_HKCR;
-
-
-/* REG_Q_OPEN_HKLM   */
-typedef struct q_reg_open_hklm_info
-{
-	uint32 ptr;
-	uint16 unknown_0;	/* 0xE084      - 16 bit unknown */
-	uint16 unknown_1;	/* random.  changes */
-	uint32 access_mask;
-
-}
-REG_Q_OPEN_HKLM;
-
-/* REG_R_OPEN_HKLM   */
-typedef struct r_reg_open_hklm_info
-{
-	POLICY_HND pol;		/* policy handle */
-	NTSTATUS status;		/* return status */
-
-}
-REG_R_OPEN_HKLM;
-
-
-/* REG_Q_OPEN_HKU */
-typedef struct q_reg_open_hku_info
-{
-	uint32 ptr;
-	uint16 unknown_0; 
-	uint16 unknown_1; 
-	uint32 access_mask;    
-
-} REG_Q_OPEN_HKU;
-
-/* REG_R_OPEN_HKU */
-typedef struct r_reg_open_hku_info
-{
-	POLICY_HND pol;      /* policy handle */
-	NTSTATUS status;     /* return status */
-
-} REG_R_OPEN_HKU;
 
+} REG_R_OPEN_HIVE;
 
 /* REG_Q_FLUSH_KEY */
 typedef struct q_reg_open_flush_key_info
--- source/lib/util.c	2004/06/18 17:39:19	1.1.1.1
+++ source/lib/util.c	2004/06/29 22:38:49
@@ -2041,7 +2041,11 @@
 
 	if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
 		(*reg_type) = HKEY_LOCAL_MACHINE;
+	else if (strequal(tmp, "HKCR") || strequal(tmp, "HKEY_CLASSES_ROOT"))
+		(*reg_type) = HKEY_USERS;
 	else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
+		(*reg_type) = HKEY_USERS;
+	else if (strequal(tmp, "HKPD")||strequal(tmp, "HKEY_PERFORMANCE_DATA"))
 		(*reg_type) = HKEY_USERS;
 	else {
 		DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
--- source/lib/util_sock.c	2004/06/18 17:39:19	1.1.1.1
+++ source/lib/util_sock.c	2004/06/25 02:53:10	1.3
@@ -726,6 +726,9 @@
 	memset((char *)&sock_out,'\0',sizeof(sock_out));
 	putip((char *)&sock_out.sin_addr,(char *)addr);
   
+#ifdef HAVE_SOCK_SIN_LEN
+	sock_out.sin_len = sizeof(sock_out);
+#endif
 	sock_out.sin_port = htons( port );
 	sock_out.sin_family = PF_INET;
 
--- source/lib/util_unistr.c	2004/06/18 17:39:19	1.1.1.1
+++ source/lib/util_unistr.c	2004/06/29 22:38:49
@@ -283,6 +283,19 @@
 }
 
 /*******************************************************************
+ Convert a (little-endian) UNISTR3 structure to an ASCII string
+********************************************************************/
+void unistr3_to_ascii(char *dest, const UNISTR3 *str, size_t maxlen)
+{
+	if (str == NULL) {
+		*dest='\0';
+		return;
+	}
+	pull_ucs2(NULL, dest, str->str.buffer, maxlen, str->uni_str_len*2,
+	          STR_NOALIGN);
+}
+	
+/*******************************************************************
 give a static string for displaying a UNISTR2
 ********************************************************************/
 const char *unistr2_static(const UNISTR2 *str)
--- source/rpc_client/cli_reg.c	2004/06/18 17:39:21	1.1.1.1
+++ source/rpc_client/cli_reg.c	2004/06/24 23:22:11	1.3
@@ -2,11 +2,12 @@
    Unix SMB/CIFS implementation.
    RPC Pipe client
  
-   Copyright (C) Andrew Tridgell              1992-1998,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
-   Copyright (C) Paul Ashton                  1997-1998.
+   Copyright (C) Andrew Tridgell              1992-2000,
+   Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
+   Copyright (C) Paul Ashton                  1997-2000.
    Copyright (C) Jeremy Allison                    1999.
    Copyright (C) Simo Sorce                        2001
+   Copyright (C) nCircle Network Security, Inc.    2004
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -25,6 +26,11 @@
 
 #include "includes.h"
 
+static NTSTATUS cli_reg_open_hive_int(struct cli_state *cli,
+                                      TALLOC_CTX *mem_ctx, uint16 op_code,
+                                      const char *op_name, uint16 unknown_0,
+                                      uint32 access_mask, POLICY_HND *hnd);
+
 /* Shutdown a server */
 
 NTSTATUS cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx,
@@ -90,7 +96,7 @@
 	    !rpc_api_pipe_req(cli, REG_ABORT_SHUTDOWN, &qbuf, &rbuf))
 	    	goto done;
 	
-		/* Unmarshall response */
+	/* Unmarshall response */
 	
 	if (reg_io_r_abort_shutdown("", &r_s, &rbuf, 0))
 		result = r_s.status;
@@ -98,6 +104,741 @@
 done:
 	prs_mem_free(&rbuf);
 	prs_mem_free(&qbuf );
+
+	return result;
+}
+
+/* connect to a registry hive root (open a registry policy) */
+
+NTSTATUS cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                         uint32 reg_type, uint32 access_mask,
+                         POLICY_HND *reg_hnd)
+{
+	uint16 unknown_0;
+	uint16 op_code;
+	const char *op_name;
+
+	ZERO_STRUCTP(reg_hnd);
+
+	switch (reg_type)
+	{
+	case HKEY_CLASSES_ROOT:
+		op_code = REG_OPEN_HKCR;
+		op_name = "REG_OPEN_HKCR";
+		unknown_0 = 0x5428;
+		break;
+	case HKEY_LOCAL_MACHINE:
+		op_code = REG_OPEN_HKLM;
+		op_name = "REG_OPEN_HKLM";
+		unknown_0 = 0x84e0;
+		break;
+	case HKEY_USERS:
+		op_code = REG_OPEN_HKU;
+		op_name = "REG_OPEN_HKU";
+		unknown_0 = 0x84e0;
+		break;
+	case HKEY_PERFORMANCE_DATA:
+		op_code = REG_OPEN_HKPD;
+		op_name = "REG_OPEN_HKPD";
+		unknown_0 = 0x86e8;
+		break;
+	default:
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	return cli_reg_open_hive_int(cli, mem_ctx, op_code, op_name, unknown_0,
+                                     access_mask, reg_hnd);
+}
+
+/****************************************************************************
+do a REG Unknown 0xB command.  sent after a create key or create value.
+this might be some sort of "sync" or "refresh" command, sent after
+modification of the registry...
+****************************************************************************/
+NTSTATUS cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                           POLICY_HND *hnd)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_FLUSH_KEY q_o;
+	REG_R_FLUSH_KEY r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_flush_key(&q_o, hnd);
+
+	if (!reg_io_q_flush_key("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_FLUSH_KEY, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (reg_io_r_flush_key("", &r_o, &rbuf, 0))
+		result = r_o.status;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Query Key
+****************************************************************************/
+NTSTATUS cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                           POLICY_HND *hnd,
+                           char *key_class, uint32 *class_len,
+                           uint32 *num_subkeys, uint32 *max_subkeylen,
+                           uint32 *max_classlen, uint32 *num_values,
+                           uint32 *max_valnamelen, uint32 *max_valbufsize,
+                           uint32 *sec_desc, NTTIME *mod_time)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_QUERY_KEY q_o;
+	REG_R_QUERY_KEY r_o;
+	UNISTR2 class_uni2;
+	uint32 saved_class_len = *class_len;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	/*
+	 * Construct a temporary UNISTR2 structure just to communicate
+	 * the maximum desired return size for the key class.
+	 */
+	class_uni2.uni_str_len = 0;
+	class_uni2.uni_max_len = *class_len;
+
+	init_reg_q_query_key(&q_o, hnd, &class_uni2);
+
+	if (!reg_io_q_query_key("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_QUERY_KEY, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (!reg_io_r_query_key("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_EQUAL(result, ERROR_INSUFFICIENT_BUFFER)) {
+		*class_len = r_o.hdr_class.uni_max_len;
+		goto done;
+	} else if (!NT_STATUS_IS_OK(result))
+		goto done;
+
+	*class_len      = r_o.hdr_class.uni_max_len;
+	unistr2_to_ascii(key_class, &r_o.uni_class, saved_class_len-1);
+	*num_subkeys    = r_o.num_subkeys   ;
+	*max_subkeylen  = r_o.max_subkeylen ;
+	*num_values     = r_o.num_values    ;
+	*max_valnamelen = r_o.max_valnamelen;
+	*max_valbufsize = r_o.max_valbufsize;
+	*sec_desc       = r_o.sec_desc      ;
+	*mod_time       = r_o.mod_time      ;
+	/* Maybe: *max_classlen = r_o.reserved; */
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Unknown 1A
+****************************************************************************/
+NTSTATUS cli_reg_unknown_1a(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *hnd, uint32 *unk)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_UNKNOWN_1A q_o;
+	REG_R_UNKNOWN_1A r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_unknown_1a(&q_o, hnd);
+
+	if (!reg_io_q_unknown_1a("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_UNKNOWN_1A, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (!reg_io_r_unknown_1a("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result))
+		if (unk != NULL)
+			*unk = r_o.unknown;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Query Info
+****************************************************************************/
+NTSTATUS cli_reg_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                           POLICY_HND *hnd, const char *val_name,
+                           uint32 *type, BUFFER2 *buffer)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_INFO q_o;
+	REG_R_INFO r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_info(&q_o, hnd, val_name, buffer);
+
+	if (!reg_io_q_info("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_INFO, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	r_o.uni_val = *buffer;
+	if (!reg_io_r_info("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result)) {
+		*type = r_o.type;
+		*buffer = r_o.uni_val;
+	}
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Set Key Security 
+****************************************************************************/
+NTSTATUS cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                             POLICY_HND *hnd, uint32 sec_info,
+                             size_t sec_desc_size, SEC_DESC *sec_desc)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_SET_KEY_SEC q_o;
+	REG_R_SET_KEY_SEC r_o;
+	SEC_DESC_BUF *sec_desc_buf;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	/*
+	 * Flatten the security descriptor.
+	 */
+	sec_desc_buf = make_sec_desc_buf(mem_ctx, sec_desc_size, sec_desc);
+	if (sec_desc_buf == NULL)
+		goto done;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_set_key_sec(&q_o, hnd, sec_info, sec_desc_buf);
+
+	if (!reg_io_q_set_key_sec("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_SET_KEY_SEC, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (reg_io_r_set_key_sec("", &r_o, &rbuf, 0))
+		result = r_o.status;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+
+/****************************************************************************
+do a REG Query Key Security 
+****************************************************************************/
+NTSTATUS cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                             POLICY_HND *hnd, uint32 sec_info,
+                             uint32 *sec_buf_size, SEC_DESC_BUF *sec_buf)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_GET_KEY_SEC q_o;
+	REG_R_GET_KEY_SEC r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_get_key_sec(&q_o, hnd, sec_info, *sec_buf_size, sec_buf);
+
+	if (!reg_io_q_get_key_sec("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_GET_KEY_SEC, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	r_o.data = sec_buf;
+
+	if (*sec_buf_size != 0)
+	{
+		sec_buf->sec = (SEC_DESC*)talloc(mem_ctx, *sec_buf_size);
+	}
+
+	if (!reg_io_r_get_key_sec("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result))
+		(*sec_buf_size) = r_o.data->len;
+	else if (NT_STATUS_EQUAL(result, ERROR_INSUFFICIENT_BUFFER)) 
+	{
+		/*
+		 * get the maximum buffer size: it was too small
+		 */
+		(*sec_buf_size) = r_o.hdr_sec.buf_max_len;
+	}
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Delete Value
+****************************************************************************/
+NTSTATUS cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *hnd, char *val_name)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_DELETE_VALUE q_o;
+	REG_R_DELETE_VALUE r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_delete_val(&q_o, hnd, val_name);
+
+	if (!reg_io_q_delete_val("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_DELETE_VALUE, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (reg_io_r_delete_val("", &r_o, &rbuf, 0))
+		result = r_o.status;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Delete Key
+****************************************************************************/
+NTSTATUS cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *hnd, char *key_name)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_DELETE_KEY q_o;
+	REG_R_DELETE_KEY r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_delete_key(&q_o, hnd, key_name);
+
+	if (!reg_io_q_delete_key("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_DELETE_KEY, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (reg_io_r_delete_key("", &r_o, &rbuf, 0))
+		result = r_o.status;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Create Key
+****************************************************************************/
+NTSTATUS cli_reg_create_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *hnd, char *key_name, char *key_class,
+                            SEC_ACCESS *sam_access, POLICY_HND *key)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_CREATE_KEY q_o;
+	REG_R_CREATE_KEY r_o;
+	SEC_DESC *sec;
+	SEC_DESC_BUF *sec_buf;
+	size_t sec_len;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	ZERO_STRUCT(q_o);
+
+	if ((sec = make_sec_desc(mem_ctx, 1, SEC_DESC_SELF_RELATIVE,
+	                         NULL, NULL, NULL, NULL, &sec_len)) == NULL)
+		goto done;
+
+	if ((sec_buf = make_sec_desc_buf(mem_ctx, sec_len, sec)) == NULL)
+		goto done;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_create_key(&q_o, hnd, key_name, key_class, sam_access,
+	                      sec_buf);
+
+	if (!reg_io_q_create_key("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_CREATE_KEY, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (!reg_io_r_create_key("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result))
+		*key = r_o.key_pol;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Enum Key
+****************************************************************************/
+NTSTATUS cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                          POLICY_HND *hnd, int key_index, fstring key_name,
+                          uint32 *unk_1, uint32 *unk_2, time_t *mod_time)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_ENUM_KEY q_o;
+	REG_R_ENUM_KEY r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_enum_key(&q_o, hnd, key_index);
+
+	if (!reg_io_q_enum_key("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_ENUM_KEY, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshall response */
+
+	if (!reg_io_r_enum_key("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result)) {
+		(*unk_1) = r_o.unknown_1;
+		(*unk_2) = r_o.unknown_2;
+		unistr3_to_ascii(key_name, &r_o.key_name,
+		                sizeof(fstring)-1);
+		(*mod_time) = nt_time_to_unix(&r_o.time);
+	}
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Create Value
+****************************************************************************/
+NTSTATUS cli_reg_create_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *hnd, char *val_name, uint32 type,
+                            BUFFER3 *data)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_CREATE_VALUE q_o;
+	REG_R_CREATE_VALUE r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_create_val(&q_o, hnd, val_name, type, data);
+
+	if (!reg_io_q_create_val("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_CREATE_VALUE, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarshal response */
+
+	if (reg_io_r_create_val("", &r_o, &rbuf, 0))
+		result = r_o.status;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Enum Value
+****************************************************************************/
+NTSTATUS cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                          POLICY_HND *hnd, int val_index, int max_valnamelen,
+                          int max_valbufsize, fstring val_name,
+                          uint32 *val_type, BUFFER2 *value)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_ENUM_VALUE q_o;
+	REG_R_ENUM_VALUE r_o;
+	UNISTR2 value_name_uni2;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/*
+	 * Construct a temporary UNISTR2 structure just to communicate
+	 * the maximum desired return size for the value name.
+	 */
+	value_name_uni2.uni_str_len = 0;
+	value_name_uni2.uni_max_len = sizeof(fstring);
+
+	/* Marshall data and send request */
+
+	init_reg_q_enum_val(&q_o, hnd, val_index, &value_name_uni2,
+	                    max_valbufsize);
+
+	if (!reg_io_q_enum_val("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_ENUM_VALUE, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+	r_o.buf_value = *value;
+
+	/* Unmarshall response */
+
+	if (!reg_io_r_enum_val("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result) ||
+	    NT_STATUS_EQUAL(result, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+		(*val_type) = r_o.type;
+		unistr2_to_ascii(val_name, &r_o.uni_name, sizeof(fstring)-1);
+		*value = r_o.buf_value;
+	}
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Open Key
+****************************************************************************/
+NTSTATUS cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                            POLICY_HND *hnd, char *key_name,
+                            uint32 access_desired, POLICY_HND *key_hnd)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_OPEN_ENTRY q_o;
+	REG_R_OPEN_ENTRY r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_open_entry(&q_o, hnd, key_name, access_desired);
+
+	/* turn parameters into data stream */
+	if (!reg_io_q_open_entry("", &q_o, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_OPEN_ENTRY, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_o);
+
+	/* Unmarsall response */
+
+	if (!reg_io_r_open_entry("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result))
+		*key_hnd = r_o.pol;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/****************************************************************************
+do a REG Close
+****************************************************************************/
+NTSTATUS cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                       POLICY_HND *hnd)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_CLOSE q_c;
+	REG_R_CLOSE r_c;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	/* Marshall data and send request */
+
+	init_reg_q_close(&q_c, hnd);
+
+	if (!reg_io_q_close("", &q_c, &qbuf, 0) ||
+	    !rpc_api_pipe_req(cli, REG_CLOSE, &qbuf, &rbuf))
+		goto done;
+
+	ZERO_STRUCT(r_c);
+
+	/* Unmarshall response */
+
+	if (reg_io_r_close("", &r_c, &rbuf, 0))
+		result = r_c.status;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
+
+	return result;
+}
+
+/* internal connect to a registry hive root (open a registry policy) */
+
+static NTSTATUS cli_reg_open_hive_int(struct cli_state *cli,
+                                      TALLOC_CTX *mem_ctx, uint16 op_code,
+                                      const char *op_name, uint16 unknown_0,
+                                      uint32 access_mask, POLICY_HND *hnd)
+{
+	prs_struct rbuf;
+	prs_struct qbuf; 
+	REG_Q_OPEN_HIVE q_o;
+	REG_R_OPEN_HIVE r_o;
+	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+	ZERO_STRUCT(q_o);
+	ZERO_STRUCT(r_o);
+
+	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	init_reg_q_open_hive(&q_o, unknown_0, access_mask);
+
+	/* Marshall the query parameters */
+	if (!reg_io_q_open_hive("", &q_o, &qbuf, 0))
+		goto done;
+
+	/* Send the request, receive the response */
+	if (!rpc_api_pipe_req(cli, op_code, &qbuf, &rbuf))
+		goto done;
+
+	/* Unmarshall the response */
+	if (!reg_io_r_open_hive("", &r_o, &rbuf, 0))
+		goto done;
+
+	result = r_o.status;
+	if (NT_STATUS_IS_OK(result))
+		*hnd = r_o.pol;
+
+done:
+	prs_mem_free(&rbuf);
+	prs_mem_free(&qbuf);
 
 	return result;
 }
--- source/rpc_parse/parse_reg.c	2004/06/18 17:39:21	1.1.1.1
+++ source/rpc_parse/parse_reg.c	2004/06/24 23:23:33	1.3
@@ -46,11 +46,10 @@
 }
 
 /*******************************************************************
- Inits a structure.
+ Inits a hive connect request structure
 ********************************************************************/
 
-void init_reg_q_open_hkcr(REG_Q_OPEN_HKCR *q_o,
-				uint16 unknown_0, uint32 level)
+void init_reg_q_open_hive(REG_Q_OPEN_HIVE *q_o, uint16 unknown_0, uint32 level)
 {
 	q_o->ptr = 1;
 	q_o->unknown_0 = unknown_0;
@@ -59,15 +58,13 @@
 }
 
 /*******************************************************************
-reads or writes a structure.
+Marshalls a hive connect request
 ********************************************************************/
 
-BOOL reg_io_q_open_hkcr(const char *desc,  REG_Q_OPEN_HKCR *r_q, prs_struct *ps, int depth)
+BOOL reg_io_q_open_hive(const char *desc, REG_Q_OPEN_HIVE *r_q,
+                        prs_struct *ps, int depth)
 {
-	if (r_q == NULL)
-		return False;
-
-	prs_debug(ps, depth, desc, "reg_io_q_open_hkcr");
+	prs_debug(ps, depth, desc, "reg_io_q_open_hive");
 	depth++;
 
 	if(!prs_align(ps))
@@ -90,15 +87,16 @@
 
 
 /*******************************************************************
-reads or writes a structure.
+Unmarshalls a hive connect response
 ********************************************************************/
 
-BOOL reg_io_r_open_hkcr(const char *desc,  REG_R_OPEN_HKCR *r_r, prs_struct *ps, int depth)
+BOOL reg_io_r_open_hive(const char *desc,  REG_R_OPEN_HIVE *r_r,
+                        prs_struct *ps, int depth)
 {
 	if (r_r == NULL)
 		return False;
 
-	prs_debug(ps, depth, desc, "reg_io_r_open_hkcr");
+	prs_debug(ps, depth, desc, "reg_io_r_open_hive");
 	depth++;
 
 	if(!prs_align(ps))
@@ -114,91 +112,20 @@
 }
 
 /*******************************************************************
- Inits a structure.
+Inits a registry key flush request structure
 ********************************************************************/
 
-void init_reg_q_open_hklm(REG_Q_OPEN_HKLM * q_o,
-			  uint16 unknown_0, uint32 access_mask)
-{
-	q_o->ptr = 1;
-	q_o->unknown_0 = unknown_0;
-	q_o->unknown_1 = 0x0;	/* random - changes */
-	q_o->access_mask = access_mask;
-
-}
-
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-BOOL reg_io_q_open_hklm(const char *desc, REG_Q_OPEN_HKLM * r_q, prs_struct *ps,
-			int depth)
-{
-	if (r_q == NULL)
-		return False;
-
-	prs_debug(ps, depth, desc, "reg_io_q_open_hklm");
-	depth++;
-
-	if (!prs_align(ps))
-		return False;
-
-	if (!prs_uint32("ptr      ", ps, depth, &(r_q->ptr)))
-		return False;
-	if (r_q->ptr != 0)
-	{
-		if (!prs_uint16("unknown_0", ps, depth, &(r_q->unknown_0)))
-			return False;
-		if (!prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1)))
-			return False;
-		if (!prs_uint32("access_mask", ps, depth, &(r_q->access_mask)))
-			return False;
-	}
-
-	return True;
-}
-
-
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-BOOL reg_io_r_open_hklm(const char *desc, REG_R_OPEN_HKLM * r_r, prs_struct *ps,
-			int depth)
-{
-	if (r_r == NULL)
-		return False;
-
-	prs_debug(ps, depth, desc, "reg_io_r_open_hklm");
-	depth++;
-
-	if (!prs_align(ps))
-		return False;
-
-	if (!smb_io_pol_hnd("", &r_r->pol, ps, depth))
-		return False;
-
-	if (!prs_ntstatus("status", ps, depth, &r_r->status))
-		return False;
-
-	return True;
-}
-
-
-
-
-/*******************************************************************
- Inits a structure.
-********************************************************************/
-
 void init_reg_q_flush_key(REG_Q_FLUSH_KEY *q_u, POLICY_HND *pol)
 {
 	memcpy(&q_u->pol, pol, sizeof(q_u->pol));
 }
 
 /*******************************************************************
-reads or writes a structure.
+Marshalls a registry key flush request
 ********************************************************************/
 
-BOOL reg_io_q_flush_key(const char *desc,  REG_Q_FLUSH_KEY *r_q, prs_struct *ps, int depth)
+BOOL reg_io_q_flush_key(const char *desc,  REG_Q_FLUSH_KEY *r_q,
+                        prs_struct *ps, int depth)
 {
 	if (r_q == NULL)
 		return False;
@@ -216,10 +143,11 @@
 }
 
 /*******************************************************************
-reads or writes a structure.
+Unmarshalls a registry key flush response
 ********************************************************************/
 
-BOOL reg_io_r_flush_key(const char *desc,  REG_R_FLUSH_KEY *r_r, prs_struct *ps, int depth)
+BOOL reg_io_r_flush_key(const char *desc,  REG_R_FLUSH_KEY *r_r,
+                        prs_struct *ps, int depth)
 {
 	if (r_r == NULL)
 		return False;
@@ -240,12 +168,14 @@
 reads or writes SEC_DESC_BUF and SEC_DATA structures.
 ********************************************************************/
 
-static BOOL reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec, SEC_DESC_BUF *data, prs_struct *ps, int depth)
+static BOOL reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec,
+                              SEC_DESC_BUF *data, prs_struct *ps, int depth)
 {
 	if (ptr != 0) {
 		uint32 hdr_offset;
 		uint32 old_offset;
-		if(!smb_io_hdrbuf_pre("hdr_sec", hdr_sec, ps, depth, &hdr_offset))
+		if(!smb_io_hdrbuf_pre("hdr_sec", hdr_sec, ps, depth,
+		                      &hdr_offset))
 			return False;
 
 		old_offset = prs_offset(ps);
@@ -256,14 +186,16 @@
 		}
 
 		if (ptr3 == NULL || *ptr3 != 0) {
-			if(!sec_io_desc_buf("data   ", &data, ps, depth)) /* JRA - this line is probably wrong... */
+ 			/* JRA - this next line is probably wrong... */
+			if(!sec_io_desc_buf("data   ", &data, ps, depth))
 				return False;
 		}
 
-		if(!smb_io_hdrbuf_post("hdr_sec", hdr_sec, ps, depth, hdr_offset,
-		                   data->max_len, data->len))
+		if(!smb_io_hdrbuf_post("hdr_sec", hdr_sec, ps, depth,
+		                       hdr_offset, data->max_len, data->len))
 				return False;
-		if(!prs_set_offset(ps, old_offset + data->len + sizeof(uint32) * ((ptr3 != NULL) ? 5 : 3)))
+		if(!prs_set_offset(ps, old_offset + data->len +
+		                       sizeof(uint32) * ((ptr3 != NULL) ? 5 : 3)))
 			return False;
 
 		if(!prs_align(ps))
@@ -274,12 +206,12 @@
 }
 
 /*******************************************************************
- Inits a structure.
+ Inits a registry key create request
 ********************************************************************/
 
 void init_reg_q_create_key(REG_Q_CREATE_KEY *q_c, POLICY_HND *hnd,
-				char *name, char *class, SEC_ACCESS *sam_access,
-				SEC_DESC_BUF *sec_buf)
+                           char *name, char *class, SEC_ACCESS *sam_access,
+                           SEC_DESC_BUF *sec_buf)
 {
 	ZERO_STRUCTP(q_c);
 
@@ -305,10 +237,11 @@
 }
 
 /*******************************************************************
-reads or writes a structure.
+Marshalls a registry key create request
 ********************************************************************/
 
-BOOL reg_io_q_create_key(const char *desc,  REG_Q_CREATE_KEY *r_q, prs_struct *ps, int depth)
+BOOL reg_io_q_create_key(const char *desc,  REG_Q_CREATE_KEY *r_q,
+                         prs_struct *ps, int depth)
 {
 	if (r_q == NULL)
 		return False;
@@ -331,7 +264,8 @@
 
 	if(!smb_io_unihdr ("", &r_q->hdr_class, ps, depth))
 		return False;
-	if(!smb_io_unistr2("", &r_q->uni_class, r_q->hdr_class.buffer, ps, depth))
+	if(!smb_io_unistr2("", &r_q->uni_class, r_q->hdr_class.buffer, ps,
+	                   depth))
 		return False;
 	if(!prs_align(ps))
 		return False;
@@ -351,7 +285,8 @@
 
 	if(!prs_uint32("ptr2", ps, depth, &r_q->ptr2))
 		return False;
-	if(!reg_io_hdrbuf_sec(r_q->ptr2, &r_q->ptr3, &r_q->hdr_sec, r_q->data, ps, depth))
+	if(!reg_io_hdrbuf_sec(r_q->ptr2, &r_q->ptr3, &r_q->hdr_sec, r_q->data,
+	                      ps, depth))
 		return False;
 
 	if(!prs_uint32("unknown_2", ps, depth, &r_q->unknown_2))
@@ -361,10 +296,11 @@
 }
 
 /*******************************************************************
-reads or writes a structure.
+Unmarshalls a registry key create response
 ********************************************************************/
 
-BOOL reg_io_r_create_key(const char *desc,  REG_R_CREATE_KEY *r_r, prs_struct *ps, int depth)
+BOOL reg_io_r_create_key(const char *desc,  REG_R_CREATE_KEY *r_r,
+                         prs_struct *ps, int depth)
 {
 	if (r_r == NULL)
 		return False;
@@ -392,7 +328,7 @@
 ********************************************************************/
 
 void init_reg_q_delete_val(REG_Q_DELETE_VALUE *q_c, POLICY_HND *hnd,
-				char *name)
+                           char *name)
 {
 	ZERO_STRUCTP(q_c);
 
@@ -406,7 +342,8 @@
 reads or writes a structure.
 ********************************************************************/
 
-BOOL reg_io_q_delete_val(const char *desc,  REG_Q_DELETE_VALUE *r_q, prs_struct *ps, int depth)
+BOOL reg_io_q_delete_val(const char *desc, REG_Q_DELETE_VALUE *r_q,
+                         prs_struct *ps, int depth)
 {
 	if (r_q == NULL)
 		return False;
@@ -435,7 +372,8 @@
 reads or writes a structure.
 ********************************************************************/
 
-BOOL reg_io_r_delete_val(const char *desc,  REG_R_DELETE_VALUE *r_r, prs_struct *ps, int depth)
+BOOL reg_io_r_delete_val(const char *desc,  REG_R_DELETE_VALUE *r_r,
+                         prs_struct *ps, int depth)
 {
 	if (r_r == NULL)
 		return False;
@@ -457,7 +395,7 @@
 ********************************************************************/
 
 void init_reg_q_delete_key(REG_Q_DELETE_KEY *q_c, POLICY_HND *hnd,
-				char *name)
+                           char *name)
 {
 	ZERO_STRUCTP(q_c);
 
@@ -471,7 +409,8 @@
 reads or writes a structure.
 ********************************************************************/
 
-BOOL reg_io_q_delete_key(const char *desc,  REG_Q_DELETE_KEY *r_q, prs_struct *ps, int depth)
+BOOL reg_io_q_delete_key(const char *desc,  REG_Q_DELETE_KEY *r_q,
+                         prs_struct *ps, int depth)
 {
 	if (r_q == NULL)
 		return False;
@@ -709,72 +648,6 @@
 }
 
 /*******************************************************************
- Inits a structure.
-********************************************************************/
-
-void init_reg_q_open_hku(REG_Q_OPEN_HKU *q_o,
-				uint16 unknown_0, uint32 access_mask)
-{
-	q_o->ptr = 1;
-	q_o->unknown_0 = unknown_0;
-	q_o->unknown_1 = 0x0; /* random - changes */
-	q_o->access_mask = access_mask;
-}
-
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-
-BOOL reg_io_q_open_hku(const char *desc,  REG_Q_OPEN_HKU *r_q, prs_struct *ps, int depth)
-{
-	if (r_q == NULL)
-		return False;
-
-	prs_debug(ps, depth, desc, "reg_io_q_open_hku");
-	depth++;
-
-	if(!prs_align(ps))
-		return False;
-	
-	if(!prs_uint32("ptr      ", ps, depth, &r_q->ptr))
-		return False;
-	if (r_q->ptr != 0) {
-		if(!prs_uint16("unknown_0   ", ps, depth, &r_q->unknown_0))
-			return False;
-		if(!prs_uint16("unknown_1   ", ps, depth, &r_q->unknown_1))
-			return False;
-		if(!prs_uint32("access_mask ", ps, depth, &r_q->access_mask))
-			return False;
-	}
-
-	return True;
-}
-
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-
-BOOL reg_io_r_open_hku(const char *desc,  REG_R_OPEN_HKU *r_r, prs_struct *ps, int depth)
-{
-	if (r_r == NULL)
-		return False;
-
-	prs_debug(ps, depth, desc, "reg_io_r_open_hku");
-	depth++;
-
-	if(!prs_align(ps))
-		return False;
-	
-	if(!smb_io_pol_hnd("", &r_r->pol, ps, depth))
-		return False;
-
-	if(!prs_ntstatus("status", ps, depth, &r_r->status))
-		return False;
-
-	return True;
-}
-
-/*******************************************************************
  Inits an REG_Q_CLOSE structure.
 ********************************************************************/
 
@@ -838,11 +711,12 @@
 makes a structure.
 ********************************************************************/
 
-void init_reg_q_set_key_sec(REG_Q_SET_KEY_SEC *q_i, POLICY_HND *pol, SEC_DESC_BUF *sec_desc_buf)
+void init_reg_q_set_key_sec(REG_Q_SET_KEY_SEC *q_i, POLICY_HND *pol,
+                            uint32 sec_info, SEC_DESC_BUF *sec_desc_buf)
 {
 	memcpy(&q_i->pol, pol, sizeof(q_i->pol));
 
-	q_i->sec_info = DACL_SECURITY_INFORMATION;
+	q_i->sec_info = sec_info;
 
 	q_i->ptr = 1;
 	init_buf_hdr(&q_i->hdr_sec, sec_desc_buf->len, sec_desc_buf->len);
@@ -905,13 +779,12 @@
 ********************************************************************/
 
 void init_reg_q_get_key_sec(REG_Q_GET_KEY_SEC *q_i, POLICY_HND *pol, 
-				uint32 sec_buf_size, SEC_DESC_BUF *psdb)
+                            uint32 sec_info, uint32 sec_buf_size,
+                            SEC_DESC_BUF *psdb)
 {
 	memcpy(&q_i->pol, pol, sizeof(q_i->pol));
 
-	q_i->sec_info = OWNER_SECURITY_INFORMATION |
-	                GROUP_SECURITY_INFORMATION |
-	                DACL_SECURITY_INFORMATION;
+	q_i->sec_info = sec_info;
 
 	q_i->ptr = psdb != NULL ? 1 : 0;
 	q_i->data = psdb;
@@ -1001,7 +874,8 @@
 makes a structure.
 ********************************************************************/
 
-BOOL init_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char* val_name)
+BOOL init_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, const char *val_name,
+                     BUFFER2 *value_output)
 {
         if (q_i == NULL)
                 return False;
@@ -1015,12 +889,12 @@
         q_i->ptr_buf = 1;
 
         q_i->ptr_bufsize = 1;
-        q_i->bufsize = 0;
+        q_i->bufsize = value_output->buf_max_len;
         q_i->buf_unk = 0;
 
         q_i->unk1 = 0;
         q_i->ptr_buflen = 1;
-        q_i->buflen = 0;
+        q_i->buflen = value_output->buf_max_len; 
 
         q_i->ptr_buflen2 = 1;
         q_i->buflen2 = 0;
--- source/rpc_server/srv_reg.c	2004/06/18 17:39:21	1.1.1.1
+++ source/rpc_server/srv_reg.c	2004/06/29 22:38:51
@@ -63,8 +63,8 @@
 
 static BOOL api_reg_open_hklm(pipes_struct *p)
 {
-	REG_Q_OPEN_HKLM q_u;
-	REG_R_OPEN_HKLM r_u;
+	REG_Q_OPEN_HIVE q_u;
+	REG_R_OPEN_HIVE r_u;
 	prs_struct *data = &p->in_data.data;
 	prs_struct *rdata = &p->out_data.rdata;
 
@@ -72,12 +72,12 @@
 	ZERO_STRUCT(r_u);
 
 	/* grab the reg open */
-	if(!reg_io_q_open_hklm("", &q_u, data, 0))
+	if(!reg_io_q_open_hive("", &q_u, data, 0))
 		return False;
 
 	r_u.status = _reg_open_hklm(p, &q_u, &r_u);
 
-	if(!reg_io_r_open_hklm("", &r_u, rdata, 0))
+	if(!reg_io_r_open_hive("", &r_u, rdata, 0))
 		return False;
 
 	return True;
@@ -89,8 +89,8 @@
 
 static BOOL api_reg_open_hku(pipes_struct *p)
 {
-	REG_Q_OPEN_HKU q_u;
-	REG_R_OPEN_HKU r_u;
+	REG_Q_OPEN_HIVE q_u;
+	REG_R_OPEN_HIVE r_u;
 	prs_struct *data = &p->in_data.data;
 	prs_struct *rdata = &p->out_data.rdata;
 
@@ -98,12 +98,12 @@
 	ZERO_STRUCT(r_u);
 
 	/* grab the reg open */
-	if(!reg_io_q_open_hku("", &q_u, data, 0))
+	if(!reg_io_q_open_hive("", &q_u, data, 0))
 		return False;
 
 	r_u.status = _reg_open_hku(p, &q_u, &r_u);
 
-	if(!reg_io_r_open_hku("", &r_u, rdata, 0))
+	if(!reg_io_r_open_hive("", &r_u, rdata, 0))
 		return False;
 
 	return True;
@@ -115,8 +115,8 @@
 
 static BOOL api_reg_open_hkcr(pipes_struct *p)
 {
-	REG_Q_OPEN_HKCR q_u;
-	REG_R_OPEN_HKCR r_u;
+	REG_Q_OPEN_HIVE q_u;
+	REG_R_OPEN_HIVE r_u;
 	prs_struct *data = &p->in_data.data;
 	prs_struct *rdata = &p->out_data.rdata;
 
@@ -124,12 +124,12 @@
 	ZERO_STRUCT(r_u);
 
 	/* grab the reg open */
-	if(!reg_io_q_open_hkcr("", &q_u, data, 0))
+	if(!reg_io_q_open_hive("", &q_u, data, 0))
 		return False;
 
 	r_u.status = _reg_open_hkcr(p, &q_u, &r_u);
 
-	if(!reg_io_r_open_hkcr("", &r_u, rdata, 0))
+	if(!reg_io_r_open_hive("", &r_u, rdata, 0))
 		return False;
 
 	return True;
--- source/rpc_server/srv_reg_nt.c	2004/06/18 17:39:21	1.1.1.1
+++ source/rpc_server/srv_reg_nt.c	2004/06/29 22:38:51
@@ -291,7 +291,7 @@
 /*******************************************************************
  ********************************************************************/
 
-NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
+NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
 {
 	return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, 0x0 );
 }
@@ -299,7 +299,7 @@
 /*******************************************************************
  ********************************************************************/
 
-NTSTATUS _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_u)
+NTSTATUS _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
 {
 	return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, 0x0 );
 }
@@ -307,7 +307,7 @@
 /*******************************************************************
  ********************************************************************/
 
-NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u)
+NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
 {
 	return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, 0x0 );
 }
--- source/rpcclient/cmd_reg.c	2004/06/18 17:39:22	1.1.1.1
+++ source/rpcclient/cmd_reg.c	2004/06/29 22:38:51
@@ -57,6 +57,7 @@
 	POLICY_HND key_pol;
 	fstring full_keyname;
 	fstring key_name;
+	uint32 reg_type;
 
 	/*
 	 * query key info
@@ -84,6 +85,11 @@
 	if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname)))
 	{
 		fprintf(out_hnd, "regenum <key_name>\n");
+		return;
+	}
+
+	if (!reg_split_key(full_keyname, &reg_type, key_name)) {
+		fprintf(out_hnd, "Unknown registry hive '%s'\n", key_name);
 		return;
 	}
 


More information about the samba-technical mailing list