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 );
Will this order marker survive registry save and load?
On Tue Feb 18 07:45:07 2025 +0000, Nikolay Sivov wrote:
Will this order marker survive registry save and load?
Indeed, this order needs to be stored in a file or it fails. An order needs to be added to each value, and I will provide a version of this at the right time.