Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=9314
-- v2: server: Store the order for registry value.
From: Haoyang Chen chenhaoyang@kylinos.cn
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=9314 --- dlls/advapi32/tests/registry.c | 26 ++++++++++++++++++++++---- server/registry.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index cc9c0bff2c6..e864691c3dc 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2541,7 +2541,7 @@ static void test_rw_order(void) DWORD dw = 0; static const char keyname[] = "test_rw_order"; char value_buf[2]; - DWORD values, value_len, value_name_max_len; + DWORD values, value_len, value_name_max_len, res; LSTATUS ret;
RegDeleteKeyA(HKEY_CURRENT_USER, keyname); @@ -2570,13 +2570,31 @@ static void test_rw_order(void) ok(strcmp(value_buf, "A") == 0, "Expected name "A", got %s\n", value_buf); value_len = 2; ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); - todo_wine ok(strcmp(value_buf, "C") == 0, "Expected name "C", got %s\n", value_buf); + ok(strcmp(value_buf, "C") == 0, "Expected name "C", got %s\n", value_buf); value_len = 2; ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); - todo_wine ok(strcmp(value_buf, "D") == 0, "Expected name "D", got %s\n", value_buf); + ok(strcmp(value_buf, "D") == 0, "Expected name "D", got %s\n", value_buf); value_len = 2; ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); - todo_wine ok(strcmp(value_buf, "B") == 0, "Expected name "B", got %s\n", value_buf); + ok(strcmp(value_buf, "B") == 0, "Expected name "B", got %s\n", value_buf); + + res = RegDeleteValueA( hKey, "C" ); + ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", res); + ok(!RegSetValueExA(hKey, "C", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)), + "RegSetValueExA for value "C" failed\n"); + + value_len = 2; + ok(!RegEnumValueA(hKey, 0, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); + ok(strcmp(value_buf, "A") == 0, "Expected name "A", got %s\n", value_buf); + value_len = 2; + ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); + ok(strcmp(value_buf, "D") == 0, "Expected name "D", got %s\n", value_buf); + value_len = 2; + ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); + ok(strcmp(value_buf, "B") == 0, "Expected name "B", got %s\n", value_buf); + value_len = 2; + ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); + ok(strcmp(value_buf, "C") == 0, "Expected name "C", got %s\n", value_buf);
ok(!RegDeleteKeyA(HKEY_CURRENT_USER, keyname), "Failed to delete key\n"); } diff --git a/server/registry.c b/server/registry.c index c60c737feff..4d544844df4 100644 --- a/server/registry.c +++ b/server/registry.c @@ -110,6 +110,7 @@ struct key_value unsigned int type; /* value type */ data_size_t len; /* value data length in bytes */ void *data; /* pointer to value data */ + unsigned int order; };
#define MIN_SUBKEYS 8 /* min. number of allocated subkeys per key */ @@ -1165,6 +1166,7 @@ static struct key_value *insert_value( struct key *key, const struct unicode_str value->namelen = name->len; value->len = 0; value->data = NULL; + value->order = key->last_value; return value; }
@@ -1251,7 +1253,7 @@ static void get_value( struct key *key, const struct unicode_str *name, int *typ /* enumerate a key value */ static void enum_value( struct key *key, int i, int info_class, struct enum_key_value_reply *reply ) { - struct key_value *value; + struct key_value *value = NULL;
if (key->flags & KEY_PREDEF) { @@ -1264,8 +1266,21 @@ static void enum_value( struct key *key, int i, int info_class, struct enum_key_ { void *data; data_size_t namelen, maxlen; + for(int j = 0; j <= key->last_value; j++) + { + if (key->values[j].order == i) + { + value = &key->values[j]; + break; + } + } + + if (!value) + { + set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + return; + }
- value = &key->values[i]; reply->type = value->type; namelen = value->namelen;
@@ -1310,6 +1325,7 @@ static void delete_value( struct key *key, const struct unicode_str *name ) { struct key_value *value; int i, index, nb_values; + int order;
if (key->flags & KEY_PREDEF) { @@ -1323,9 +1339,18 @@ static void delete_value( struct key *key, const struct unicode_str *name ) return; } if (debug_level > 1) dump_operation( key, value, "Delete" ); + order = value->order; free( value->name ); free( value->data ); - for (i = index; i < key->last_value; i++) key->values[i] = key->values[i + 1]; + for (i = index; i < key->last_value; i++) + { + if (key->values[i].order > order) key->values[i].order--; + key->values[i] = key->values[i + 1]; + } + for (int j = 0; j <= index; j++) + { + if (key->values[j].order > order) key->values[j].order--; + } key->last_value--; touch_key( key, REG_NOTIFY_CHANGE_LAST_SET );
From: Haoyang Chen chenhaoyang@kylinos.cn
--- server/registry.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/server/registry.c b/server/registry.c index 4d544844df4..bda381a37d4 100644 --- a/server/registry.c +++ b/server/registry.c @@ -242,7 +242,9 @@ static void dump_value( const struct key_value *value, FILE *f ) { fputc( '"', f ); count = 1 + dump_strW( value->name, value->namelen, f, """" ); - count += fprintf( f, ""=" ); + count += fprintf( f, ""$" ); + count += fprintf( f, "%x", value->order ); + fputc( '=', f ); } else count = fprintf( f, "@=" );
@@ -1144,7 +1146,7 @@ static struct key_value *find_value( const struct key *key, const struct unicode }
/* insert a new value; the index must have been returned by find_value */ -static struct key_value *insert_value( struct key *key, const struct unicode_str *name, int index ) +static struct key_value *insert_value( struct key *key, const struct unicode_str *name, int index, int order ) { struct key_value *value; WCHAR *new_name = NULL; @@ -1166,7 +1168,7 @@ static struct key_value *insert_value( struct key *key, const struct unicode_str value->namelen = name->len; value->len = 0; value->data = NULL; - value->order = key->last_value; + value->order = order == -1 ? key->last_value : order; return value; }
@@ -1209,7 +1211,7 @@ static void set_value( struct key *key, const struct unicode_str *name,
if (!value) { - if (!(value = insert_value( key, name, index ))) + if (!(value = insert_value( key, name, index, -1 ))) { free( ptr ); return; @@ -1614,6 +1616,8 @@ static struct key_value *parse_value_name( struct key *key, const char *buffer, struct key_value *value; struct unicode_str name; int index; + char buf[512] = {0}; + int order = -1;
if (!get_file_tmp_space( info, strlen(buffer) * sizeof(WCHAR) )) return NULL; name.str = info->tmp; @@ -1631,10 +1635,22 @@ static struct key_value *parse_value_name( struct key *key, const char *buffer, name.len -= sizeof(WCHAR); /* terminating null */ } while (isspace(buffer[*len])) (*len)++; + if (buffer[*len] == '$'){ + const char *order_start = buffer + *len + 1; + int i = 0; + while(order_start[i] != '=') { + buf[i] = order_start[i]; + if (!isxdigit(buf[i])) goto error; + i++; + } + if (!i) goto error; + order = strtoul( buf, NULL, 16 ); + (*len) += i + 1; + } if (buffer[*len] != '=') goto error; (*len)++; while (isspace(buffer[*len])) (*len)++; - if (!(value = find_value( key, &name, &index ))) value = insert_value( key, &name, index ); + if (!(value = find_value( key, &name, &index ))) value = insert_value( key, &name, index , order ); return value;
error: