added jeremy's new c++-like code for parsing of security descriptors.
[samba.git] / source3 / rpcclient / cmd_reg.c
index 7dfc3555695722e2bf79be4b04c68d79a833f18d..95a439c4623fc7e296938a6ef604c4a623e464fb 100644 (file)
@@ -36,18 +36,38 @@ extern int smb_tidx;
 
 extern FILE* out_hnd;
 
+/*
+ * keys.  of the form:
+ * ----
+ *
+ * [HKLM]|[HKU]\[parent_keyname_components]\[subkey]|[value]
+ *
+ * reg_getsubkey() splits this down into:
+ * [HKLM]|[HKU]\[parent_keyname_components] and [subkey]|[value]
+ *
+ * do_reg_connect() splits the left side down further into:
+ * [HKLM]|[HKU] and [parent_keyname_components].
+ *
+ * HKLM is short for HKEY_LOCAL_MACHINE
+ * HKU  is short for HKEY_USERS
+ *
+ * oh, and HKEY stands for "Hive Key".
+ *
+ */
 
 /****************************************************************************
 nt registry enum
 ****************************************************************************/
 void cmd_reg_enum(struct client_info *info)
 {
+       uint16 fnum;
        BOOL res = True;
        BOOL res1 = True;
        BOOL res2 = True;
        int i;
 
        POLICY_HND key_pol;
+       fstring full_keyname;
        fstring key_name;
 
        /*
@@ -73,31 +93,43 @@ void cmd_reg_enum(struct client_info *info)
 
        DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
 
-       if (!next_token(NULL, key_name, NULL, sizeof(key_name)))
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
        {
-               fprintf(out_hnd, "regenum key_name\n");
+               fprintf(out_hnd, "regenum <key_name>\n");
                return;
        }
 
        /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
 
        /* open registry receive a policy handle */
-       res = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
+       res = res ? do_reg_connect(smb_cli, fnum, full_keyname, key_name,
                                &info->dom.reg_pol_connect) : False;
 
-       /* open an entry */
-       res1 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
-                                key_name, 0x02000000, &key_pol) : False;
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res1 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
 
-       res1 = res1 ? do_reg_query_key(smb_cli,
+       res1 = res1 ? do_reg_query_key(smb_cli, fnum,
                                &key_pol,
                                key_class, &max_class_len,
                                &num_subkeys, &max_subkeylen, &max_subkeysize,
                                &num_values, &max_valnamelen, &max_valbufsize,
                                &sec_desc, &mod_time) : False;
 
+       if (res1 && num_subkeys > 0)
+       {
+               fprintf(out_hnd,"Subkeys\n");
+               fprintf(out_hnd,"-------\n");
+       }
+
        for (i = 0; i < num_subkeys; i++)
        {
                /*
@@ -110,7 +142,7 @@ void cmd_reg_enum(struct client_info *info)
                time_t key_mod_time;
 
                /* unknown 1a it */
-               res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol,
+               res2 = res1 ? do_reg_unknown_1a(smb_cli, fnum, &key_pol,
                                        &unk_1a_response) : False;
 
                if (res2 && unk_1a_response != 5)
@@ -119,7 +151,7 @@ void cmd_reg_enum(struct client_info *info)
                }
 
                /* enum key */
-               res2 = res2 ? do_reg_enum_key(smb_cli, &key_pol,
+               res2 = res2 ? do_reg_enum_key(smb_cli, fnum, &key_pol,
                                        i, enum_name,
                                        &enum_unk1, &enum_unk2,
                                        &key_mod_time) : False;
@@ -133,6 +165,12 @@ void cmd_reg_enum(struct client_info *info)
 
        }
 
+       if (num_values > 0)
+       {
+               fprintf(out_hnd,"Key Values\n");
+               fprintf(out_hnd,"----------\n");
+       }
+
        for (i = 0; i < num_values; i++)
        {
                /*
@@ -144,7 +182,7 @@ void cmd_reg_enum(struct client_info *info)
                fstring val_name;
 
                /* unknown 1a it */
-               res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol,
+               res2 = res1 ? do_reg_unknown_1a(smb_cli, fnum, &key_pol,
                                        &unk_1a_response) : False;
 
                if (res2 && unk_1a_response != 5)
@@ -153,7 +191,7 @@ void cmd_reg_enum(struct client_info *info)
                }
 
                /* enum key */
-               res2 = res2 ? do_reg_enum_val(smb_cli, &key_pol,
+               res2 = res2 ? do_reg_enum_val(smb_cli, fnum, &key_pol,
                                        i, max_valnamelen, max_valbufsize,
                                        val_name, &val_type, &value) : False;
                
@@ -166,11 +204,14 @@ void cmd_reg_enum(struct client_info *info)
        }
 
        /* close the handles */
-       res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+       if ((*key_name) != 0)
+       {
+               res1 = res1 ? do_reg_close(smb_cli, fnum, &key_pol) : False;
+       }
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
 
        /* close the session */
-       cli_nt_session_close(smb_cli);
+       cli_nt_session_close(smb_cli, fnum);
 
        if (res && res1 && res2)
        {
@@ -187,10 +228,12 @@ nt registry query key
 ****************************************************************************/
 void cmd_reg_query_key(struct client_info *info)
 {
+       uint16 fnum;
        BOOL res = True;
        BOOL res1 = True;
 
        POLICY_HND key_pol;
+       fstring full_keyname;
        fstring key_name;
 
        /*
@@ -210,25 +253,31 @@ void cmd_reg_query_key(struct client_info *info)
 
        DEBUG(5, ("cmd_reg_enum: smb_cli->fd:%d\n", smb_cli->fd));
 
-       if (!next_token(NULL, key_name, NULL, sizeof(key_name)))
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
        {
                fprintf(out_hnd, "regquery key_name\n");
                return;
        }
 
        /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
 
        /* open registry receive a policy handle */
-       res = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
+       res = res ? do_reg_connect(smb_cli, fnum, full_keyname, key_name,
                                &info->dom.reg_pol_connect) : False;
 
-       /* open an entry */
-       res1 = res  ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
-                                key_name, 0x02000000, &key_pol) : False;
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res1 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
 
-       res1 = res1 ? do_reg_query_key(smb_cli,
+       res1 = res1 ? do_reg_query_key(smb_cli, fnum,
                                &key_pol,
                                key_class, &key_class_len,
                                &num_subkeys, &max_subkeylen, &max_subkeysize,
@@ -237,7 +286,7 @@ void cmd_reg_query_key(struct client_info *info)
 
        if (res1 && key_class_len != 0)
        {
-               res1 = res1 ? do_reg_query_key(smb_cli,
+               res1 = res1 ? do_reg_query_key(smb_cli, fnum,
                                &key_pol,
                                key_class, &key_class_len,
                                &num_subkeys, &max_subkeylen, &max_subkeysize,
@@ -256,11 +305,14 @@ void cmd_reg_query_key(struct client_info *info)
        }
 
        /* close the handles */
-       res1 = res1 ? do_reg_close(smb_cli, &key_pol) : False;
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+       if ((*key_name) != 0)
+       {
+               res1 = res1 ? do_reg_close(smb_cli, fnum, &key_pol) : False;
+       }
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
 
        /* close the session */
-       cli_nt_session_close(smb_cli);
+       cli_nt_session_close(smb_cli, fnum);
 
        if (res && res1)
        {
@@ -272,123 +324,19 @@ void cmd_reg_query_key(struct client_info *info)
        }
 }
 
-/****************************************************************************
-nt registry test
-****************************************************************************/
-void cmd_reg_test2(struct client_info *info)
-{
-       BOOL res = True;
-       BOOL res1 = True;
-       BOOL res2 = True;
-       BOOL res3 = True;
-       int i;
-
-       /*
-        * query key info
-        */
-
-       POLICY_HND key_pol;
-       fstring key_class;
-       uint32 max_class_len;
-       uint32 num_subkeys;
-       uint32 max_subkeylen;
-       uint32 max_subkeysize; 
-       uint32 num_values;
-       uint32 max_valnamelen;
-       uint32 max_valbufsize;
-       uint32 sec_desc;
-       NTTIME mod_time;
-
-       /*
-        * unknown 0x1a request
-        */
-
-       uint32 unk_1a_response;
-
-       /*
-        * enumerate key
-        */
-
-       fstring enum_name;
-       uint32 enum_unk1;
-       uint32 enum_unk2;
-       time_t key_mod_time;
-
-       DEBUG(5, ("cmd_reg_test: smb_cli->fd:%d\n", smb_cli->fd));
-
-       /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
-
-       /* open registry receive a policy handle */
-       res  = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
-                               &info->dom.reg_pol_connect) : False;
-
-       res1 = res ? do_reg_open_unk_4(smb_cli,
-                               0x84E0, 0x02000000,
-                               &info->dom.reg_pol_unk_4  ) : False;
-
-       res2 = res1 ? do_reg_query_key(smb_cli,
-                               &key_pol,
-                               key_class, &max_class_len,
-                               &num_subkeys, &max_subkeylen, &max_subkeysize,
-                               &num_values, &max_valnamelen, &max_valbufsize,
-                               &sec_desc, &mod_time) : False;
-
-       for (i = 0; i < num_subkeys; i++)
-       {
-               /* unknown 1a it */
-               res3 = res2 ? do_reg_unknown_1a(smb_cli, &info->dom.reg_pol_connect,
-                                       &unk_1a_response) : False;
-
-               if (res3)
-               {
-                       fprintf(out_hnd,"Unknown 1a response: %x\n", unk_1a_response);
-               }
-
-               /* enum key */
-               res3 = res3 ? do_reg_enum_key(smb_cli, &info->dom.reg_pol_connect,
-                                       i, enum_name,
-                                       &enum_unk1, &enum_unk2,
-                                       &key_mod_time) : False;
-               
-               if (res3)
-               {
-                       fprintf(out_hnd,"Enum Key: %s  ", enum_name);
-                       fprintf(out_hnd,"unk (%08x %08x)  ", enum_unk1, enum_unk2);
-                       fprintf(out_hnd,"mod time: %s\n", http_timestring(key_mod_time));
-               }
-       }
-
-       /* close the handles */
-       res2 = res2 ? do_reg_close(smb_cli, &key_pol                  ) : False;
-       res1 = res1 ? do_reg_close(smb_cli, &info->dom.reg_pol_unk_4  ) : False;
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
-
-       /* close the session */
-       cli_nt_session_close(smb_cli);
-
-       if (res && res1 && res2)
-       {
-               DEBUG(5,("cmd_reg_test2: query succeeded\n"));
-               fprintf(out_hnd,"Registry Test2\n");
-       }
-       else
-       {
-               DEBUG(5,("cmd_reg_test2: query failed\n"));
-       }
-}
-
 /****************************************************************************
 nt registry create value
 ****************************************************************************/
 void cmd_reg_create_val(struct client_info *info)
 {
+       uint16 fnum;
        BOOL res = True;
        BOOL res3 = True;
        BOOL res4 = True;
 
        POLICY_HND parent_pol;
+       fstring full_keyname;
+       fstring keyname;
        fstring parent_name;
        fstring val_name;
        fstring tmp;
@@ -399,27 +347,29 @@ void cmd_reg_create_val(struct client_info *info)
        uint32 unk_0;
        uint32 unk_1;
        /* query it */
-       res1 = res1 ? do_reg_query_info(smb_cli, &val_pol,
+       res1 = res1 ? do_reg_query_info(smb_cli, fnum, &val_pol,
                                type, &unk_0, &unk_1) : False;
 #endif
 
-       DEBUG(5, ("cmd_reg_get_val_sec: smb_cli->fd:%d\n", smb_cli->fd));
+       DEBUG(5, ("cmd_reg_create_val: smb_cli->fd:%d\n", smb_cli->fd));
 
-       if (!next_token(NULL, parent_name, NULL, sizeof(parent_name)))
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
        {
-               fprintf(out_hnd, "regcreate <parent val name> <val_name> <val_type> <val>\n");
+               fprintf(out_hnd, "regcreate <val_name> <val_type> <val>\n");
                return;
        }
 
-       if (!next_token(NULL, val_name   , NULL, sizeof(val_name   )))
+       reg_get_subkey(full_keyname, keyname, val_name);
+
+       if (keyname[0] == 0 || val_name[0] == 0)
        {
-               fprintf(out_hnd, "regcreate <parent val name> <val_name> <val_type> <val>\n");
+               fprintf(out_hnd, "invalid key name\n");
                return;
        }
-
+       
        if (!next_token(NULL, tmp, NULL, sizeof(tmp)))
        {
-               fprintf(out_hnd, "regcreate <parent val name> <val_name> <val_type (1|4)> <val>\n");
+               fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
                return;
        }
 
@@ -433,7 +383,7 @@ void cmd_reg_create_val(struct client_info *info)
 
        if (!next_token(NULL, tmp, NULL, sizeof(tmp)))
        {
-               fprintf(out_hnd, "regcreate <parent val name> <val_name> <val_type (1|4)> <val>\n");
+               fprintf(out_hnd, "regcreate <val_name> <val_type (1|4)> <val>\n");
                return;
        }
 
@@ -474,32 +424,41 @@ void cmd_reg_create_val(struct client_info *info)
        dump_data(10, (char *)value.buffer, value.buf_len);
 
        /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
 
        /* open registry receive a policy handle */
-       res  = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
+       res = res ? do_reg_connect(smb_cli, fnum, keyname, parent_name,
                                &info->dom.reg_pol_connect) : False;
 
-       /* open an entry */
-       res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
-                                parent_name, 0x02000000, &parent_pol) : False;
+       if ((*val_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        parent_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
 
        /* create an entry */
-       res4 = res3 ? do_reg_create_val(smb_cli, &parent_pol,
+       res4 = res3 ? do_reg_create_val(smb_cli, fnum, &parent_pol,
                                 val_name, val_type, &value) : False;
 
-       /* some sort of "sync" or "refresh" on the parent key? */
-       res4 = res4 ? do_reg_unk_b(smb_cli, &parent_pol) : False;
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, fnum, &parent_pol) : False;
 
        /* close the val handle */
-       res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+       if ((*val_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, fnum, &parent_pol) : False;
+       }
 
        /* close the registry handles */
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
 
        /* close the session */
-       cli_nt_session_close(smb_cli);
+       cli_nt_session_close(smb_cli, fnum);
 
        if (res && res3 && res4)
        {
@@ -512,59 +471,149 @@ void cmd_reg_create_val(struct client_info *info)
        }
 }
 
+/****************************************************************************
+nt registry delete value
+****************************************************************************/
+void cmd_reg_delete_val(struct client_info *info)
+{
+       uint16 fnum;
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND parent_pol;
+       fstring full_keyname;
+       fstring keyname;
+       fstring parent_name;
+       fstring val_name;
+
+       DEBUG(5, ("cmd_reg_delete_val: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "regdelete <val_name>\n");
+               return;
+       }
+
+       reg_get_subkey(full_keyname, keyname, val_name);
+
+       if (keyname[0] == 0 || val_name[0] == 0)
+       {
+               fprintf(out_hnd, "invalid key name\n");
+               return;
+       }
+       
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, fnum, keyname, parent_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*val_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        parent_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
+
+       /* delete an entry */
+       res4 = res3 ? do_reg_delete_val(smb_cli, fnum, &parent_pol, val_name) : False;
+
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, fnum, &parent_pol) : False;
+
+       /* close the key handle */
+       res3 = res3 ? do_reg_close(smb_cli, fnum, &parent_pol) : False;
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli, fnum);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_delete_val: query succeeded\n"));
+               fprintf(out_hnd,"OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_delete_val: query failed\n"));
+       }
+}
+
 /****************************************************************************
 nt registry delete key
 ****************************************************************************/
 void cmd_reg_delete_key(struct client_info *info)
 {
+       uint16 fnum;
        BOOL res = True;
        BOOL res3 = True;
        BOOL res4 = True;
 
        POLICY_HND parent_pol;
+       fstring full_keyname;
        fstring parent_name;
        fstring key_name;
+       fstring subkey_name;
 
        DEBUG(5, ("cmd_reg_delete_key: smb_cli->fd:%d\n", smb_cli->fd));
 
-       if (!next_token(NULL, parent_name, NULL, sizeof(parent_name)))
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
        {
-               fprintf(out_hnd, "regcreate <parent key name> <key_name>\n");
+               fprintf(out_hnd, "regdeletekey <key_name>\n");
                return;
        }
 
-       if (!next_token(NULL, key_name   , NULL, sizeof(key_name   )))
+       reg_get_subkey(full_keyname, parent_name, subkey_name);
+
+       if (parent_name[0] == 0 || subkey_name[0] == 0)
        {
-               fprintf(out_hnd, "regcreate <parent key name> <key_name>\n");
+               fprintf(out_hnd, "invalid key name\n");
                return;
        }
-
+       
        /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
 
        /* open registry receive a policy handle */
-       res  = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
+       res = res ? do_reg_connect(smb_cli, fnum, parent_name, key_name,
                                &info->dom.reg_pol_connect) : False;
 
-       /* open an entry */
-       res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
-                                parent_name, 0x02000000, &parent_pol) : False;
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
 
        /* create an entry */
-       res4 = res3 ? do_reg_delete_key(smb_cli, &parent_pol, key_name) : False;
+       res4 = res3 ? do_reg_delete_key(smb_cli, fnum, &parent_pol, subkey_name) : False;
 
-       /* some sort of "sync" or "refresh" on the parent key? */
-       res4 = res4 ? do_reg_unk_b(smb_cli, &parent_pol) : False;
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, fnum, &parent_pol) : False;
 
        /* close the key handle */
-       res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+       if ((*key_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, fnum, &parent_pol) : False;
+       }
 
        /* close the registry handles */
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
 
        /* close the session */
-       cli_nt_session_close(smb_cli);
+       cli_nt_session_close(smb_cli, fnum);
 
        if (res && res3 && res4)
        {
@@ -582,77 +631,83 @@ nt registry create key
 ****************************************************************************/
 void cmd_reg_create_key(struct client_info *info)
 {
+       uint16 fnum;
        BOOL res = True;
        BOOL res3 = True;
        BOOL res4 = True;
 
        POLICY_HND parent_pol;
        POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring parent_key;
        fstring parent_name;
        fstring key_name;
        fstring key_class;
-       SEC_INFO sam_access;
-
-#if 0
-       uint32 unk_0;
-       uint32 unk_1;
-       /* query it */
-       res1 = res1 ? do_reg_query_info(smb_cli, &key_pol,
-                               type, &unk_0, &unk_1) : False;
-#endif
+       SEC_ACCESS sam_access;
 
        DEBUG(5, ("cmd_reg_create_key: smb_cli->fd:%d\n", smb_cli->fd));
 
-       if (!next_token(NULL, parent_name, NULL, sizeof(parent_name)))
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
        {
-               fprintf(out_hnd, "regcreate <parent key name> <key_name> [key_class]\n");
+               fprintf(out_hnd, "regcreate <key_name> [key_class]\n");
                return;
        }
 
-       if (!next_token(NULL, key_name   , NULL, sizeof(key_name   )))
+       reg_get_subkey(full_keyname, parent_key, key_name);
+
+       if (parent_key[0] == 0 || key_name[0] == 0)
        {
-               fprintf(out_hnd, "regcreate <parent key name> <key_name> [key_class]\n");
+               fprintf(out_hnd, "invalid key name\n");
                return;
        }
-
+       
        if (!next_token(NULL, key_class, NULL, sizeof(key_class)))
        {
                memset(key_class, 0, sizeof(key_class));
        }
 
        /* set access permissions */
-       sam_access.perms = SEC_RIGHTS_READ;
+       sam_access.mask = SEC_RIGHTS_READ;
 
        /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
 
        /* open registry receive a policy handle */
-       res  = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
+       res = res ? do_reg_connect(smb_cli, fnum, parent_key, parent_name,
                                &info->dom.reg_pol_connect) : False;
 
-       /* open an entry */
-       res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
-                                parent_name, 0x02000000, &parent_pol) : False;
+       if ((*parent_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        parent_name, 0x02000000, &parent_pol) : False;
+       }
+       else
+       {
+               memcpy(&parent_pol, &info->dom.reg_pol_connect, sizeof(parent_pol));
+       }
 
        /* create an entry */
-       res4 = res3 ? do_reg_create_key(smb_cli, &parent_pol,
+       res4 = res3 ? do_reg_create_key(smb_cli, fnum, &parent_pol,
                                 key_name, key_class, &sam_access, &key_pol) : False;
 
-       /* some sort of "sync" or "refresh" on the parent key? */
-       res4 = res4 ? do_reg_unk_b(smb_cli, &parent_pol) : False;
+       /* flush the modified key */
+       res4 = res4 ? do_reg_flush_key(smb_cli, fnum, &parent_pol) : False;
 
        /* close the key handle */
-       res4 = res4 ? do_reg_close(smb_cli, &key_pol) : False;
+       res4 = res4 ? do_reg_close(smb_cli, fnum, &key_pol) : False;
 
        /* close the key handle */
-       res3 = res3 ? do_reg_close(smb_cli, &parent_pol) : False;
+       if ((*parent_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, fnum, &parent_pol) : False;
+       }
 
        /* close the registry handles */
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
 
        /* close the session */
-       cli_nt_session_close(smb_cli);
+       cli_nt_session_close(smb_cli, fnum);
 
        if (res && res3 && res4)
        {
@@ -668,13 +723,15 @@ void cmd_reg_create_key(struct client_info *info)
 /****************************************************************************
 nt registry security info
 ****************************************************************************/
-void cmd_reg_get_key_sec(struct client_info *info)
+void cmd_reg_test_key_sec(struct client_info *info)
 {
+       uint16 fnum;
        BOOL res = True;
        BOOL res3 = True;
        BOOL res4 = True;
 
        POLICY_HND key_pol;
+       fstring full_keyname;
        fstring key_name;
 
        /*
@@ -682,53 +739,72 @@ void cmd_reg_get_key_sec(struct client_info *info)
         */
 
        uint32 sec_buf_size;
-       SEC_DESC_BUF sec_buf;
+       SEC_DESC_BUF *psdb;
 
        DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
 
-       if (!next_token(NULL, key_name, NULL, sizeof(key_name)))
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
        {
-               fprintf(out_hnd, "regtest key_name\n");
+               fprintf(out_hnd, "reggetsec <key_name>\n");
                return;
        }
 
        /* open WINREG session. */
-       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG) : False;
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
 
        /* open registry receive a policy handle */
-       res  = res ? do_reg_open_policy(smb_cli,
-                               0x84E0, 0x02000000,
+       res = res ? do_reg_connect(smb_cli, fnum, full_keyname, key_name,
                                &info->dom.reg_pol_connect) : False;
 
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
+
        /* open an entry */
-       res3 = res ? do_reg_open_entry(smb_cli, &info->dom.reg_pol_connect,
+       res3 = res ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
                                 key_name, 0x02000000, &key_pol) : False;
 
-       /* query key sec info.  first call sets sec_buf_size. */
+       /* Get the size. */
        sec_buf_size = 0;
-       res4 = res3 ? do_reg_get_key_sec(smb_cli, &key_pol,
-                               &sec_buf_size, &sec_buf) : False;
+
+       res4 = res3 ? do_reg_get_key_sec(smb_cli, fnum, &key_pol,
+                               &sec_buf_size, &psdb) : False;
        
-       res4 = res4 ? do_reg_get_key_sec(smb_cli, &key_pol,
-                               &sec_buf_size, &sec_buf) : False;
+       free_sec_desc_buf(&psdb);
+
+       res4 = res4 ? do_reg_get_key_sec(smb_cli, fnum, &key_pol,
+                               &sec_buf_size, &psdb) : False;
 
-       if (res4 && sec_buf.len > 0)
+       if (res4 && psdb->len > 0 && psdb->sec != NULL)
        {
-               fprintf(out_hnd, "Security Info for %s: (%d)\n",
-                                key_name, sec_buf_size);
-               display_sec_desc(out_hnd, ACTION_HEADER   , &sec_buf.sec);
-               display_sec_desc(out_hnd, ACTION_ENUMERATE, &sec_buf.sec);
-               display_sec_desc(out_hnd, ACTION_FOOTER   , &sec_buf.sec);
+               display_sec_desc(out_hnd, ACTION_HEADER   , psdb->sec);
+               display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
+               display_sec_desc(out_hnd, ACTION_FOOTER   , psdb->sec);
+
+               res4 = res4 ? do_reg_set_key_sec(smb_cli, fnum, &key_pol,
+                               psdb) : False;
+
        }
+       free_sec_desc_buf(&psdb);
 
        /* close the key handle */
-       res3 = res3 ? do_reg_close(smb_cli, &key_pol) : False;
+       if ((*key_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, fnum, &key_pol) : False;
+       }
 
        /* close the registry handles */
-       res  = res  ? do_reg_close(smb_cli, &info->dom.reg_pol_connect) : False;
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
 
        /* close the session */
-       cli_nt_session_close(smb_cli);
+       cli_nt_session_close(smb_cli, fnum);
 
        if (res && res3 && res4)
        {
@@ -741,3 +817,141 @@ void cmd_reg_get_key_sec(struct client_info *info)
        }
 }
 
+/****************************************************************************
+nt registry security info
+****************************************************************************/
+void cmd_reg_get_key_sec(struct client_info *info)
+{
+       uint16 fnum;
+       BOOL res = True;
+       BOOL res3 = True;
+       BOOL res4 = True;
+
+       POLICY_HND key_pol;
+       fstring full_keyname;
+       fstring key_name;
+
+       /*
+        * security info
+        */
+
+       uint32 sec_buf_size;
+       SEC_DESC_BUF *psdb;
+
+       DEBUG(5, ("cmd_reg_get_key_sec: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, full_keyname, NULL, sizeof(full_keyname)))
+       {
+               fprintf(out_hnd, "reggetsec <key_name>\n");
+               return;
+       }
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
+
+       /* open registry receive a policy handle */
+       res = res ? do_reg_connect(smb_cli, fnum, full_keyname, key_name,
+                               &info->dom.reg_pol_connect) : False;
+
+       if ((*key_name) != 0)
+       {
+               /* open an entry */
+               res3 = res  ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                        key_name, 0x02000000, &key_pol) : False;
+       }
+       else
+       {
+               memcpy(&key_pol, &info->dom.reg_pol_connect, sizeof(key_pol));
+       }
+
+       /* open an entry */
+       res3 = res ? do_reg_open_entry(smb_cli, fnum, &info->dom.reg_pol_connect,
+                                key_name, 0x02000000, &key_pol) : False;
+
+       /* Get the size. */
+       sec_buf_size = 0;
+
+       res4 = res3 ? do_reg_get_key_sec(smb_cli, fnum, &key_pol,
+                               &sec_buf_size, &psdb) : False;
+       
+       free_sec_desc_buf(&psdb);
+
+       res4 = res4 ? do_reg_get_key_sec(smb_cli, fnum, &key_pol,
+                               &sec_buf_size, &psdb) : False;
+
+       if (res4 && psdb->len > 0 && psdb->sec != NULL)
+       {
+               display_sec_desc(out_hnd, ACTION_HEADER   , psdb->sec);
+               display_sec_desc(out_hnd, ACTION_ENUMERATE, psdb->sec);
+               display_sec_desc(out_hnd, ACTION_FOOTER   , psdb->sec);
+
+       }
+       free_sec_desc_buf(&psdb);
+
+       /* close the key handle */
+       if ((*key_name) != 0)
+       {
+               res3 = res3 ? do_reg_close(smb_cli, fnum, &key_pol) : False;
+       }
+
+       /* close the registry handles */
+       res  = res  ? do_reg_close(smb_cli, fnum, &info->dom.reg_pol_connect) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli, fnum);
+
+       if (res && res3 && res4)
+       {
+               DEBUG(5,("cmd_reg_get_key_sec: query succeeded\n"));
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_get_key_sec: query failed\n"));
+       }
+}
+
+/****************************************************************************
+nt registry shutdown
+****************************************************************************/
+void cmd_reg_shutdown(struct client_info *info)
+{
+       uint16 fnum;
+       BOOL res = True;
+
+       fstring msg;
+       fstring tmp;
+       uint32 timeout = 20;
+
+       DEBUG(5, ("cmd_reg_shutdown: smb_cli->fd:%d\n", smb_cli->fd));
+
+       if (!next_token(NULL, msg, NULL, sizeof(msg)))
+       {
+               msg[0] = 0;
+       }
+       else if (next_token(NULL, tmp, NULL, sizeof(tmp)))
+       {
+               timeout = atoi(tmp);
+       }
+
+
+       /* open WINREG session. */
+       res = res ? cli_nt_session_open(smb_cli, PIPE_WINREG, &fnum) : False;
+
+       /* create an entry */
+       res = res ? do_reg_shutdown(smb_cli, fnum, msg, timeout, 1) : False;
+
+       /* close the session */
+       cli_nt_session_close(smb_cli, fnum);
+
+       if (res)
+       {
+               DEBUG(5,("cmd_reg_shutdown: query succeeded\n"));
+               fprintf(out_hnd,"OK\n");
+       }
+       else
+       {
+               DEBUG(5,("cmd_reg_shutdown: query failed\n"));
+               fprintf(out_hnd,"Failed\n");
+       }
+}
+