push cea036dc4aae50c232dc1391dcc459ff0b060bcf
[wine/hacks.git] / programs / regedit / framewnd.c
bloba8017033bb9f606d7fb379479184f1a8899452af
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, (long)&nParts);
91 bInMenuLoop = TRUE;
92 SendMessageW(hStatusBar, SB_SETTEXTW, (WPARAM)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 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)
310 LoadStringW(hInst, IDS_FILEDIALOG_FILTER, FilterBuffer, _MAX_PATH);
311 pofn->lpstrFilter = FilterBuffer;
312 pofn->nFilterIndex = 2;
313 pofn->lpstrFile = FileNameBuffer;
314 pofn->nMaxFile = _MAX_PATH;
315 pofn->lpstrFileTitle = FileTitleBuffer;
316 pofn->nMaxFileTitle = _MAX_PATH;
317 pofn->Flags = OFN_HIDEREADONLY;
318 /* some other fields may be set by the caller */
319 return TRUE;
322 static BOOL import_registry_filename(LPTSTR filename)
324 BOOL Success;
325 FILE* reg_file = fopen(filename, "r");
327 if(!reg_file)
328 return FALSE;
330 Success = import_registry_file(reg_file);
332 if(fclose(reg_file) != 0)
333 Success = FALSE;
335 return Success;
338 static BOOL ImportRegistryFile(HWND hWnd)
340 OPENFILENAMEW ofn;
341 WCHAR title[128];
343 InitOpenFileName(hWnd, &ofn);
344 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
345 ofn.lpstrTitle = title;
346 if (GetOpenFileNameW(&ofn)) {
347 CHAR* fileA = GetMultiByteString(ofn.lpstrFile);
348 if (!import_registry_filename(fileA)) {
349 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
350 HeapFree(GetProcessHeap(), 0, fileA);
351 return FALSE;
353 HeapFree(GetProcessHeap(), 0, fileA);
354 } else {
355 CheckCommDlgError(hWnd);
357 RefreshTreeView(g_pChildWnd->hTreeWnd);
358 return TRUE;
362 static BOOL ExportRegistryFile(HWND hWnd)
364 OPENFILENAMEW ofn;
365 WCHAR ExportKeyPath[_MAX_PATH];
366 WCHAR title[128];
368 ExportKeyPath[0] = 0;
369 InitOpenFileName(hWnd, &ofn);
370 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
371 ofn.lpstrTitle = title;
372 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
373 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
374 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
375 if (GetSaveFileNameW(&ofn)) {
376 BOOL result;
377 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
378 if (!result) {
379 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
380 return FALSE;
382 } else {
383 CheckCommDlgError(hWnd);
385 return TRUE;
388 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
390 #if 1
391 PRINTDLGW pd;
393 ZeroMemory(&pd, sizeof(PRINTDLG));
394 pd.lStructSize = sizeof(PRINTDLG);
395 pd.hwndOwner = hWnd;
396 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
397 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
398 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
399 pd.nCopies = 1;
400 pd.nFromPage = 0xFFFF;
401 pd.nToPage = 0xFFFF;
402 pd.nMinPage = 1;
403 pd.nMaxPage = 0xFFFF;
404 if (PrintDlgW(&pd)) {
405 /* GDI calls to render output. */
406 DeleteDC(pd.hDC); /* Delete DC when done.*/
408 #else
409 HRESULT hResult;
410 PRINTDLGEXW pd;
412 hResult = PrintDlgExW(&pd);
413 if (hResult == S_OK) {
414 switch (pd.dwResultAction) {
415 case PD_RESULT_APPLY:
416 /*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. */
417 break;
418 case PD_RESULT_CANCEL:
419 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
420 break;
421 case PD_RESULT_PRINT:
422 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
423 break;
424 default:
425 break;
427 } else {
428 switch (hResult) {
429 case E_OUTOFMEMORY:
430 /*Insufficient memory. */
431 break;
432 case E_INVALIDARG:
433 /* One or more arguments are invalid. */
434 break;
435 case E_POINTER:
436 /*Invalid pointer. */
437 break;
438 case E_HANDLE:
439 /*Invalid handle. */
440 break;
441 case E_FAIL:
442 /*Unspecified error. */
443 break;
444 default:
445 break;
447 return FALSE;
449 #endif
450 return TRUE;
453 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
455 BOOL result;
457 result = OpenClipboard(hWnd);
458 if (result) {
459 result = EmptyClipboard();
460 if (result) {
461 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
462 HANDLE hClipData = GlobalAlloc(GHND, len);
463 LPVOID pLoc = GlobalLock(hClipData);
464 lstrcpyW(pLoc, keyName);
465 GlobalUnlock(hClipData);
466 hClipData = SetClipboardData(CF_UNICODETEXT, hClipData);
468 } else {
469 /* error emptying clipboard*/
470 /* DWORD dwError = GetLastError(); */
473 if (!CloseClipboard()) {
474 /* error closing clipboard*/
475 /* DWORD dwError = GetLastError(); */
478 } else {
479 /* error opening clipboard*/
480 /* DWORD dwError = GetLastError(); */
483 return result;
486 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
488 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
490 switch(uMsg) {
491 case WM_INITDIALOG:
492 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
493 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
494 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
495 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
496 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
497 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
498 SetWindowTextW(hwndValue, searchString);
499 return TRUE;
500 case WM_COMMAND:
501 switch(LOWORD(wParam)) {
502 case IDC_VALUE_NAME:
503 if (HIWORD(wParam) == EN_UPDATE) {
504 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
505 return TRUE;
507 break;
508 case IDOK:
509 if (GetWindowTextLengthW(hwndValue)>0) {
510 int mask = 0;
511 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
512 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
513 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
514 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
515 searchMask = mask;
516 GetWindowTextW(hwndValue, searchString, 128);
517 EndDialog(hwndDlg, IDOK);
519 return TRUE;
520 case IDCANCEL:
521 EndDialog(hwndDlg, IDCANCEL);
522 return TRUE;
524 break;
526 return FALSE;
529 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
531 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
533 switch(uMsg) {
534 case WM_INITDIALOG:
536 HKEY hKeyRoot = NULL;
537 LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
539 if(!ItemPath || !*ItemPath)
540 ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
541 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
542 SetWindowTextW(hwndValue, ItemPath);
543 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
544 HeapFree(GetProcessHeap(), 0, ItemPath);
545 return TRUE;
547 case WM_COMMAND:
548 switch(LOWORD(wParam)) {
549 case IDC_VALUE_NAME:
550 if (HIWORD(wParam) == EN_UPDATE) {
551 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(hwndValue)>0);
552 return TRUE;
554 break;
555 case IDOK:
556 if (GetWindowTextLengthW(hwndValue)>0) {
557 GetWindowTextW(hwndValue, favoriteName, 128);
558 EndDialog(hwndDlg, IDOK);
560 return TRUE;
561 case IDCANCEL:
562 EndDialog(hwndDlg, IDCANCEL);
563 return TRUE;
565 break;
567 return FALSE;
570 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
572 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
574 switch(uMsg) {
575 case WM_INITDIALOG: {
576 HKEY hKey;
577 int i = 0;
578 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
579 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
580 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
581 WCHAR namebuf[KEY_MAX_LEN];
582 BYTE valuebuf[4096];
583 DWORD ksize, vsize, type;
584 LONG error;
585 do {
586 ksize = KEY_MAX_LEN;
587 vsize = sizeof(valuebuf);
588 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
589 if (error != ERROR_SUCCESS)
590 break;
591 if (type == REG_SZ) {
592 SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
594 i++;
595 } while(error == ERROR_SUCCESS);
596 RegCloseKey(hKey);
598 else
599 return FALSE;
600 EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
601 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
602 return TRUE;
604 case WM_COMMAND:
605 switch(LOWORD(wParam)) {
606 case IDC_NAME_LIST:
607 if (HIWORD(wParam) == LBN_SELCHANGE) {
608 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
609 return TRUE;
611 break;
612 case IDOK: {
613 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
614 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
615 if (len>0) {
616 LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
617 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
618 if (len>127)
619 lpName[127] = '\0';
620 lstrcpyW(favoriteName, lpName);
621 EndDialog(hwndDlg, IDOK);
622 HeapFree(GetProcessHeap(), 0, lpName);
624 return TRUE;
626 case IDCANCEL:
627 EndDialog(hwndDlg, IDCANCEL);
628 return TRUE;
630 break;
632 return FALSE;
635 /*******************************************************************************
637 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
639 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
642 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
644 HKEY hKeyRoot = 0;
645 DWORD valueType;
646 int curIndex;
647 BOOL firstItem = TRUE;
649 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
650 HKEY hKey;
651 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
652 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
653 WCHAR namebuf[KEY_MAX_LEN];
654 BYTE valuebuf[4096];
655 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
656 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
657 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
658 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
659 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
661 RegCloseKey(hKey);
663 return TRUE;
665 switch (LOWORD(wParam)) {
666 case ID_REGISTRY_IMPORTREGISTRYFILE:
667 ImportRegistryFile(hWnd);
668 break;
669 case ID_EDIT_EXPORT:
670 case ID_REGISTRY_EXPORTREGISTRYFILE:
671 ExportRegistryFile(hWnd);
672 break;
673 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
674 break;
675 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
676 break;
677 case ID_REGISTRY_PRINT:
679 const WCHAR empty = 0;
680 PrintRegistryHive(hWnd, &empty);
681 break;
683 case ID_EDIT_DELETE:
685 HWND hWndDelete = GetFocus();
686 if (hWndDelete == g_pChildWnd->hTreeWnd) {
687 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
688 if (keyPath == 0 || *keyPath == 0) {
689 MessageBeep(MB_ICONHAND);
690 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
691 DeleteNode(g_pChildWnd->hTreeWnd, 0);
693 HeapFree(GetProcessHeap(), 0, keyPath);
694 } else if (hWndDelete == g_pChildWnd->hListWnd) {
695 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
696 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
697 while(curIndex != -1) {
698 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
700 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, curIndex, LVNI_SELECTED);
701 if(curIndex != -1 && firstItem) {
702 if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_BOX_TEXT_MULTIPLE),
703 MAKEINTRESOURCEW(IDS_DELETE_BOX_TITLE),
704 MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
705 break;
708 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
710 HeapFree(GetProcessHeap(), 0, valueName);
711 break;
713 firstItem = FALSE;
714 HeapFree(GetProcessHeap(), 0, valueName);
716 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
717 HeapFree(GetProcessHeap(), 0, keyPath);
718 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
719 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
720 SendMessage(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
722 break;
724 case ID_EDIT_MODIFY:
726 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
727 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
728 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
729 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
730 HeapFree(GetProcessHeap(), 0, keyPath);
731 break;
733 case ID_EDIT_FIND:
734 case ID_EDIT_FINDNEXT:
736 HTREEITEM hItem;
737 if (LOWORD(wParam) == ID_EDIT_FIND &&
738 DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
739 break;
740 if (!*searchString)
741 break;
742 hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
743 if (hItem) {
744 int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
745 HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
746 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
747 SetCursor(hcursorOld);
748 if (hItem) {
749 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
750 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
751 UpdateWindow(g_pChildWnd->hTreeWnd);
752 if (row != -1) {
753 ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
754 ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
755 SetFocus(g_pChildWnd->hListWnd);
756 } else {
757 SetFocus(g_pChildWnd->hTreeWnd);
759 } else {
760 CHAR* searchStringA = GetMultiByteString(searchString);
761 error(hWnd, IDS_NOTFOUND, searchStringA);
762 HeapFree(GetProcessHeap(), 0, searchStringA);
765 break;
767 case ID_EDIT_COPYKEYNAME:
769 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
770 if (fullPath) {
771 CopyKeyName(hWnd, fullPath);
772 HeapFree(GetProcessHeap(), 0, fullPath);
774 break;
776 case ID_EDIT_NEW_KEY:
778 WCHAR newKeyW[MAX_NEW_KEY_LEN];
779 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
780 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
781 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
782 StartKeyRename(g_pChildWnd->hTreeWnd);
784 HeapFree(GetProcessHeap(), 0, keyPath);
786 break;
787 case ID_EDIT_NEW_STRINGVALUE:
788 valueType = REG_SZ;
789 goto create_value;
790 case ID_EDIT_NEW_MULTI_STRINGVALUE:
791 valueType = REG_MULTI_SZ;
792 goto create_value;
793 case ID_EDIT_NEW_BINARYVALUE:
794 valueType = REG_BINARY;
795 goto create_value;
796 case ID_EDIT_NEW_DWORDVALUE:
797 valueType = REG_DWORD;
798 /* fall through */
799 create_value:
801 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
802 WCHAR newKey[MAX_NEW_KEY_LEN];
803 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
804 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
805 StartValueRename(g_pChildWnd->hListWnd);
807 HeapFree(GetProcessHeap(), 0, keyPath);
809 break;
810 case ID_EDIT_RENAME:
812 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
813 if (keyPath == 0 || *keyPath == 0) {
814 MessageBeep(MB_ICONHAND);
815 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
816 StartKeyRename(g_pChildWnd->hTreeWnd);
817 } else if (GetFocus() == g_pChildWnd->hListWnd) {
818 StartValueRename(g_pChildWnd->hListWnd);
820 HeapFree(GetProcessHeap(), 0, keyPath);
822 break;
823 case ID_REGISTRY_PRINTERSETUP:
824 /*PRINTDLG pd;*/
825 /*PrintDlg(&pd);*/
826 /*PAGESETUPDLG psd;*/
827 /*PageSetupDlg(&psd);*/
828 break;
829 case ID_REGISTRY_OPENLOCAL:
830 break;
831 case ID_REGISTRY_EXIT:
832 DestroyWindow(hWnd);
833 break;
834 case ID_FAVORITES_ADDTOFAVORITES:
836 HKEY hKey;
837 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
838 if (lpKeyPath) {
839 if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
840 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
841 0, NULL, 0,
842 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
843 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
844 RegCloseKey(hKey);
847 HeapFree(GetProcessHeap(), 0, lpKeyPath);
849 break;
851 case ID_FAVORITES_REMOVEFAVORITE:
853 if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
854 HKEY hKey;
855 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
856 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
857 RegDeleteValueW(hKey, favoriteName);
858 RegCloseKey(hKey);
861 break;
863 case ID_VIEW_REFRESH:
865 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
866 RefreshTreeView(g_pChildWnd->hTreeWnd);
867 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
868 HeapFree(GetProcessHeap(), 0, keyPath);
870 break;
871 /*case ID_OPTIONS_TOOLBAR:*/
872 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
873 /* break;*/
874 case ID_VIEW_STATUSBAR:
875 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
876 break;
877 case ID_HELP_HELPTOPICS:
879 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
880 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
881 break;
883 case ID_HELP_ABOUT:
884 ShowAboutBox(hWnd);
885 break;
886 case ID_VIEW_SPLIT: {
887 RECT rt;
888 POINT pt, pts;
889 GetClientRect(g_pChildWnd->hWnd, &rt);
890 pt.x = rt.left + g_pChildWnd->nSplitPos;
891 pt.y = (rt.bottom / 2);
892 pts = pt;
893 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
894 SetCursorPos(pts.x, pts.y);
895 SetCursor(LoadCursor(0, IDC_SIZEWE));
896 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
898 return TRUE;
900 default:
901 return FALSE;
904 return TRUE;
907 /********************************************************************************
909 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
911 * PURPOSE: Processes messages for the main frame window.
913 * WM_COMMAND - process the application menu
914 * WM_DESTROY - post a quit message and return
918 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
920 switch (message) {
921 case WM_CREATE:
922 CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
923 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
924 hWnd, NULL, hInst, 0);
925 break;
926 case WM_COMMAND:
927 if (!_CmdWndProc(hWnd, message, wParam, lParam))
928 return DefWindowProc(hWnd, message, wParam, lParam);
929 break;
930 case WM_ACTIVATE:
931 if (LOWORD(hWnd))
932 SetFocus(g_pChildWnd->hWnd);
933 break;
934 case WM_SIZE:
935 resize_frame_client(hWnd);
936 break;
937 case WM_TIMER:
938 break;
939 case WM_ENTERMENULOOP:
940 OnEnterMenuLoop(hWnd);
941 break;
942 case WM_EXITMENULOOP:
943 OnExitMenuLoop(hWnd);
944 break;
945 case WM_INITMENUPOPUP:
946 if (!HIWORD(lParam))
947 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
948 break;
949 case WM_MENUSELECT:
950 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
951 break;
952 case WM_DESTROY:
954 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
955 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
956 PostQuitMessage(0);
958 default:
959 return DefWindowProc(hWnd, message, wParam, lParam);
961 return 0;