1 /* 2 * Copyright 2017-2018, 2021 Hugh McMaster 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "reg_test.h" 20 21 BOOL compare_export_(const char *file, unsigned line, const char *filename, 22 const char *expected, DWORD todo) 23 { 24 FILE *fp; 25 long file_size; 26 WCHAR *fbuf = NULL, *wstr = NULL; 27 size_t len; 28 BOOL ret = FALSE; 29 30 fp = fopen(filename, "rb"); 31 if (!fp) return FALSE; 32 33 if (fseek(fp, 0, SEEK_END)) goto error; 34 file_size = ftell(fp); 35 if (file_size == -1) goto error; 36 rewind(fp); 37 38 fbuf = HeapAlloc(GetProcessHeap(), 0, file_size + sizeof(WCHAR)); 39 if (!fbuf) goto error; 40 41 fread(fbuf, file_size, 1, fp); 42 fbuf[file_size/sizeof(WCHAR)] = 0; 43 fclose(fp); 44 45 len = MultiByteToWideChar(CP_UTF8, 0, expected, -1, NULL, 0); 46 wstr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 47 if (!wstr) goto exit; 48 MultiByteToWideChar(CP_UTF8, 0, expected, -1, wstr, len); 49 50 todo_wine_if (todo & TODO_REG_COMPARE) 51 lok(!lstrcmpW(fbuf, wstr), "export data does not match expected data\n"); 52 53 ret = delete_file_(file, line, filename); 54 55 exit: 56 HeapFree(GetProcessHeap(), 0, fbuf); 57 HeapFree(GetProcessHeap(), 0, wstr); 58 return ret; 59 60 error: 61 fclose(fp); 62 return FALSE; 63 } 64 65 const char *empty_key_test = 66 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 67 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n\r\n"; 68 69 const char *simple_data_test = 70 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 71 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 72 "\"DWORD\"=dword:00000100\r\n" 73 "\"String\"=\"Your text here...\"\r\n\r\n"; 74 75 const char *complex_data_test = 76 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 77 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 78 "\"DWORD\"=dword:00000100\r\n" 79 "\"String\"=\"Your text here...\"\r\n\r\n" 80 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey1]\r\n" 81 "\"Binary\"=hex:11,22,33,44\r\n" 82 "\"Undefined hex\"=hex(100):25,50,41,54,48,25,00\r\n\r\n" 83 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey2a]\r\n" 84 "\"double\\\"quote\"=\"\\\"Hello, World!\\\"\"\r\n" 85 "\"single'quote\"=dword:00000008\r\n\r\n" 86 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey2a\\Subkey2b]\r\n" 87 "@=\"Default value name\"\r\n" 88 "\"Multiple strings\"=hex(7):4c,00,69,00,6e,00,65,00,31,00,00,00,4c,00,69,00,6e,\\\r\n" 89 " 00,65,00,32,00,00,00,4c,00,69,00,6e,00,65,00,33,00,00,00,00,00\r\n\r\n" 90 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey3a]\r\n" 91 "\"Backslash\"=\"Use \\\\\\\\ to escape a backslash\"\r\n\r\n" 92 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey3a\\Subkey3b]\r\n\r\n" 93 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey3a\\Subkey3b\\Subkey3c]\r\n" 94 "\"String expansion\"=hex(2):25,00,48,00,4f,00,4d,00,45,00,25,00,5c,00,25,00,50,\\\r\n" 95 " 00,41,00,54,00,48,00,25,00,00,00\r\n" 96 "\"Zero data type\"=hex(0):56,61,6c,75,65,00\r\n\r\n" 97 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey4]\r\n" 98 "@=dword:12345678\r\n" 99 "\"43981\"=hex(abcd):56,61,6c,75,65,00\r\n\r\n"; 100 101 const char *key_order_test = 102 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 103 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n\r\n" 104 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey1]\r\n\r\n" 105 "[HKEY_CURRENT_USER\\" KEY_BASE "\\Subkey2]\r\n\r\n"; 106 107 const char *value_order_test = 108 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 109 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 110 "\"Value 2\"=\"I was added first!\"\r\n" 111 "\"Value 1\"=\"I was added second!\"\r\n\r\n"; 112 113 const char *empty_hex_test = 114 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 115 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 116 "\"Wine1a\"=hex(0):\r\n" 117 "\"Wine1b\"=\"\"\r\n" 118 "\"Wine1c\"=hex(2):\r\n" 119 "\"Wine1d\"=hex:\r\n" 120 "\"Wine1e\"=hex(4):\r\n" 121 "\"Wine1f\"=hex(7):\r\n" 122 "\"Wine1g\"=hex(100):\r\n" 123 "\"Wine1h\"=hex(abcd):\r\n\r\n"; 124 125 const char *empty_hex_test2 = 126 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 127 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 128 "\"Wine2a\"=\"\"\r\n" 129 "\"Wine2b\"=hex:\r\n" 130 "\"Wine2c\"=hex(4):\r\n\r\n"; 131 132 const char *hex_types_test = 133 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 134 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 135 "\"Wine3a\"=\"Value\"\r\n" 136 "\"Wine3b\"=hex:12,34,56,78\r\n" 137 "\"Wine3c\"=dword:10203040\r\n\r\n"; 138 139 const char *embedded_null_test = 140 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 141 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 142 "\"Wine4a\"=dword:00000005\r\n" 143 "\"Wine4b\"=\"\"\r\n" 144 "\"Wine4c\"=\"Value\"\r\n" 145 "\"Wine4d\"=\"\"\r\n" 146 "\"Wine4e\"=dword:00000100\r\n" 147 "\"Wine4f\"=\"\"\r\n" 148 "\"Wine4g\"=\"Value2\"\r\n" 149 "\"Wine4h\"=\"abc\"\r\n\r\n"; 150 151 const char *slashes_test = 152 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 153 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 154 "\"count/up\"=\"one/two/three\"\r\n" 155 "\"\\\\foo\\\\bar\"=\"\"\r\n\r\n" 156 "[HKEY_CURRENT_USER\\" KEY_BASE "\\https://winehq.org]\r\n\r\n"; 157 158 const char *escaped_null_test = 159 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 160 "[HKEY_CURRENT_USER\\" KEY_BASE "]\r\n" 161 "\"Wine5a\"=\"\\\\0\"\r\n" 162 "\"Wine5b\"=\"\\\\0\\\\0\"\r\n" 163 "\"Wine5c\"=\"Value1\\\\0\"\r\n" 164 "\"Wine5d\"=\"Value2\\\\0\\\\0\\\\0\\\\0\"\r\n" 165 "\"Wine5e\"=\"Value3\\\\0Value4\"\r\n" 166 "\"Wine5f\"=\"\\\\0Value5\"\r\n\r\n"; 167 168 const char *registry_view_test = 169 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 170 "[HKEY_LOCAL_MACHINE\\" KEY_BASE "]\r\n" 171 "\"DWORD\"=dword:00000100\r\n" 172 "\"String\"=\"Your text here...\"\r\n\r\n" 173 "[HKEY_LOCAL_MACHINE\\" KEY_BASE "\\Subkey1]\r\n" 174 "\"Binary\"=hex:11,22,33,44\r\n" 175 "\"Undefined hex\"=hex(100):25,50,41,54,48,25,00\r\n\r\n"; 176 177 178 /* Unit tests */ 179 180 static void test_command_syntax(void) 181 { 182 DWORD r; 183 184 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 185 186 run_reg_exe("reg export", &r); 187 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 188 189 run_reg_exe("reg export /?", &r); 190 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 191 192 run_reg_exe("reg export /h", &r); 193 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 194 195 run_reg_exe("reg export -H", &r); 196 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 197 198 run_reg_exe("reg export \\\\remote-pc\\HKLM\\Wine file.reg", &r); 199 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 200 201 run_reg_exe("reg export HKEY_DYN_DATA file.reg", &r); 202 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 203 204 run_reg_exe("reg export HKDD file.reg", &r); 205 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 206 207 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE, &r); 208 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 209 210 run_reg_exe("reg export file.reg", &r); 211 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 212 213 run_reg_exe("reg export file.reg HKEY_CURRENT_USER\\" KEY_BASE, &r); 214 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 215 216 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE, &r); 217 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 218 219 /* This test fails because the registry key doesn't exist */ 220 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); 221 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 222 223 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg file2.reg", &r); 224 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 225 226 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /reg:32 /reg:32", &r); 227 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 228 229 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /reg:32 /reg:64", &r); 230 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 231 232 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /reg:64 /reg:64", &r); 233 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 234 } 235 236 static void test_export(void) 237 { 238 LONG err; 239 DWORD r, dword, type, size; 240 HKEY hkey, subkey; 241 BYTE hex[4], buffer[8]; 242 243 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 244 245 /* Test registry export with an empty key */ 246 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 247 248 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); 249 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 250 ok(compare_export("file.reg", empty_key_test, 0), "compare_export() failed\n"); 251 252 run_reg_exe("reg export /y HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); 253 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 254 255 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " /y file.reg", &r); 256 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 257 258 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 259 ok(r == REG_EXIT_SUCCESS || broken(r == REG_EXIT_FAILURE), /* winxp */ 260 "got exit code %d, expected 0\n", r); 261 ok(compare_export("file.reg", empty_key_test, 0), "compare_export() failed\n"); 262 263 /* Test registry export with a simple data structure */ 264 dword = 0x100; 265 add_value(hkey, "DWORD", REG_DWORD, &dword, sizeof(dword)); 266 add_value(hkey, "String", REG_SZ, "Your text here...", 18); 267 268 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 269 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 270 ok(compare_export("file.reg", simple_data_test, 0), "compare_export() failed\n"); 271 272 /* Test whether a .reg file extension is required when exporting */ 273 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " foo /y", &r); 274 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 275 ok(compare_export("foo", simple_data_test, 0), "compare_export() failed\n"); 276 277 /* Test registry export with a complex data structure */ 278 add_key(hkey, "Subkey1", 0, &subkey); 279 add_value(subkey, "Binary", REG_BINARY, "\x11\x22\x33\x44", 4); 280 add_value(subkey, "Undefined hex", 0x100, "%PATH%", 7); 281 close_key(subkey); 282 283 add_key(hkey, "Subkey2a", 0, &subkey); 284 add_value(subkey, "double\"quote", REG_SZ, "\"Hello, World!\"", 16); 285 dword = 0x8; 286 add_value(subkey, "single'quote", REG_DWORD, &dword, sizeof(dword)); 287 close_key(subkey); 288 289 add_key(hkey, "Subkey2a\\Subkey2b", 0, &subkey); 290 add_value(subkey, NULL, REG_SZ, "Default value name", 19); 291 add_value(subkey, "Multiple strings", REG_MULTI_SZ, "Line1\0Line2\0Line3\0", 19); 292 close_key(subkey); 293 294 add_key(hkey, "Subkey3a", 0, &subkey); 295 add_value(subkey, "Backslash", REG_SZ, "Use \\\\ to escape a backslash", 29); 296 close_key(subkey); 297 298 add_key(hkey, "Subkey3a\\Subkey3b\\Subkey3c", 0, &subkey); 299 add_value(subkey, "String expansion", REG_EXPAND_SZ, "%HOME%\\%PATH%", 14); 300 add_value(subkey, "Zero data type", REG_NONE, "Value", 6); 301 close_key(subkey); 302 303 add_key(hkey, "Subkey4", 0, &subkey); 304 dword = 0x12345678; 305 add_value(subkey, NULL, REG_DWORD, &dword, sizeof(dword)); 306 add_value(subkey, "43981", 0xabcd, "Value", 6); 307 close_key(subkey); 308 309 close_key(hkey); 310 311 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 312 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 313 ok(compare_export("file.reg", complex_data_test, 0), "compare_export() failed\n"); 314 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 315 316 /* Test the export order of registry keys */ 317 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 318 add_key(hkey, "Subkey2", 0, NULL); 319 add_key(hkey, "Subkey1", 0, NULL); 320 321 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 322 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 323 ok(compare_export("file.reg", key_order_test, 0), "compare_export() failed\n"); 324 delete_key(hkey, "Subkey1", 0); 325 delete_key(hkey, "Subkey2", 0); 326 327 /* Test the export order of registry values. Windows exports registry values 328 * in order of creation; Wine uses alphabetical order. 329 */ 330 add_value(hkey, "Value 2", REG_SZ, "I was added first!", 19); 331 add_value(hkey, "Value 1", REG_SZ, "I was added second!", 20); 332 close_key(hkey); 333 334 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 335 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 336 ok(compare_export("file.reg", value_order_test, TODO_REG_COMPARE), "compare_export() failed\n"); 337 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 338 339 /* Test registry export with empty hex data */ 340 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 341 add_value(hkey, "Wine1a", REG_NONE, NULL, 0); 342 add_value(hkey, "Wine1b", REG_SZ, NULL, 0); 343 add_value(hkey, "Wine1c", REG_EXPAND_SZ, NULL, 0); 344 add_value(hkey, "Wine1d", REG_BINARY, NULL, 0); 345 add_value(hkey, "Wine1e", REG_DWORD, NULL, 0); 346 add_value(hkey, "Wine1f", REG_MULTI_SZ, NULL, 0); 347 add_value(hkey, "Wine1g", 0x100, NULL, 0); 348 add_value(hkey, "Wine1h", 0xabcd, NULL, 0); 349 close_key(hkey); 350 351 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 352 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 353 ok(compare_export("file.reg", empty_hex_test, 0), "compare_export() failed\n"); 354 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 355 356 /* Test registry export after importing alternative registry data types */ 357 test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" 358 "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" 359 "\"Wine2a\"=hex(1):\n" 360 "\"Wine2b\"=hex(3):\n" 361 "\"Wine2c\"=hex(4):\n\n", &r); 362 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 363 open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 364 verify_reg(hkey, "Wine2a", REG_SZ, NULL, 0, 0); 365 verify_reg(hkey, "Wine2b", REG_BINARY, NULL, 0, 0); 366 verify_reg(hkey, "Wine2c", REG_DWORD, NULL, 0, 0); 367 close_key(hkey); 368 369 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 370 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 371 ok(compare_export("file.reg", empty_hex_test2, 0), "compare_export() failed\n"); 372 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 373 374 test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" 375 "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" 376 "\"Wine3a\"=hex(1):56,00,61,00,6c,00,75,00,65,00,00,00\n" 377 "\"Wine3b\"=hex(3):12,34,56,78\n" 378 "\"Wine3c\"=hex(4):40,30,20,10\n\n", &r); 379 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 380 open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 381 verify_reg(hkey, "Wine3a", REG_SZ, "Value", 6, 0); 382 memcpy(hex, "\x12\x34\x56\x78", 4); 383 verify_reg(hkey, "Wine3b", REG_BINARY, hex, 4, 0); 384 dword = 0x10203040; 385 verify_reg(hkey, "Wine3c", REG_DWORD, &dword, sizeof(dword), 0); 386 close_key(hkey); 387 388 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 389 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 390 ok(compare_export("file.reg", hex_types_test, 0), "compare_export() failed\n"); 391 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 392 393 /* Test registry export with embedded null characters */ 394 test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" 395 "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" 396 "\"Wine4a\"=dword:00000005\n" 397 "\"Wine4b\"=hex(1):00,00,00,00,00,00,00,00\n" 398 "\"Wine4c\"=\"Value\"\n" 399 "\"Wine4d\"=hex(1):00,00,61,00,62,00,63,00\n" 400 "\"Wine4e\"=dword:00000100\n" 401 "\"Wine4f\"=hex(1):00,00,56,00,61,00,6c,00,75,00,65,00,00,00\n" 402 "\"Wine4g\"=\"Value2\"\n" 403 "\"Wine4h\"=hex(1):61,00,62,00,63,00,00,00, \\\n" 404 " 64,00,65,00,66,00,00,00\n\n", &r); 405 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 406 open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 407 dword = 0x5; 408 verify_reg(hkey, "Wine4a", REG_DWORD, &dword, sizeof(dword), 0); 409 verify_reg(hkey, "Wine4b", REG_SZ, "\0\0\0\0\0\0\0", 4, 0); 410 verify_reg(hkey, "Wine4c", REG_SZ, "Value", 6, 0); 411 /* Wine4d */ 412 size = sizeof(buffer); 413 err = RegQueryValueExA(hkey, "Wine4d", NULL, &type, (BYTE *)&buffer, &size); 414 ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); 415 ok(type == REG_SZ, "got wrong type %u, expected %u\n", type, REG_SZ); 416 ok(size == 5 || broken(size == 4) /* WinXP */, "got wrong size %u, expected 5\n", size); 417 ok(memcmp(buffer, "\0abc", size) == 0, "got wrong data\n"); 418 dword = 0x100; 419 verify_reg(hkey, "Wine4e", REG_DWORD, &dword, sizeof(dword), 0); 420 verify_reg(hkey, "Wine4f", REG_SZ, "\0Value", 7, 0); 421 verify_reg(hkey, "Wine4g", REG_SZ, "Value2", 7, 0); 422 verify_reg(hkey, "Wine4h", REG_SZ, "abc\0def", 8, 0); 423 close_key(hkey); 424 425 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 426 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 427 ok(compare_export("file.reg", embedded_null_test, 0), "compare_export() failed\n"); 428 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 429 430 /* Test registry export with forward and back slashes */ 431 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 432 add_key(hkey, "https://winehq.org", 0, NULL); 433 add_value(hkey, "count/up", REG_SZ, "one/two/three", 14); 434 add_value(hkey, "\\foo\\bar", REG_SZ, "", 1); 435 close_key(hkey); 436 437 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 438 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 439 ok(compare_export("file.reg", slashes_test, TODO_REG_COMPARE), "compare_export() failed\n"); 440 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 441 442 /* Test escaped null characters */ 443 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 444 add_value(hkey, "Wine5a", REG_SZ, "\\0", 3); 445 add_value(hkey, "Wine5b", REG_SZ, "\\0\\0", 5); 446 add_value(hkey, "Wine5c", REG_SZ, "Value1\\0", 9); 447 add_value(hkey, "Wine5d", REG_SZ, "Value2\\0\\0\\0\\0", 15); 448 add_value(hkey, "Wine5e", REG_SZ, "Value3\\0Value4", 15); 449 add_value(hkey, "Wine5f", REG_SZ, "\\0Value5", 9); 450 close_key(hkey); 451 452 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 453 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 454 ok(compare_export("file.reg", escaped_null_test, 0), "compare_export() failed\n"); 455 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 456 } 457 458 #if 0 459 static void create_test_key(REGSAM sam) 460 { 461 HKEY hkey, subkey; 462 DWORD dword = 0x100; 463 464 add_key(HKEY_LOCAL_MACHINE, KEY_BASE, sam, &hkey); 465 add_value(hkey, "DWORD", REG_DWORD, &dword, sizeof(dword)); 466 add_value(hkey, "String", REG_SZ, "Your text here...", 18); 467 468 add_key(hkey, "Subkey1", sam, &subkey); 469 add_value(subkey, "Binary", REG_BINARY, "\x11\x22\x33\x44", 4); 470 add_value(subkey, "Undefined hex", 0x100, "%PATH%", 7); 471 close_key(subkey); 472 473 close_key(hkey); 474 } 475 476 static void test_registry_view_win32(void) 477 { 478 DWORD r; 479 BOOL is_wow64, is_win32; 480 481 IsWow64Process(GetCurrentProcess(), &is_wow64); 482 is_win32 = !is_wow64 && (sizeof(void *) == sizeof(int)); 483 484 if (!is_win32) return; 485 486 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 487 488 /* Try exporting from the 32-bit registry view (32-bit Windows) */ 489 create_test_key(KEY_WOW64_32KEY); 490 491 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 492 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 493 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 494 495 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 496 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 497 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 498 499 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 500 501 /* Try exporting from the 64-bit registry view, which doesn't exist on 32-bit Windows */ 502 create_test_key(KEY_WOW64_64KEY); 503 504 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 505 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 506 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 507 508 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 509 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 510 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 511 512 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 513 } 514 515 static void test_registry_view_win64(void) 516 { 517 DWORD r; 518 BOOL is_wow64, is_win64; 519 520 IsWow64Process(GetCurrentProcess(), &is_wow64); 521 is_win64 = !is_wow64 && (sizeof(void *) > sizeof(int)); 522 523 if (!is_win64) return; 524 525 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 526 527 /* Try exporting from the 32-bit registry view (64-bit Windows) */ 528 create_test_key(KEY_WOW64_32KEY); 529 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 530 531 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 532 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 533 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 534 535 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 536 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 537 538 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 539 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 540 541 /* Try exporting from the 64-bit registry view (64-bit Windows) */ 542 create_test_key(KEY_WOW64_64KEY); 543 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 544 545 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 546 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 547 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 548 549 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 550 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 551 552 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 553 } 554 555 static void test_registry_view_wow64(void) 556 { 557 DWORD r; 558 BOOL is_wow64; 559 560 IsWow64Process(GetCurrentProcess(), &is_wow64); 561 562 if (!is_wow64) return; 563 564 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 565 566 /* Try exporting from the 32-bit registry view (WOW64) */ 567 create_test_key(KEY_WOW64_32KEY); 568 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 569 570 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 571 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 572 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 573 574 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 575 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 576 577 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 578 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 579 580 /* Try exporting from the 64-bit registry view (WOW64) */ 581 create_test_key(KEY_WOW64_64KEY); 582 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 583 584 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 585 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 586 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 587 588 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 589 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 590 591 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 592 } 593 #endif 594 595 START_TEST(export) 596 { 597 DWORD r; 598 599 if (!run_reg_exe("reg.exe /?", &r)) { 600 win_skip("reg.exe not available, skipping 'export' tests\n"); 601 return; 602 } 603 604 test_command_syntax(); 605 test_export(); 606 607 /* Check if reg.exe is running with elevated privileges */ 608 if (!is_elevated_process()) 609 { 610 win_skip("reg.exe is not running with elevated privileges; " 611 "skipping registry view tests\n"); 612 return; 613 } 614 615 #if 0 616 test_registry_view_win32(); 617 test_registry_view_win64(); 618 test_registry_view_wow64(); 619 #endif 620 621 } 622