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(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 169 /* Unit tests */ 170 171 static void test_export(void) 172 { 173 LONG err; 174 DWORD r, dword, type, size; 175 HKEY hkey, subkey; 176 BYTE hex[4], buffer[8]; 177 178 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 179 180 run_reg_exe("reg export", &r); 181 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 182 183 run_reg_exe("reg export /?", &r); 184 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 185 186 run_reg_exe("reg export /h", &r); 187 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 188 189 run_reg_exe("reg export -H", &r); 190 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 191 192 run_reg_exe("reg export \\\\remote-pc\\HKLM\\Wine file.reg", &r); 193 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 194 195 run_reg_exe("reg export HKEY_DYN_DATA file.reg", &r); 196 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 197 198 run_reg_exe("reg export HKDD 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_CURRENT_USER\\" KEY_BASE, &r); 202 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 203 204 run_reg_exe("reg export file.reg", &r); 205 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 206 207 run_reg_exe("reg export file.reg 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 HKEY_CURRENT_USER\\" KEY_BASE, &r); 211 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 212 213 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &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 " file.reg file2.reg", &r); 217 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 218 219 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /reg:32 /reg:32", &r); 220 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 221 222 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /reg:32 /reg:64", &r); 223 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 224 225 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /reg:64 /reg:64", &r); 226 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 227 228 /* Test registry export with an empty key */ 229 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 230 231 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); 232 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 233 ok(compare_export("file.reg", empty_key_test, 0), "compare_export() failed\n"); 234 235 run_reg_exe("reg export /y HKEY_CURRENT_USER\\" KEY_BASE " file.reg", &r); 236 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 237 238 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " /y file.reg", &r); 239 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 240 241 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 242 ok(r == REG_EXIT_SUCCESS || broken(r == REG_EXIT_FAILURE), /* winxp */ 243 "got exit code %d, expected 0\n", r); 244 ok(compare_export("file.reg", empty_key_test, 0), "compare_export() failed\n"); 245 246 /* Test registry export with a simple data structure */ 247 dword = 0x100; 248 add_value(hkey, "DWORD", REG_DWORD, &dword, sizeof(dword)); 249 add_value(hkey, "String", REG_SZ, "Your text here...", 18); 250 251 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 252 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 253 ok(compare_export("file.reg", simple_data_test, 0), "compare_export() failed\n"); 254 255 /* Test whether a .reg file extension is required when exporting */ 256 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " foo /y", &r); 257 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 258 ok(compare_export("foo", simple_data_test, 0), "compare_export() failed\n"); 259 260 /* Test registry export with a complex data structure */ 261 add_key(hkey, "Subkey1", 0, &subkey); 262 add_value(subkey, "Binary", REG_BINARY, "\x11\x22\x33\x44", 4); 263 add_value(subkey, "Undefined hex", 0x100, "%PATH%", 7); 264 close_key(subkey); 265 266 add_key(hkey, "Subkey2a", 0, &subkey); 267 add_value(subkey, "double\"quote", REG_SZ, "\"Hello, World!\"", 16); 268 dword = 0x8; 269 add_value(subkey, "single'quote", REG_DWORD, &dword, sizeof(dword)); 270 close_key(subkey); 271 272 add_key(hkey, "Subkey2a\\Subkey2b", 0, &subkey); 273 add_value(subkey, NULL, REG_SZ, "Default value name", 19); 274 add_value(subkey, "Multiple strings", REG_MULTI_SZ, "Line1\0Line2\0Line3\0", 19); 275 close_key(subkey); 276 277 add_key(hkey, "Subkey3a", 0, &subkey); 278 add_value(subkey, "Backslash", REG_SZ, "Use \\\\ to escape a backslash", 29); 279 close_key(subkey); 280 281 add_key(hkey, "Subkey3a\\Subkey3b\\Subkey3c", 0, &subkey); 282 add_value(subkey, "String expansion", REG_EXPAND_SZ, "%HOME%\\%PATH%", 14); 283 add_value(subkey, "Zero data type", REG_NONE, "Value", 6); 284 close_key(subkey); 285 286 add_key(hkey, "Subkey4", 0, &subkey); 287 dword = 0x12345678; 288 add_value(subkey, NULL, REG_DWORD, &dword, sizeof(dword)); 289 add_value(subkey, "43981", 0xabcd, "Value", 6); 290 close_key(subkey); 291 292 close_key(hkey); 293 294 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 295 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 296 ok(compare_export("file.reg", complex_data_test, 0), "compare_export() failed\n"); 297 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 298 299 /* Test the export order of registry keys */ 300 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 301 add_key(hkey, "Subkey2", 0, NULL); 302 add_key(hkey, "Subkey1", 0, NULL); 303 304 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 305 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 306 ok(compare_export("file.reg", key_order_test, 0), "compare_export() failed\n"); 307 delete_key(hkey, "Subkey1", 0); 308 delete_key(hkey, "Subkey2", 0); 309 310 /* Test the export order of registry values. Windows exports registry values 311 * in order of creation; Wine uses alphabetical order. 312 */ 313 add_value(hkey, "Value 2", REG_SZ, "I was added first!", 19); 314 add_value(hkey, "Value 1", REG_SZ, "I was added second!", 20); 315 close_key(hkey); 316 317 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 318 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 319 ok(compare_export("file.reg", value_order_test, TODO_REG_COMPARE), "compare_export() failed\n"); 320 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 321 322 /* Test registry export with empty hex data */ 323 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 324 add_value(hkey, "Wine1a", REG_NONE, NULL, 0); 325 add_value(hkey, "Wine1b", REG_SZ, NULL, 0); 326 add_value(hkey, "Wine1c", REG_EXPAND_SZ, NULL, 0); 327 add_value(hkey, "Wine1d", REG_BINARY, NULL, 0); 328 add_value(hkey, "Wine1e", REG_DWORD, NULL, 0); 329 add_value(hkey, "Wine1f", REG_MULTI_SZ, NULL, 0); 330 add_value(hkey, "Wine1g", 0x100, NULL, 0); 331 add_value(hkey, "Wine1h", 0xabcd, NULL, 0); 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", empty_hex_test, 0), "compare_export() failed\n"); 337 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 338 339 /* Test registry export after importing alternative registry data types */ 340 test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" 341 "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" 342 "\"Wine2a\"=hex(1):\n" 343 "\"Wine2b\"=hex(3):\n" 344 "\"Wine2c\"=hex(4):\n\n", &r); 345 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 346 open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 347 verify_reg(hkey, "Wine2a", REG_SZ, NULL, 0, 0); 348 verify_reg(hkey, "Wine2b", REG_BINARY, NULL, 0, 0); 349 verify_reg(hkey, "Wine2c", REG_DWORD, NULL, 0, 0); 350 close_key(hkey); 351 352 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 353 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 354 ok(compare_export("file.reg", empty_hex_test2, 0), "compare_export() failed\n"); 355 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 356 357 test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" 358 "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" 359 "\"Wine3a\"=hex(1):56,00,61,00,6c,00,75,00,65,00,00,00\n" 360 "\"Wine3b\"=hex(3):12,34,56,78\n" 361 "\"Wine3c\"=hex(4):40,30,20,10\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, "Wine3a", REG_SZ, "Value", 6, 0); 365 memcpy(hex, "\x12\x34\x56\x78", 4); 366 verify_reg(hkey, "Wine3b", REG_BINARY, hex, 4, 0); 367 dword = 0x10203040; 368 verify_reg(hkey, "Wine3c", REG_DWORD, &dword, sizeof(dword), 0); 369 close_key(hkey); 370 371 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 372 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 373 ok(compare_export("file.reg", hex_types_test, 0), "compare_export() failed\n"); 374 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 375 376 /* Test registry export with embedded null characters */ 377 test_import_wstr("\xef\xbb\xbfWindows Registry Editor Version 5.00\n\n" 378 "[HKEY_CURRENT_USER\\" KEY_BASE "]\n" 379 "\"Wine4a\"=dword:00000005\n" 380 "\"Wine4b\"=hex(1):00,00,00,00,00,00,00,00\n" 381 "\"Wine4c\"=\"Value\"\n" 382 "\"Wine4d\"=hex(1):00,00,61,00,62,00,63,00\n" 383 "\"Wine4e\"=dword:00000100\n" 384 "\"Wine4f\"=hex(1):00,00,56,00,61,00,6c,00,75,00,65,00,00,00\n" 385 "\"Wine4g\"=\"Value2\"\n" 386 "\"Wine4h\"=hex(1):61,00,62,00,63,00,00,00, \\\n" 387 " 64,00,65,00,66,00,00,00\n\n", &r); 388 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 389 open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 390 dword = 0x5; 391 verify_reg(hkey, "Wine4a", REG_DWORD, &dword, sizeof(dword), 0); 392 verify_reg(hkey, "Wine4b", REG_SZ, "\0\0\0\0\0\0\0", 4, 0); 393 verify_reg(hkey, "Wine4c", REG_SZ, "Value", 6, 0); 394 /* Wine4d */ 395 size = sizeof(buffer); 396 err = RegQueryValueExA(hkey, "Wine4d", NULL, &type, (BYTE *)&buffer, &size); 397 ok(err == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", err); 398 ok(type == REG_SZ, "got wrong type %u, expected %u\n", type, REG_SZ); 399 ok(size == 5 || broken(size == 4) /* WinXP */, "got wrong size %u, expected 5\n", size); 400 ok(memcmp(buffer, "\0abc", size) == 0, "got wrong data\n"); 401 dword = 0x100; 402 verify_reg(hkey, "Wine4e", REG_DWORD, &dword, sizeof(dword), 0); 403 verify_reg(hkey, "Wine4f", REG_SZ, "\0Value", 7, 0); 404 verify_reg(hkey, "Wine4g", REG_SZ, "Value2", 7, 0); 405 verify_reg(hkey, "Wine4h", REG_SZ, "abc\0def", 8, 0); 406 close_key(hkey); 407 408 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 409 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 410 ok(compare_export("file.reg", embedded_null_test, 0), "compare_export() failed\n"); 411 delete_key(HKEY_CURRENT_USER, KEY_BASE, 0); 412 413 /* Test registry export with forward and back slashes */ 414 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 415 add_key(hkey, "https://winehq.org", 0, NULL); 416 add_value(hkey, "count/up", REG_SZ, "one/two/three", 14); 417 add_value(hkey, "\\foo\\bar", REG_SZ, "", 1); 418 close_key(hkey); 419 420 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 421 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 422 ok(compare_export("file.reg", slashes_test, TODO_REG_COMPARE), "compare_export() failed\n"); 423 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 424 425 /* Test escaped null characters */ 426 add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey); 427 add_value(hkey, "Wine5a", REG_SZ, "\\0", 3); 428 add_value(hkey, "Wine5b", REG_SZ, "\\0\\0", 5); 429 add_value(hkey, "Wine5c", REG_SZ, "Value1\\0", 9); 430 add_value(hkey, "Wine5d", REG_SZ, "Value2\\0\\0\\0\\0", 15); 431 add_value(hkey, "Wine5e", REG_SZ, "Value3\\0Value4", 15); 432 add_value(hkey, "Wine5f", REG_SZ, "\\0Value5", 9); 433 close_key(hkey); 434 435 run_reg_exe("reg export HKEY_CURRENT_USER\\" KEY_BASE " file.reg /y", &r); 436 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 437 ok(compare_export("file.reg", escaped_null_test, 0), "compare_export() failed\n"); 438 delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0); 439 } 440 441 static void create_test_key(REGSAM sam) 442 { 443 HKEY hkey, subkey; 444 DWORD dword = 0x100; 445 446 add_key(HKEY_LOCAL_MACHINE, KEY_BASE, sam, &hkey); 447 add_value(hkey, "DWORD", REG_DWORD, &dword, sizeof(dword)); 448 add_value(hkey, "String", REG_SZ, "Your text here...", 18); 449 450 add_key(hkey, "Subkey1", sam, &subkey); 451 add_value(subkey, "Binary", REG_BINARY, "\x11\x22\x33\x44", 4); 452 add_value(subkey, "Undefined hex", 0x100, "%PATH%", 7); 453 close_key(subkey); 454 455 close_key(hkey); 456 } 457 458 static const char *registry_view_test = 459 "\xef\xbb\xbfWindows Registry Editor Version 5.00\r\n\r\n" 460 "[HKEY_LOCAL_MACHINE\\" KEY_BASE "]\r\n" 461 "\"DWORD\"=dword:00000100\r\n" 462 "\"String\"=\"Your text here...\"\r\n\r\n" 463 "[HKEY_LOCAL_MACHINE\\" KEY_BASE "\\Subkey1]\r\n" 464 "\"Binary\"=hex:11,22,33,44\r\n" 465 "\"Undefined hex\"=hex(100):25,50,41,54,48,25,00\r\n\r\n"; 466 467 static void test_registry_view_win32(void) 468 { 469 DWORD r; 470 BOOL is_wow64, is_win32; 471 472 IsWow64Process(GetCurrentProcess(), &is_wow64); 473 is_win32 = !is_wow64 && (sizeof(void *) == sizeof(int)); 474 475 if (!is_win32) return; 476 477 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 478 479 /* Try exporting from the 32-bit registry view (32-bit Windows) */ 480 create_test_key(KEY_WOW64_32KEY); 481 482 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 483 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 484 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 485 486 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 487 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 488 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 489 490 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 491 492 /* Try exporting from the 64-bit registry view, which doesn't exist on 32-bit Windows */ 493 create_test_key(KEY_WOW64_64KEY); 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 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 500 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 501 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 502 503 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 504 } 505 506 static void test_registry_view_win64(void) 507 { 508 DWORD r; 509 BOOL is_wow64, is_win64; 510 511 IsWow64Process(GetCurrentProcess(), &is_wow64); 512 is_win64 = !is_wow64 && (sizeof(void *) > sizeof(int)); 513 514 if (!is_win64) return; 515 516 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 517 518 /* Try exporting from the 32-bit registry view (64-bit Windows) */ 519 create_test_key(KEY_WOW64_32KEY); 520 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 521 522 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 523 todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 524 todo_wine ok(compare_export("file.reg", registry_view_test, TODO_REG_COMPARE), "compare_export() failed\n"); 525 526 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 527 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 528 529 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 530 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 531 532 /* Try exporting from the 64-bit registry view (64-bit Windows) */ 533 create_test_key(KEY_WOW64_64KEY); 534 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 535 536 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 537 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 538 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 539 540 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 541 todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 542 543 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 544 } 545 546 static void test_registry_view_wow64(void) 547 { 548 DWORD r; 549 BOOL is_wow64; 550 551 IsWow64Process(GetCurrentProcess(), &is_wow64); 552 553 if (!is_wow64) return; 554 555 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 556 557 /* Try exporting from the 32-bit registry view (WOW64) */ 558 create_test_key(KEY_WOW64_32KEY); 559 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 560 561 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 562 ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 563 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 564 565 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 566 todo_wine ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 567 568 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 569 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 570 571 /* Try exporting from the 64-bit registry view (WOW64) */ 572 create_test_key(KEY_WOW64_64KEY); 573 verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY); 574 575 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:64", &r); 576 todo_wine ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r); 577 ok(compare_export("file.reg", registry_view_test, 0), "compare_export() failed\n"); 578 579 run_reg_exe("reg export HKEY_LOCAL_MACHINE\\" KEY_BASE " file.reg /y /reg:32", &r); 580 ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r); 581 582 delete_tree(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY); 583 } 584 585 START_TEST(export) 586 { 587 DWORD r; 588 589 if (!run_reg_exe("reg.exe /?", &r)) { 590 win_skip("reg.exe not available, skipping 'export' tests\n"); 591 return; 592 } 593 594 test_export(); 595 596 /* Check if reg.exe is running with elevated privileges */ 597 if (!is_elevated_process()) 598 { 599 win_skip("reg.exe is not running with elevated privileges; " 600 "skipping registry view tests\n"); 601 return; 602 } 603 604 test_registry_view_win32(); 605 test_registry_view_win64(); 606 test_registry_view_wow64(); 607 } 608