edit.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. * Registry editing UI functions.
  3. *
  4. * Copyright (C) 2003 Dimitrie O. Paun
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include <commdlg.h>
  24. #include <cderr.h>
  25. #include <stdlib.h>
  26. #include <shellapi.h>
  27. #include <shlwapi.h>
  28. #include "wine/heap.h"
  29. #include "main.h"
  30. static const WCHAR* editValueName;
  31. static WCHAR* stringValueData;
  32. static BOOL isDecimal;
  33. struct edit_params
  34. {
  35. HKEY hkey;
  36. const WCHAR *value_name;
  37. DWORD type;
  38. void *data;
  39. DWORD size;
  40. };
  41. static int vmessagebox(HWND hwnd, int buttons, int titleId, int resId, va_list va_args)
  42. {
  43. WCHAR title[256];
  44. WCHAR fmt[1024];
  45. WCHAR *str;
  46. int ret;
  47. LoadStringW(hInst, titleId, title, ARRAY_SIZE(title));
  48. LoadStringW(hInst, resId, fmt, ARRAY_SIZE(fmt));
  49. FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  50. fmt, 0, 0, (WCHAR *)&str, 0, &va_args);
  51. ret = MessageBoxW(hwnd, str, title, buttons);
  52. LocalFree(str);
  53. return ret;
  54. }
  55. int WINAPIV messagebox(HWND hwnd, int buttons, int titleId, int resId, ...)
  56. {
  57. va_list ap;
  58. INT result;
  59. va_start(ap, resId);
  60. result = vmessagebox(hwnd, buttons, titleId, resId, ap);
  61. va_end(ap);
  62. return result;
  63. }
  64. static void WINAPIV error_code_messagebox(HWND hwnd, unsigned int msg_id, ...)
  65. {
  66. va_list ap;
  67. va_start(ap, msg_id);
  68. vmessagebox(hwnd, MB_OK|MB_ICONERROR, IDS_ERROR, msg_id, ap);
  69. va_end(ap);
  70. }
  71. static BOOL change_dword_base(HWND hwndDlg, BOOL toHex)
  72. {
  73. WCHAR buf[128];
  74. DWORD val;
  75. if (!GetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, buf, ARRAY_SIZE(buf))) return FALSE;
  76. if (!swscanf(buf, toHex ? L"%u" : L"%x", &val)) return FALSE;
  77. wsprintfW(buf, toHex ? L"%x" : L"%u", val);
  78. return SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, buf);
  79. }
  80. static INT_PTR CALLBACK modify_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  81. {
  82. HWND hwndValue;
  83. int len;
  84. switch(uMsg) {
  85. case WM_INITDIALOG:
  86. SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, editValueName);
  87. SetDlgItemTextW(hwndDlg, IDC_VALUE_DATA, stringValueData);
  88. CheckRadioButton(hwndDlg, IDC_DWORD_HEX, IDC_DWORD_DEC, IDC_DWORD_HEX);
  89. isDecimal = FALSE;
  90. return TRUE;
  91. case WM_COMMAND:
  92. switch (LOWORD(wParam)) {
  93. case IDC_DWORD_HEX:
  94. if (isDecimal && change_dword_base(hwndDlg, TRUE)) isDecimal = FALSE;
  95. break;
  96. case IDC_DWORD_DEC:
  97. if (!isDecimal && change_dword_base(hwndDlg, FALSE)) isDecimal = TRUE;
  98. break;
  99. case IDOK:
  100. if ((hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_DATA))) {
  101. len = GetWindowTextLengthW(hwndValue);
  102. stringValueData = heap_xrealloc(stringValueData, (len + 1) * sizeof(WCHAR));
  103. if (!GetWindowTextW(hwndValue, stringValueData, len + 1))
  104. *stringValueData = 0;
  105. }
  106. /* Fall through */
  107. case IDCANCEL:
  108. EndDialog(hwndDlg, wParam);
  109. return TRUE;
  110. }
  111. }
  112. return FALSE;
  113. }
  114. static INT_PTR CALLBACK bin_modify_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  115. {
  116. struct edit_params *params;
  117. BYTE *data;
  118. LONG size;
  119. LONG lRet;
  120. switch(uMsg) {
  121. case WM_INITDIALOG:
  122. params = (struct edit_params *)lParam;
  123. SetWindowLongPtrW(hwndDlg, DWLP_USER, (ULONG_PTR)params);
  124. if (params->value_name)
  125. SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, params->value_name);
  126. else
  127. SetDlgItemTextW(hwndDlg, IDC_VALUE_NAME, g_pszDefaultValueName);
  128. SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, HEM_SETDATA, (WPARAM)params->size, (LPARAM)params->data);
  129. SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, WM_SETFONT, (WPARAM) GetStockObject(ANSI_FIXED_FONT), TRUE);
  130. return TRUE;
  131. case WM_COMMAND:
  132. switch (LOWORD(wParam)) {
  133. case IDOK:
  134. params = (struct edit_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
  135. size = SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, HEM_GETDATA, 0, 0);
  136. data = heap_xalloc(size);
  137. SendDlgItemMessageW(hwndDlg, IDC_VALUE_DATA, HEM_GETDATA, (WPARAM)size, (LPARAM)data);
  138. lRet = RegSetValueExW(params->hkey, params->value_name, 0, params->type, data, size);
  139. heap_free(data);
  140. if (lRet == ERROR_SUCCESS)
  141. EndDialog(hwndDlg, 1);
  142. else
  143. {
  144. error_code_messagebox(hwndDlg, IDS_SET_VALUE_FAILED);
  145. EndDialog(hwndDlg, 0);
  146. }
  147. return TRUE;
  148. case IDCANCEL:
  149. EndDialog(hwndDlg, 0);
  150. return TRUE;
  151. }
  152. }
  153. return FALSE;
  154. }
  155. static BOOL value_exists(HWND hwnd, HKEY hKey, const WCHAR *value_name)
  156. {
  157. return !RegQueryValueExW(hKey, value_name, NULL, NULL, NULL, NULL);
  158. }
  159. static LPWSTR read_value(HWND hwnd, HKEY hKey, LPCWSTR valueName, DWORD *lpType, LONG *len)
  160. {
  161. DWORD valueDataLen;
  162. LPWSTR buffer = NULL;
  163. LONG lRet;
  164. lRet = RegQueryValueExW(hKey, valueName, NULL, lpType, NULL, &valueDataLen);
  165. if (lRet) {
  166. if (lRet == ERROR_FILE_NOT_FOUND && !valueName) { /* no default value here, make it up */
  167. if (len) *len = 1;
  168. if (lpType) *lpType = REG_SZ;
  169. buffer = heap_xalloc(sizeof(WCHAR));
  170. *buffer = '\0';
  171. return buffer;
  172. }
  173. error_code_messagebox(hwnd, IDS_BAD_VALUE, valueName);
  174. goto done;
  175. }
  176. if ( *lpType == REG_DWORD ) valueDataLen = sizeof(DWORD);
  177. buffer = heap_xalloc(valueDataLen + sizeof(WCHAR));
  178. lRet = RegQueryValueExW(hKey, valueName, 0, 0, (LPBYTE)buffer, &valueDataLen);
  179. if (lRet) {
  180. error_code_messagebox(hwnd, IDS_BAD_VALUE, valueName);
  181. goto done;
  182. }
  183. if((valueDataLen % sizeof(WCHAR)) == 0)
  184. buffer[valueDataLen / sizeof(WCHAR)] = 0;
  185. if(len) *len = valueDataLen;
  186. return buffer;
  187. done:
  188. heap_free(buffer);
  189. return NULL;
  190. }
  191. BOOL CreateKey(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPWSTR keyName)
  192. {
  193. BOOL result = FALSE;
  194. LONG lRet = ERROR_SUCCESS;
  195. HKEY retKey = NULL;
  196. WCHAR newKey[MAX_NEW_KEY_LEN - 4];
  197. int keyNum;
  198. HKEY hKey;
  199. lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_CREATE_SUB_KEY, &hKey);
  200. if (lRet) {
  201. error_code_messagebox(hwnd, IDS_CREATE_KEY_FAILED);
  202. goto done;
  203. }
  204. if (!LoadStringW(GetModuleHandleW(0), IDS_NEWKEY, newKey, ARRAY_SIZE(newKey))) goto done;
  205. /* try to find a name for the key being created (maximum = 100 attempts) */
  206. for (keyNum = 1; keyNum < 100; keyNum++) {
  207. wsprintfW(keyName, newKey, keyNum);
  208. lRet = RegOpenKeyW(hKey, keyName, &retKey);
  209. if (lRet) break;
  210. RegCloseKey(retKey);
  211. }
  212. if (lRet == ERROR_SUCCESS) goto done;
  213. lRet = RegCreateKeyW(hKey, keyName, &retKey);
  214. if (lRet) {
  215. error_code_messagebox(hwnd, IDS_CREATE_KEY_FAILED);
  216. goto done;
  217. }
  218. result = TRUE;
  219. done:
  220. RegCloseKey(retKey);
  221. return result;
  222. }
  223. BOOL ModifyValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPCWSTR valueName)
  224. {
  225. BOOL result = FALSE;
  226. DWORD type;
  227. LONG lRet;
  228. HKEY hKey;
  229. LONG len;
  230. lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
  231. if (lRet) {
  232. error_code_messagebox(hwnd, IDS_SET_VALUE_FAILED);
  233. return FALSE;
  234. }
  235. editValueName = valueName ? valueName : g_pszDefaultValueName;
  236. if(!(stringValueData = read_value(hwnd, hKey, valueName, &type, &len))) goto done;
  237. if ( (type == REG_SZ) || (type == REG_EXPAND_SZ) ) {
  238. if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_STRING), hwnd, modify_dlgproc) == IDOK) {
  239. lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)stringValueData, (lstrlenW(stringValueData) + 1) * sizeof(WCHAR));
  240. if (lRet == ERROR_SUCCESS) result = TRUE;
  241. else error_code_messagebox(hwnd, IDS_SET_VALUE_FAILED);
  242. }
  243. } else if ( type == REG_DWORD ) {
  244. DWORD value = *((DWORD*)stringValueData);
  245. stringValueData = heap_xrealloc(stringValueData, 64);
  246. wsprintfW(stringValueData, L"%x", value);
  247. if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_DWORD), hwnd, modify_dlgproc) == IDOK) {
  248. DWORD val;
  249. CHAR* valueA = GetMultiByteString(stringValueData);
  250. if (sscanf(valueA, isDecimal ? "%lu" : "%lx", &val)) {
  251. lRet = RegSetValueExW(hKey, valueName, 0, type, (BYTE*)&val, sizeof(val));
  252. if (lRet == ERROR_SUCCESS) result = TRUE;
  253. else error_code_messagebox(hwnd, IDS_SET_VALUE_FAILED);
  254. }
  255. heap_free(valueA);
  256. }
  257. } else if ( type == REG_MULTI_SZ ) {
  258. WCHAR char1 = '\r', char2 = '\n';
  259. WCHAR *tmpValueData = NULL;
  260. INT i, j, count;
  261. for ( i = 0, count = 0; i < len - 1; i++)
  262. if ( !stringValueData[i] && stringValueData[i + 1] )
  263. count++;
  264. tmpValueData = heap_xalloc((len + count) * sizeof(WCHAR));
  265. for ( i = 0, j = 0; i < len - 1; i++)
  266. {
  267. if ( !stringValueData[i] && stringValueData[i + 1])
  268. {
  269. tmpValueData[j++] = char1;
  270. tmpValueData[j++] = char2;
  271. }
  272. else
  273. tmpValueData[j++] = stringValueData[i];
  274. }
  275. tmpValueData[j] = stringValueData[i];
  276. heap_free(stringValueData);
  277. stringValueData = tmpValueData;
  278. tmpValueData = NULL;
  279. if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_EDIT_MULTI_STRING), hwnd, modify_dlgproc) == IDOK)
  280. {
  281. len = lstrlenW( stringValueData );
  282. tmpValueData = heap_xalloc((len + 2) * sizeof(WCHAR));
  283. for ( i = 0, j = 0; i < len - 1; i++)
  284. {
  285. if ( stringValueData[i] == char1 && stringValueData[i + 1] == char2)
  286. {
  287. if ( tmpValueData[j - 1] != 0)
  288. tmpValueData[j++] = 0;
  289. i++;
  290. }
  291. else
  292. tmpValueData[j++] = stringValueData[i];
  293. }
  294. tmpValueData[j++] = stringValueData[i];
  295. tmpValueData[j++] = 0;
  296. tmpValueData[j++] = 0;
  297. heap_free(stringValueData);
  298. stringValueData = tmpValueData;
  299. lRet = RegSetValueExW(hKey, valueName, 0, type, (LPBYTE)stringValueData, j * sizeof(WCHAR));
  300. if (lRet == ERROR_SUCCESS) result = TRUE;
  301. else error_code_messagebox(hwnd, IDS_SET_VALUE_FAILED);
  302. }
  303. }
  304. else /* hex data types */
  305. {
  306. struct edit_params params;
  307. params.hkey = hKey;
  308. params.value_name = valueName;
  309. params.type = type;
  310. params.data = stringValueData;
  311. params.size = len;
  312. result = DialogBoxParamW(NULL, MAKEINTRESOURCEW(IDD_EDIT_BINARY), hwnd,
  313. bin_modify_dlgproc, (LPARAM)&params);
  314. }
  315. /* Update the listview item with the new data string */
  316. if (result)
  317. {
  318. int index = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1,
  319. MAKELPARAM(LVNI_FOCUSED | LVNI_SELECTED, 0));
  320. heap_free(stringValueData);
  321. stringValueData = read_value(hwnd, hKey, valueName, &type, &len);
  322. format_value_data(g_pChildWnd->hListWnd, index, type, stringValueData, len);
  323. }
  324. done:
  325. heap_free(stringValueData);
  326. stringValueData = NULL;
  327. RegCloseKey(hKey);
  328. return result;
  329. }
  330. BOOL DeleteKey(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath)
  331. {
  332. BOOL result = FALSE;
  333. LONG lRet;
  334. HKEY hKey;
  335. lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ|KEY_SET_VALUE, &hKey);
  336. if (lRet) {
  337. error_code_messagebox(hwnd, IDS_DELETE_KEY_FAILED);
  338. return FALSE;
  339. }
  340. if (messagebox(hwnd, MB_YESNO | MB_ICONEXCLAMATION, IDS_DELETE_KEY_TITLE,
  341. IDS_DELETE_KEY_TEXT) != IDYES)
  342. goto done;
  343. lRet = SHDeleteKeyW(hKeyRoot, keyPath);
  344. if (lRet) {
  345. error_code_messagebox(hwnd, IDS_BAD_KEY, keyPath);
  346. goto done;
  347. }
  348. result = TRUE;
  349. done:
  350. RegCloseKey(hKey);
  351. return result;
  352. }
  353. BOOL DeleteValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPCWSTR valueName)
  354. {
  355. BOOL result = FALSE;
  356. LONG lRet;
  357. HKEY hKey;
  358. lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
  359. if (lRet) return FALSE;
  360. lRet = RegDeleteValueW(hKey, valueName);
  361. if (lRet && valueName) {
  362. error_code_messagebox(hwnd, IDS_BAD_VALUE, valueName);
  363. }
  364. if (lRet) goto done;
  365. result = TRUE;
  366. done:
  367. RegCloseKey(hKey);
  368. return result;
  369. }
  370. BOOL CreateValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, DWORD valueType, LPWSTR valueName)
  371. {
  372. LONG lRet = ERROR_SUCCESS;
  373. WCHAR newValue[256];
  374. DWORD valueDword = 0;
  375. BOOL result = FALSE;
  376. int valueNum, index;
  377. HKEY hKey;
  378. LVITEMW item;
  379. lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
  380. if (lRet) {
  381. error_code_messagebox(hwnd, IDS_CREATE_VALUE_FAILED);
  382. return FALSE;
  383. }
  384. if (!LoadStringW(GetModuleHandleW(0), IDS_NEWVALUE, newValue, ARRAY_SIZE(newValue))) goto done;
  385. /* try to find a name for the value being created (maximum = 100 attempts) */
  386. for (valueNum = 1; valueNum < 100; valueNum++) {
  387. wsprintfW(valueName, newValue, valueNum);
  388. lRet = RegQueryValueExW(hKey, valueName, 0, 0, 0, 0);
  389. if (lRet == ERROR_FILE_NOT_FOUND) break;
  390. }
  391. if (lRet != ERROR_FILE_NOT_FOUND) {
  392. error_code_messagebox(hwnd, IDS_CREATE_VALUE_FAILED);
  393. goto done;
  394. }
  395. lRet = RegSetValueExW(hKey, valueName, 0, valueType, (BYTE*)&valueDword, sizeof(DWORD));
  396. if (lRet) {
  397. error_code_messagebox(hwnd, IDS_CREATE_VALUE_FAILED);
  398. goto done;
  399. }
  400. /* Add the new item to the listview */
  401. index = AddEntryToList(g_pChildWnd->hListWnd, valueName, valueType,
  402. (BYTE *)&valueDword, sizeof(DWORD), -1);
  403. item.state = LVIS_FOCUSED | LVIS_SELECTED;
  404. item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
  405. SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, index, (LPARAM)&item);
  406. result = TRUE;
  407. done:
  408. RegCloseKey(hKey);
  409. return result;
  410. }
  411. BOOL RenameValue(HWND hwnd, HKEY hKeyRoot, LPCWSTR keyPath, LPCWSTR oldName, LPCWSTR newName)
  412. {
  413. LPWSTR value = NULL;
  414. DWORD type;
  415. LONG len, lRet;
  416. BOOL result = FALSE;
  417. HKEY hKey;
  418. if (!oldName) return FALSE;
  419. if (!newName) return FALSE;
  420. lRet = RegOpenKeyExW(hKeyRoot, keyPath, 0, KEY_READ | KEY_SET_VALUE, &hKey);
  421. if (lRet) {
  422. error_code_messagebox(hwnd, IDS_RENAME_VALUE_FAILED);
  423. return FALSE;
  424. }
  425. if (value_exists(hwnd, hKey, newName)) {
  426. error_code_messagebox(hwnd, IDS_VALUE_EXISTS, oldName);
  427. goto done;
  428. }
  429. value = read_value(hwnd, hKey, oldName, &type, &len);
  430. if(!value) goto done;
  431. lRet = RegSetValueExW(hKey, newName, 0, type, (BYTE*)value, len);
  432. if (lRet) {
  433. error_code_messagebox(hwnd, IDS_RENAME_VALUE_FAILED);
  434. goto done;
  435. }
  436. lRet = RegDeleteValueW(hKey, oldName);
  437. if (lRet) {
  438. RegDeleteValueW(hKey, newName);
  439. error_code_messagebox(hwnd, IDS_RENAME_VALUE_FAILED);
  440. goto done;
  441. }
  442. result = TRUE;
  443. done:
  444. heap_free(value);
  445. RegCloseKey(hKey);
  446. return result;
  447. }
  448. BOOL RenameKey(HWND hwnd, HKEY hRootKey, LPCWSTR keyPath, LPCWSTR newName)
  449. {
  450. LPWSTR parentPath = 0;
  451. LPCWSTR srcSubKey = 0;
  452. HKEY parentKey = 0;
  453. HKEY destKey = 0;
  454. BOOL result = FALSE;
  455. LONG lRet;
  456. DWORD disposition;
  457. if (!keyPath || !newName) return FALSE;
  458. if (!wcsrchr(keyPath, '\\')) {
  459. parentKey = hRootKey;
  460. srcSubKey = keyPath;
  461. } else {
  462. LPWSTR srcSubKey_copy;
  463. parentPath = heap_xalloc((lstrlenW(keyPath) + 1) * sizeof(WCHAR));
  464. lstrcpyW(parentPath, keyPath);
  465. srcSubKey_copy = wcsrchr(parentPath, '\\');
  466. *srcSubKey_copy = 0;
  467. srcSubKey = srcSubKey_copy + 1;
  468. lRet = RegOpenKeyExW(hRootKey, parentPath, 0, KEY_READ | KEY_CREATE_SUB_KEY, &parentKey);
  469. if (lRet) {
  470. error_code_messagebox(hwnd, IDS_RENAME_KEY_FAILED);
  471. goto done;
  472. }
  473. }
  474. /* The following fails if the old name is the same as the new name. */
  475. if (!lstrcmpW(srcSubKey, newName)) goto done;
  476. lRet = RegCreateKeyExW(parentKey, newName, 0, NULL, REG_OPTION_NON_VOLATILE,
  477. KEY_WRITE, NULL /* FIXME */, &destKey, &disposition);
  478. if (disposition == REG_OPENED_EXISTING_KEY)
  479. lRet = ERROR_FILE_EXISTS;
  480. if (lRet) {
  481. error_code_messagebox(hwnd, IDS_KEY_EXISTS, srcSubKey);
  482. goto done;
  483. }
  484. /* FIXME: SHCopyKey does not copy the security attributes */
  485. lRet = SHCopyKeyW(parentKey, srcSubKey, destKey, 0);
  486. if (lRet) {
  487. RegCloseKey(destKey);
  488. RegDeleteKeyW(parentKey, newName);
  489. error_code_messagebox(hwnd, IDS_RENAME_KEY_FAILED);
  490. goto done;
  491. }
  492. lRet = SHDeleteKeyW(hRootKey, keyPath);
  493. if (lRet) {
  494. error_code_messagebox(hwnd, IDS_RENAME_KEY_FAILED);
  495. goto done;
  496. }
  497. result = TRUE;
  498. done:
  499. RegCloseKey(destKey);
  500. if (parentKey) {
  501. RegCloseKey(parentKey);
  502. heap_free(parentPath);
  503. }
  504. return result;
  505. }