Commit 1fb6f271 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

ntdll: Implement NtRenameKey().

parent 440d3717
......@@ -2126,7 +2126,6 @@ static void test_NtRenameKey(void)
DWORD size;
status = NtRenameKey(NULL, NULL);
todo_wine
ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
......@@ -2140,17 +2139,18 @@ static void test_NtRenameKey(void)
status = pNtCreateKey(&subkey, KEY_READ|DELETE, &attr, 0, 0, 0, 0);
ok(!status, "Unexpected status %#lx.\n", status);
memset(&str2, 0, sizeof(str2));
status = NtRenameKey(subkey, &str2);
ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %#lx.\n", status);
pRtlCreateUnicodeStringFromAsciiz(&str2, "renamed_subkey");
status = NtRenameKey(subkey, NULL);
todo_wine
ok(status == STATUS_ACCESS_VIOLATION, "Unexpected status %#lx.\n", status);
status = NtRenameKey(NULL, &str);
todo_wine
ok(status == STATUS_INVALID_HANDLE, "Unexpected status %#lx.\n", status);
status = NtRenameKey(subkey, &str2);
todo_wine
ok(status == STATUS_ACCESS_DENIED, "Unexpected status %#lx.\n", status);
pNtClose(subkey);
......@@ -2158,10 +2158,8 @@ static void test_NtRenameKey(void)
ok(!status, "Unexpected status %#lx.\n", status);
/* Rename to itself. */
status = NtRenameKey(subkey, &str);
todo_wine
ok(status == STATUS_CANNOT_DELETE, "Unexpected status %#lx.\n", status);
status = NtRenameKey(subkey, &str2);
todo_wine
ok(!status, "Unexpected status %#lx.\n", status);
pRtlFreeUnicodeString(&str2);
......
......@@ -199,10 +199,23 @@ NTSTATUS WINAPI NtDeleteKey( HANDLE key )
/******************************************************************************
* NtRenameKey (NTDLL.@)
*/
NTSTATUS WINAPI NtRenameKey( HANDLE handle, UNICODE_STRING *name )
NTSTATUS WINAPI NtRenameKey( HANDLE key, UNICODE_STRING *name )
{
FIXME( "(%p %s)\n", handle, debugstr_us(name) );
return STATUS_NOT_IMPLEMENTED;
NTSTATUS ret;
TRACE( "(%p %s)\n", key, debugstr_us(name) );
if (!name) return STATUS_ACCESS_VIOLATION;
if (!name->Buffer || !name->Length) return STATUS_INVALID_PARAMETER;
SERVER_START_REQ( rename_key )
{
req->hkey = wine_server_obj_handle( key );
wine_server_add_data( req, name->Buffer, name->Length );
ret = wine_server_call( req );
}
SERVER_END_REQ;
return ret;
}
......
......@@ -2384,6 +2384,19 @@ struct set_registry_notification_reply
struct rename_key_request
{
struct request_header __header;
obj_handle_t hkey;
/* VARARG(name,unicode_str); */
};
struct rename_key_reply
{
struct reply_header __header;
};
struct create_timer_request
{
struct request_header __header;
......@@ -5538,6 +5551,7 @@ enum request
REQ_unload_registry,
REQ_save_registry,
REQ_set_registry_notification,
REQ_rename_key,
REQ_create_timer,
REQ_open_timer,
REQ_set_timer,
......@@ -5820,6 +5834,7 @@ union generic_request
struct unload_registry_request unload_registry_request;
struct save_registry_request save_registry_request;
struct set_registry_notification_request set_registry_notification_request;
struct rename_key_request rename_key_request;
struct create_timer_request create_timer_request;
struct open_timer_request open_timer_request;
struct set_timer_request set_timer_request;
......@@ -6100,6 +6115,7 @@ union generic_reply
struct unload_registry_reply unload_registry_reply;
struct save_registry_reply save_registry_reply;
struct set_registry_notification_reply set_registry_notification_reply;
struct rename_key_reply rename_key_reply;
struct create_timer_reply create_timer_reply;
struct open_timer_reply open_timer_reply;
struct set_timer_reply set_timer_reply;
......@@ -6288,7 +6304,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 751
#define SERVER_PROTOCOL_VERSION 752
/* ### protocol_version end ### */
......
......@@ -1837,6 +1837,13 @@ struct process_info
@END
/* Rename a registry key */
@REQ(rename_key)
obj_handle_t hkey; /* handle to the key to be renamed */
VARARG(name,unicode_str); /* new name */
@END
/* Create a waitable timer */
@REQ(create_timer)
unsigned int access; /* wanted access rights */
......
......@@ -1007,6 +1007,64 @@ static void enum_key( struct key *key, int index, int info_class, struct enum_ke
if (debug_level > 1) dump_operation( key, NULL, "Enum" );
}
/* rename a key and its values */
static int rename_key( struct key *key, const struct unicode_str *new_name )
{
struct unicode_str token, name;
struct key *subkey;
int i, index, cur_index;
WCHAR *ptr;
token.str = NULL;
if (is_wow6432node( key->name, key->namelen ))
{
set_error( STATUS_INVALID_PARAMETER );
return -1;
}
/* changing to a path is not allowed */
if (!new_name->len || !get_path_token( new_name, &token ) || token.len != new_name->len)
{
set_error( STATUS_INVALID_PARAMETER );
return -1;
}
/* check for existing subkey with the same name */
if (!key->parent || (subkey = find_subkey( key->parent, new_name, &index )))
{
set_error( STATUS_CANNOT_DELETE );
return -1;
}
if (!(ptr = memdup( new_name->str, new_name->len ))) return -1;
name.str = key->name;
name.len = key->namelen;
find_subkey( key->parent, &name, &cur_index );
if (cur_index < index && (index - cur_index) > 1)
{
--index;
for (i = cur_index; i < index; ++i)
key->parent->subkeys[i] = key->parent->subkeys[i+1];
}
else if (cur_index > index)
{
for (i = cur_index; i > index; --i)
key->parent->subkeys[i] = key->parent->subkeys[i-1];
}
key->parent->subkeys[index] = key;
free( key->name );
key->name = ptr;
key->namelen = new_name->len;
if (debug_level > 1) dump_operation( key, NULL, "Rename" );
make_dirty( key );
touch_key( key, REG_NOTIFY_CHANGE_NAME );
return 0;
}
/* delete a key and its values */
static int delete_key( struct key *key, int recurse )
{
......@@ -2413,3 +2471,19 @@ DECL_HANDLER(set_registry_notification)
release_object( key );
}
}
/* rename a registry key */
DECL_HANDLER(rename_key)
{
struct unicode_str name;
struct key *key;
key = get_hkey_obj( req->hkey, KEY_WRITE );
if (key)
{
name.str = get_req_data();
name.len = (get_req_data_size() / sizeof(WCHAR)) * sizeof(WCHAR);
rename_key( key, &name );
release_object( key );
}
}
......@@ -210,6 +210,7 @@ DECL_HANDLER(load_registry);
DECL_HANDLER(unload_registry);
DECL_HANDLER(save_registry);
DECL_HANDLER(set_registry_notification);
DECL_HANDLER(rename_key);
DECL_HANDLER(create_timer);
DECL_HANDLER(open_timer);
DECL_HANDLER(set_timer);
......@@ -491,6 +492,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_unload_registry,
(req_handler)req_save_registry,
(req_handler)req_set_registry_notification,
(req_handler)req_rename_key,
(req_handler)req_create_timer,
(req_handler)req_open_timer,
(req_handler)req_set_timer,
......@@ -1230,6 +1232,8 @@ C_ASSERT( FIELD_OFFSET(struct set_registry_notification_request, event) == 16 );
C_ASSERT( FIELD_OFFSET(struct set_registry_notification_request, subtree) == 20 );
C_ASSERT( FIELD_OFFSET(struct set_registry_notification_request, filter) == 24 );
C_ASSERT( sizeof(struct set_registry_notification_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct rename_key_request, hkey) == 12 );
C_ASSERT( sizeof(struct rename_key_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_timer_request, access) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_timer_request, manual) == 16 );
C_ASSERT( sizeof(struct create_timer_request) == 24 );
......
......@@ -2414,6 +2414,12 @@ static void dump_set_registry_notification_request( const struct set_registry_no
fprintf( stderr, ", filter=%08x", req->filter );
}
static void dump_rename_key_request( const struct rename_key_request *req )
{
fprintf( stderr, " hkey=%04x", req->hkey );
dump_varargs_unicode_str( ", name=", cur_size );
}
static void dump_create_timer_request( const struct create_timer_request *req )
{
fprintf( stderr, " access=%08x", req->access );
......@@ -4578,6 +4584,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_unload_registry_request,
(dump_func)dump_save_registry_request,
(dump_func)dump_set_registry_notification_request,
(dump_func)dump_rename_key_request,
(dump_func)dump_create_timer_request,
(dump_func)dump_open_timer_request,
(dump_func)dump_set_timer_request,
......@@ -4856,6 +4863,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
NULL,
NULL,
NULL,
(dump_func)dump_create_timer_reply,
(dump_func)dump_open_timer_reply,
(dump_func)dump_set_timer_reply,
......@@ -5134,6 +5142,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"unload_registry",
"save_registry",
"set_registry_notification",
"rename_key",
"create_timer",
"open_timer",
"set_timer",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment