regedit: Convert regedit main code to Unicode.
[wine/multimedia.git] / programs / regedit / framewnd.c
blobc4f4f92bc6a0969ed4b821dd92c6c7d6a51adf1c
1 /*
2 * Regedit frame window
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
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.
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.
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
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
23 #include <windows.h>
24 #include <tchar.h>
25 #include <commctrl.h>
26 #include <commdlg.h>
27 #include <cderr.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <shellapi.h>
32 #include "main.h"
33 #include "regproc.h"
34 #include "wine/unicode.h"
36 /********************************************************************************
37 * Global and Local Variables:
40 static WCHAR favoritesKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','A','p','p','l','e','t','s','\\','R','e','g','E','d','i','t','\\','F','a','v','o','r','i','t','e','s',0};
41 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
42 static WCHAR favoriteName[128];
43 static WCHAR searchString[128];
44 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
46 static WCHAR FileNameBuffer[_MAX_PATH];
47 static WCHAR FileTitleBuffer[_MAX_PATH];
48 static WCHAR FilterBuffer[_MAX_PATH];
50 /*******************************************************************************
51 * Local module support methods
54 static void resize_frame_rect(HWND hWnd, PRECT prect)
56 RECT rt;
58 if (IsWindowVisible(hToolBar)) {
59 SendMessageW(hToolBar, WM_SIZE, 0, 0);
60 GetClientRect(hToolBar, &rt);
61 prect->top = rt.bottom+3;
62 prect->bottom -= rt.bottom+3;
65 if (IsWindowVisible(hStatusBar)) {
66 SetupStatusBar(hWnd, TRUE);
67 GetClientRect(hStatusBar, &rt);
68 prect->bottom -= rt.bottom;
70 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
73 static void resize_frame_client(HWND hWnd)
75 RECT rect;
77 GetClientRect(hWnd, &rect);
78 resize_frame_rect(hWnd, &rect);
81 /********************************************************************************/
83 static void OnEnterMenuLoop(HWND hWnd)
85 int nParts;
86 WCHAR empty = 0;
88 /* Update the status bar pane sizes */
89 nParts = -1;
90 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
91 bInMenuLoop = TRUE;
92 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)&empty);
95 static void OnExitMenuLoop(HWND hWnd)
97 bInMenuLoop = FALSE;
98 /* Update the status bar pane sizes*/
99 SetupStatusBar(hWnd, TRUE);
100 UpdateStatusBar();
103 static void UpdateMenuItems(HMENU hMenu) {
104 HWND hwndTV = g_pChildWnd->hTreeWnd;
105 BOOL bAllowEdit = FALSE;
106 HKEY hRootKey = NULL;
107 LPWSTR keyName;
108 keyName = GetItemPath(hwndTV, TreeView_GetSelection(hwndTV), &hRootKey);
109 if (GetFocus() != hwndTV || (keyName && *keyName)) { /* can't modify root keys, but allow for their values */
110 bAllowEdit = TRUE;
112 EnableMenuItem(hMenu, ID_EDIT_FIND, MF_ENABLED | MF_BYCOMMAND);
113 EnableMenuItem(hMenu, ID_EDIT_FINDNEXT, MF_ENABLED | MF_BYCOMMAND);
114 EnableMenuItem(hMenu, ID_EDIT_MODIFY, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
115 EnableMenuItem(hMenu, ID_EDIT_DELETE, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
116 EnableMenuItem(hMenu, ID_EDIT_RENAME, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
117 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
118 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
119 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
121 HeapFree(GetProcessHeap(), 0, keyName);
124 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
126 if (wItem == 3) {
127 HKEY hKey;
128 while(GetMenuItemCount(hMenu)>2)
129 DeleteMenu(hMenu, 2, MF_BYPOSITION);
130 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
131 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
132 WCHAR namebuf[KEY_MAX_LEN];
133 BYTE valuebuf[4096];
134 int i = 0;
135 BOOL sep = FALSE;
136 DWORD ksize, vsize, type;
137 LONG error;
138 do {
139 ksize = KEY_MAX_LEN;
140 vsize = sizeof(valuebuf);
141 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
142 if (error != ERROR_SUCCESS)
143 break;
144 if (type == REG_SZ) {
145 if (!sep) {
146 AppendMenuW(hMenu, MF_SEPARATOR, -1, NULL);
147 sep = TRUE;
149 AppendMenuW(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
151 i++;
152 } while(error == ERROR_SUCCESS);
153 RegCloseKey(hKey);
156 UpdateMenuItems(hMenu);
159 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
161 WCHAR str[100];
163 str[0] = 0;
164 if (nFlags & MF_POPUP) {
165 if (hSysMenu != GetMenu(hWnd)) {
166 if (nItemID == 2) nItemID = 5;
169 if (LoadStringW(hInst, nItemID, str, 100)) {
170 /* load appropriate string*/
171 LPWSTR lpsz = str;
172 /* first newline terminates actual string*/
173 lpsz = strchrW(lpsz, '\n');
174 if (lpsz != NULL)
175 *lpsz = '\0';
177 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
180 void SetupStatusBar(HWND hWnd, BOOL bResize)
182 RECT rc;
183 int nParts;
184 GetClientRect(hWnd, &rc);
185 nParts = rc.right;
186 /* nParts = -1;*/
187 if (bResize)
188 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
189 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
190 UpdateStatusBar();
193 void UpdateStatusBar(void)
195 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
196 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
197 HeapFree(GetProcessHeap(), 0, fullPath);
200 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
202 BOOL vis = IsWindowVisible(hchild);
203 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
205 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
206 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
207 resize_frame_client(hWnd);
210 static BOOL CheckCommDlgError(HWND hWnd)
212 DWORD dwErrorCode = CommDlgExtendedError();
213 switch (dwErrorCode) {
214 case CDERR_DIALOGFAILURE:
215 break;
216 case CDERR_FINDRESFAILURE:
217 break;
218 case CDERR_NOHINSTANCE:
219 break;
220 case CDERR_INITIALIZATION:
221 break;
222 case CDERR_NOHOOK:
223 break;
224 case CDERR_LOCKRESFAILURE:
225 break;
226 case CDERR_NOTEMPLATE:
227 break;
228 case CDERR_LOADRESFAILURE:
229 break;
230 case CDERR_STRUCTSIZE:
231 break;
232 case CDERR_LOADSTRFAILURE:
233 break;
234 case FNERR_BUFFERTOOSMALL:
235 break;
236 case CDERR_MEMALLOCFAILURE:
237 break;
238 case FNERR_INVALIDFILENAME:
239 break;
240 case CDERR_MEMLOCKFAILURE:
241 break;
242 case FNERR_SUBCLASSFAILURE:
243 break;
244 default:
245 break;
247 return TRUE;
250 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
252 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
254 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
255 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
256 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
258 else
259 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
262 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
264 static OPENFILENAMEW* pOpenFileName;
265 OFNOTIFYW *pOfNotify;
267 switch (uiMsg) {
268 case WM_INITDIALOG:
269 pOpenFileName = (OPENFILENAMEW*)lParam;
270 break;
271 case WM_COMMAND:
272 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
273 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
274 break;
275 case WM_NOTIFY:
276 pOfNotify = (OFNOTIFYW*)lParam;
277 switch (pOfNotify->hdr.code)
279 case CDN_INITDONE:
281 BOOL export_branch = FALSE;
282 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
283 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
284 if (path && strlenW(path) > 0)
285 export_branch = TRUE;
286 HeapFree(GetProcessHeap(), 0, path);
287 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
288 break;
290 case CDN_FILEOK:
291 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
292 break;
294 break;
295 default:
296 break;
298 return 0L;
302 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
304 memset(pofn, 0, sizeof(OPENFILENAMEW));
305 pofn->lStructSize = sizeof(OPENFILENAMEW);
306 pofn->hwndOwner = hWnd;
307 pofn->hInstance = hInst;
309 if (FilterBuffer[0] == 0)
311 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
312 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
314 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
315 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
316 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
317 snprintfW( FilterBuffer, MAX_PATH, filterW, filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
319 pofn->lpstrFilter = FilterBuffer;
320 pofn->nFilterIndex = 2;
321 pofn->lpstrFile = FileNameBuffer;
322 pofn->nMaxFile = _MAX_PATH;
323 pofn->lpstrFileTitle = FileTitleBuffer;
324 pofn->nMaxFileTitle = _MAX_PATH;
325 pofn->Flags = OFN_HIDEREADONLY;
326 /* some other fields may be set by the caller */
327 return TRUE;
330 static BOOL import_registry_filename(LPTSTR filename)
332 BOOL Success;
333 FILE* reg_file = fopen(filename, "r");
335 if(!reg_file)
336 return FALSE;
338 Success = import_registry_file(reg_file);
340 if(fclose(reg_file) != 0)
341 Success = FALSE;
343 return Success;
346 static BOOL ImportRegistryFile(HWND hWnd)
348 OPENFILENAMEW ofn;
349 WCHAR title[128];
351 InitOpenFileName(hWnd, &ofn);
352 ofn.Flags |= OFN_ENABLESIZING;
353 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
354 ofn.lpstrTitle = title;
355 if (GetOpenFileNameW(&ofn)) {
356 CHAR* fileA = GetMultiByteString(ofn.lpstrFile);
357 if (!import_registry_filename(fileA)) {
358 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
359 HeapFree(GetProcessHeap(), 0, fileA);
360 return FALSE;
362 HeapFree(GetProcessHeap(), 0, fileA);
363 } else {
364 CheckCommDlgError(hWnd);
366 RefreshTreeView(g_pChildWnd->hTreeWnd);
367 return TRUE;
371 static BOOL ExportRegistryFile(HWND hWnd)
373 OPENFILENAMEW ofn;
374 WCHAR title[128];
376 InitOpenFileName(hWnd, &ofn);
377 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
378 ofn.lpstrTitle = title;
379 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
380 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
381 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
382 if (GetSaveFileNameW(&ofn)) {
383 BOOL result;
384 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
385 if (!result) {
386 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
387 return FALSE;
389 } else {
390 CheckCommDlgError(hWnd);
392 return TRUE;
395 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
397 #if 1
398 PRINTDLGW pd;
400 ZeroMemory(&pd, sizeof(PRINTDLG));
401 pd.lStructSize = sizeof(PRINTDLG);
402 pd.hwndOwner = hWnd;
403 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
404 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
405 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
406 pd.nCopies = 1;
407 pd.nFromPage = 0xFFFF;
408 pd.nToPage = 0xFFFF;
409 pd.nMinPage = 1;
410 pd.nMaxPage = 0xFFFF;
411 if (PrintDlgW(&pd)) {
412 /* GDI calls to render output. */
413 DeleteDC(pd.hDC); /* Delete DC when done.*/
415 #else
416 HRESULT hResult;
417 PRINTDLGEXW pd;
419 hResult = PrintDlgExW(&pd);
420 if (hResult == S_OK) {
421 switch (pd.dwResultAction) {
422 case PD_RESULT_APPLY:
423 /*The user clicked the Apply button and later clicked the Cancel button. This indicates that the user wants to apply the changes made in the property sheet, but does not yet want to print. The PRINTDLGEX structure contains the information specified by the user at the time the Apply button was clicked. */
424 break;
425 case PD_RESULT_CANCEL:
426 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
427 break;
428 case PD_RESULT_PRINT:
429 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
430 break;
431 default:
432 break;
434 } else {
435 switch (hResult) {
436 case E_OUTOFMEMORY:
437 /*Insufficient memory. */
438 break;
439 case E_INVALIDARG:
440 /* One or more arguments are invalid. */
441 break;
442 case E_POINTER:
443 /*Invalid pointer. */
444 break;
445 case E_HANDLE:
446 /*Invalid handle. */
447 break;
448 case E_FAIL:
449 /*Unspecified error. */
450 break;
451 default:
452 break;
454 return FALSE;
456 #endif
457 return TRUE;
460 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
462 BOOL result;
464 result = OpenClipboard(hWnd);
465 if (result) {
466 result = EmptyClipboard();
467 if (result) {
468 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
469 HANDLE hClipData = GlobalAlloc(GHND, len);
470 LPVOID pLoc = GlobalLock(hClipData);
471 lstrcpyW(pLoc, keyName);
472 GlobalUnlock(hClipData);
473 hClipData = SetClipboardData(CF_UNICODETEXT, hClipData);
475 } else {
476 /* error emptying clipboard*/
477 /* DWORD dwError = GetLastError(); */
480 if (!CloseClipboard()) {
481 /* error closing clipboard*/
482 /* DWORD dwError = GetLastError(); */
485 } else {
486 /* error opening clipboard*/
487 /* DWORD dwError = GetLastError(); */
490 return result;
493 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
495 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
497 switch(uMsg) {
498 case WM_INITDIALOG:
499 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
500 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
501 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
502 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
503 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
504 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
505 SetWindowTextW(hwndValue, searchString);
506 return TRUE;
507 case WM_COMMAND:
508 switch(LOWORD(wParam)) {
509 case IDC_VALUE_NAME:
510 if (HIWORD(wParam) == EN_UPDATE) {
511 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
512 return TRUE;
514 break;
515 case IDOK:
516 if (GetWindowTextLengthW(hwndValue)>0) {
517 int mask = 0;
518 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
519 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
520 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
521 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
522 searchMask = mask;
523 GetWindowTextW(hwndValue, searchString, 128);
524 EndDialog(hwndDlg, IDOK);
526 return TRUE;
527 case IDCANCEL:
528 EndDialog(hwndDlg, IDCANCEL);
529 return TRUE;
531 break;
533 return FALSE;
536 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
538 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
540 switch(uMsg) {
541 case WM_INITDIALOG:
543 HKEY hKeyRoot = NULL;
544 LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
546 if(!ItemPath || !*ItemPath)
547 ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
548 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
549 SetWindowTextW(hwndValue, ItemPath);
550 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
551 HeapFree(GetProcessHeap(), 0, ItemPath);
552 return TRUE;
554 case WM_COMMAND:
555 switch(LOWORD(wParam)) {
556 case IDC_VALUE_NAME:
557 if (HIWORD(wParam) == EN_UPDATE) {
558 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(hwndValue)>0);
559 return TRUE;
561 break;
562 case IDOK:
563 if (GetWindowTextLengthW(hwndValue)>0) {
564 GetWindowTextW(hwndValue, favoriteName, 128);
565 EndDialog(hwndDlg, IDOK);
567 return TRUE;
568 case IDCANCEL:
569 EndDialog(hwndDlg, IDCANCEL);
570 return TRUE;
572 break;
574 return FALSE;
577 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
579 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
581 switch(uMsg) {
582 case WM_INITDIALOG: {
583 HKEY hKey;
584 int i = 0;
585 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
586 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
587 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
588 WCHAR namebuf[KEY_MAX_LEN];
589 BYTE valuebuf[4096];
590 DWORD ksize, vsize, type;
591 LONG error;
592 do {
593 ksize = KEY_MAX_LEN;
594 vsize = sizeof(valuebuf);
595 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
596 if (error != ERROR_SUCCESS)
597 break;
598 if (type == REG_SZ) {
599 SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
601 i++;
602 } while(error == ERROR_SUCCESS);
603 RegCloseKey(hKey);
605 else
606 return FALSE;
607 EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
608 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
609 return TRUE;
611 case WM_COMMAND:
612 switch(LOWORD(wParam)) {
613 case IDC_NAME_LIST:
614 if (HIWORD(wParam) == LBN_SELCHANGE) {
615 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
616 return TRUE;
618 break;
619 case IDOK: {
620 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
621 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
622 if (len>0) {
623 LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
624 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
625 if (len>127)
626 lpName[127] = '\0';
627 lstrcpyW(favoriteName, lpName);
628 EndDialog(hwndDlg, IDOK);
629 HeapFree(GetProcessHeap(), 0, lpName);
631 return TRUE;
633 case IDCANCEL:
634 EndDialog(hwndDlg, IDCANCEL);
635 return TRUE;
637 break;
639 return FALSE;
642 /*******************************************************************************
644 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
646 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
649 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
651 HKEY hKeyRoot = 0;
652 DWORD valueType;
653 int curIndex;
654 BOOL firstItem = TRUE;
656 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
657 HKEY hKey;
658 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
659 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
660 WCHAR namebuf[KEY_MAX_LEN];
661 BYTE valuebuf[4096];
662 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
663 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
664 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
665 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
666 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
668 RegCloseKey(hKey);
670 return TRUE;
672 switch (LOWORD(wParam)) {
673 case ID_REGISTRY_IMPORTREGISTRYFILE:
674 ImportRegistryFile(hWnd);
675 break;
676 case ID_EDIT_EXPORT:
677 case ID_REGISTRY_EXPORTREGISTRYFILE:
678 ExportRegistryFile(hWnd);
679 break;
680 case ID_REGISTRY_PRINT:
682 const WCHAR empty = 0;
683 PrintRegistryHive(hWnd, &empty);
684 break;
686 case ID_EDIT_DELETE:
688 HWND hWndDelete = GetFocus();
689 if (hWndDelete == g_pChildWnd->hTreeWnd) {
690 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
691 if (keyPath == 0 || *keyPath == 0) {
692 MessageBeep(MB_ICONHAND);
693 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
694 DeleteNode(g_pChildWnd->hTreeWnd, 0);
696 HeapFree(GetProcessHeap(), 0, keyPath);
697 } else if (hWndDelete == g_pChildWnd->hListWnd) {
698 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
699 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
700 while(curIndex != -1) {
701 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
703 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, curIndex, LVNI_SELECTED);
704 if(curIndex != -1 && firstItem) {
705 if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_BOX_TEXT_MULTIPLE),
706 MAKEINTRESOURCEW(IDS_DELETE_BOX_TITLE),
707 MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
708 break;
711 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
713 HeapFree(GetProcessHeap(), 0, valueName);
714 break;
716 firstItem = FALSE;
717 HeapFree(GetProcessHeap(), 0, valueName);
719 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
720 HeapFree(GetProcessHeap(), 0, keyPath);
721 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
722 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
723 SendMessage(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
725 break;
727 case ID_EDIT_MODIFY:
729 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
730 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
731 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
732 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
733 HeapFree(GetProcessHeap(), 0, keyPath);
734 break;
736 case ID_EDIT_FIND:
737 case ID_EDIT_FINDNEXT:
739 HTREEITEM hItem;
740 if (LOWORD(wParam) == ID_EDIT_FIND &&
741 DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
742 break;
743 if (!*searchString)
744 break;
745 hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
746 if (hItem) {
747 int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
748 HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
749 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
750 SetCursor(hcursorOld);
751 if (hItem) {
752 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
753 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
754 UpdateWindow(g_pChildWnd->hTreeWnd);
755 if (row != -1) {
756 ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
757 ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
758 SetFocus(g_pChildWnd->hListWnd);
759 } else {
760 SetFocus(g_pChildWnd->hTreeWnd);
762 } else {
763 error(hWnd, IDS_NOTFOUND, searchString);
766 break;
768 case ID_EDIT_COPYKEYNAME:
770 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
771 if (fullPath) {
772 CopyKeyName(hWnd, fullPath);
773 HeapFree(GetProcessHeap(), 0, fullPath);
775 break;
777 case ID_EDIT_NEW_KEY:
779 WCHAR newKeyW[MAX_NEW_KEY_LEN];
780 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
781 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
782 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
783 StartKeyRename(g_pChildWnd->hTreeWnd);
785 HeapFree(GetProcessHeap(), 0, keyPath);
787 break;
788 case ID_EDIT_NEW_STRINGVALUE:
789 valueType = REG_SZ;
790 goto create_value;
791 case ID_EDIT_NEW_EXPANDVALUE:
792 valueType = REG_EXPAND_SZ;
793 goto create_value;
794 case ID_EDIT_NEW_MULTI_STRINGVALUE:
795 valueType = REG_MULTI_SZ;
796 goto create_value;
797 case ID_EDIT_NEW_BINARYVALUE:
798 valueType = REG_BINARY;
799 goto create_value;
800 case ID_EDIT_NEW_DWORDVALUE:
801 valueType = REG_DWORD;
802 /* fall through */
803 create_value:
805 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
806 WCHAR newKey[MAX_NEW_KEY_LEN];
807 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
808 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
809 StartValueRename(g_pChildWnd->hListWnd);
811 HeapFree(GetProcessHeap(), 0, keyPath);
813 break;
814 case ID_EDIT_RENAME:
816 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
817 if (keyPath == 0 || *keyPath == 0) {
818 MessageBeep(MB_ICONHAND);
819 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
820 StartKeyRename(g_pChildWnd->hTreeWnd);
821 } else if (GetFocus() == g_pChildWnd->hListWnd) {
822 StartValueRename(g_pChildWnd->hListWnd);
824 HeapFree(GetProcessHeap(), 0, keyPath);
826 break;
827 case ID_REGISTRY_PRINTERSETUP:
828 /*PRINTDLG pd;*/
829 /*PrintDlg(&pd);*/
830 /*PAGESETUPDLG psd;*/
831 /*PageSetupDlg(&psd);*/
832 break;
833 case ID_REGISTRY_OPENLOCAL:
834 break;
835 case ID_REGISTRY_EXIT:
836 DestroyWindow(hWnd);
837 break;
838 case ID_FAVORITES_ADDTOFAVORITES:
840 HKEY hKey;
841 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
842 if (lpKeyPath) {
843 if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
844 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
845 0, NULL, 0,
846 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
847 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
848 RegCloseKey(hKey);
851 HeapFree(GetProcessHeap(), 0, lpKeyPath);
853 break;
855 case ID_FAVORITES_REMOVEFAVORITE:
857 if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
858 HKEY hKey;
859 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
860 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
861 RegDeleteValueW(hKey, favoriteName);
862 RegCloseKey(hKey);
865 break;
867 case ID_VIEW_REFRESH:
869 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
870 RefreshTreeView(g_pChildWnd->hTreeWnd);
871 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
872 HeapFree(GetProcessHeap(), 0, keyPath);
874 break;
875 /*case ID_OPTIONS_TOOLBAR:*/
876 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
877 /* break;*/
878 case ID_VIEW_STATUSBAR:
879 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
880 break;
881 case ID_HELP_HELPTOPICS:
883 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
884 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
885 break;
887 case ID_HELP_ABOUT:
888 ShowAboutBox(hWnd);
889 break;
890 case ID_VIEW_SPLIT: {
891 RECT rt;
892 POINT pt, pts;
893 GetClientRect(g_pChildWnd->hWnd, &rt);
894 pt.x = rt.left + g_pChildWnd->nSplitPos;
895 pt.y = (rt.bottom / 2);
896 pts = pt;
897 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
898 SetCursorPos(pts.x, pts.y);
899 SetCursor(LoadCursor(0, IDC_SIZEWE));
900 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
902 return TRUE;
904 default:
905 return FALSE;
908 return TRUE;
911 /********************************************************************************
913 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
915 * PURPOSE: Processes messages for the main frame window.
917 * WM_COMMAND - process the application menu
918 * WM_DESTROY - post a quit message and return
922 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
924 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
926 switch (message) {
927 case WM_CREATE:
928 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
929 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
930 hWnd, NULL, hInst, 0);
931 break;
932 case WM_COMMAND:
933 if (!_CmdWndProc(hWnd, message, wParam, lParam))
934 return DefWindowProcW(hWnd, message, wParam, lParam);
935 break;
936 case WM_ACTIVATE:
937 if (LOWORD(hWnd))
938 SetFocus(g_pChildWnd->hWnd);
939 break;
940 case WM_SIZE:
941 resize_frame_client(hWnd);
942 break;
943 case WM_TIMER:
944 break;
945 case WM_ENTERMENULOOP:
946 OnEnterMenuLoop(hWnd);
947 break;
948 case WM_EXITMENULOOP:
949 OnExitMenuLoop(hWnd);
950 break;
951 case WM_INITMENUPOPUP:
952 if (!HIWORD(lParam))
953 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
954 break;
955 case WM_MENUSELECT:
956 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
957 break;
958 case WM_DESTROY:
960 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
961 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
962 PostQuitMessage(0);
964 default:
965 return DefWindowProcW(hWnd, message, wParam, lParam);
967 return 0;