push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / programs / regedit / framewnd.c
bloba737d8d84fa040b62c15eebabe431003fd4fd80e
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)
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 ofn.Flags |= OFN_ENABLESIZING;
345 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
346 ofn.lpstrTitle = title;
347 if (GetOpenFileNameW(&ofn)) {
348 CHAR* fileA = GetMultiByteString(ofn.lpstrFile);
349 if (!import_registry_filename(fileA)) {
350 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
351 HeapFree(GetProcessHeap(), 0, fileA);
352 return FALSE;
354 HeapFree(GetProcessHeap(), 0, fileA);
355 } else {
356 CheckCommDlgError(hWnd);
358 RefreshTreeView(g_pChildWnd->hTreeWnd);
359 return TRUE;
363 static BOOL ExportRegistryFile(HWND hWnd)
365 OPENFILENAMEW ofn;
366 WCHAR ExportKeyPath[_MAX_PATH];
367 WCHAR title[128];
369 ExportKeyPath[0] = 0;
370 InitOpenFileName(hWnd, &ofn);
371 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
372 ofn.lpstrTitle = title;
373 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
374 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
375 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
376 if (GetSaveFileNameW(&ofn)) {
377 BOOL result;
378 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
379 if (!result) {
380 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
381 return FALSE;
383 } else {
384 CheckCommDlgError(hWnd);
386 return TRUE;
389 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
391 #if 1
392 PRINTDLGW pd;
394 ZeroMemory(&pd, sizeof(PRINTDLG));
395 pd.lStructSize = sizeof(PRINTDLG);
396 pd.hwndOwner = hWnd;
397 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
398 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
399 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
400 pd.nCopies = 1;
401 pd.nFromPage = 0xFFFF;
402 pd.nToPage = 0xFFFF;
403 pd.nMinPage = 1;
404 pd.nMaxPage = 0xFFFF;
405 if (PrintDlgW(&pd)) {
406 /* GDI calls to render output. */
407 DeleteDC(pd.hDC); /* Delete DC when done.*/
409 #else
410 HRESULT hResult;
411 PRINTDLGEXW pd;
413 hResult = PrintDlgExW(&pd);
414 if (hResult == S_OK) {
415 switch (pd.dwResultAction) {
416 case PD_RESULT_APPLY:
417 /*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. */
418 break;
419 case PD_RESULT_CANCEL:
420 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
421 break;
422 case PD_RESULT_PRINT:
423 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
424 break;
425 default:
426 break;
428 } else {
429 switch (hResult) {
430 case E_OUTOFMEMORY:
431 /*Insufficient memory. */
432 break;
433 case E_INVALIDARG:
434 /* One or more arguments are invalid. */
435 break;
436 case E_POINTER:
437 /*Invalid pointer. */
438 break;
439 case E_HANDLE:
440 /*Invalid handle. */
441 break;
442 case E_FAIL:
443 /*Unspecified error. */
444 break;
445 default:
446 break;
448 return FALSE;
450 #endif
451 return TRUE;
454 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
456 BOOL result;
458 result = OpenClipboard(hWnd);
459 if (result) {
460 result = EmptyClipboard();
461 if (result) {
462 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
463 HANDLE hClipData = GlobalAlloc(GHND, len);
464 LPVOID pLoc = GlobalLock(hClipData);
465 lstrcpyW(pLoc, keyName);
466 GlobalUnlock(hClipData);
467 hClipData = SetClipboardData(CF_UNICODETEXT, hClipData);
469 } else {
470 /* error emptying clipboard*/
471 /* DWORD dwError = GetLastError(); */
474 if (!CloseClipboard()) {
475 /* error closing clipboard*/
476 /* DWORD dwError = GetLastError(); */
479 } else {
480 /* error opening clipboard*/
481 /* DWORD dwError = GetLastError(); */
484 return result;
487 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
489 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
491 switch(uMsg) {
492 case WM_INITDIALOG:
493 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
494 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
495 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
496 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
497 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
498 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
499 SetWindowTextW(hwndValue, searchString);
500 return TRUE;
501 case WM_COMMAND:
502 switch(LOWORD(wParam)) {
503 case IDC_VALUE_NAME:
504 if (HIWORD(wParam) == EN_UPDATE) {
505 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
506 return TRUE;
508 break;
509 case IDOK:
510 if (GetWindowTextLengthW(hwndValue)>0) {
511 int mask = 0;
512 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
513 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
514 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
515 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
516 searchMask = mask;
517 GetWindowTextW(hwndValue, searchString, 128);
518 EndDialog(hwndDlg, IDOK);
520 return TRUE;
521 case IDCANCEL:
522 EndDialog(hwndDlg, IDCANCEL);
523 return TRUE;
525 break;
527 return FALSE;
530 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
532 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
534 switch(uMsg) {
535 case WM_INITDIALOG:
537 HKEY hKeyRoot = NULL;
538 LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
540 if(!ItemPath || !*ItemPath)
541 ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
542 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
543 SetWindowTextW(hwndValue, ItemPath);
544 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
545 HeapFree(GetProcessHeap(), 0, ItemPath);
546 return TRUE;
548 case WM_COMMAND:
549 switch(LOWORD(wParam)) {
550 case IDC_VALUE_NAME:
551 if (HIWORD(wParam) == EN_UPDATE) {
552 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(hwndValue)>0);
553 return TRUE;
555 break;
556 case IDOK:
557 if (GetWindowTextLengthW(hwndValue)>0) {
558 GetWindowTextW(hwndValue, favoriteName, 128);
559 EndDialog(hwndDlg, IDOK);
561 return TRUE;
562 case IDCANCEL:
563 EndDialog(hwndDlg, IDCANCEL);
564 return TRUE;
566 break;
568 return FALSE;
571 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
573 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
575 switch(uMsg) {
576 case WM_INITDIALOG: {
577 HKEY hKey;
578 int i = 0;
579 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
580 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
581 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
582 WCHAR namebuf[KEY_MAX_LEN];
583 BYTE valuebuf[4096];
584 DWORD ksize, vsize, type;
585 LONG error;
586 do {
587 ksize = KEY_MAX_LEN;
588 vsize = sizeof(valuebuf);
589 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
590 if (error != ERROR_SUCCESS)
591 break;
592 if (type == REG_SZ) {
593 SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
595 i++;
596 } while(error == ERROR_SUCCESS);
597 RegCloseKey(hKey);
599 else
600 return FALSE;
601 EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
602 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
603 return TRUE;
605 case WM_COMMAND:
606 switch(LOWORD(wParam)) {
607 case IDC_NAME_LIST:
608 if (HIWORD(wParam) == LBN_SELCHANGE) {
609 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
610 return TRUE;
612 break;
613 case IDOK: {
614 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
615 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
616 if (len>0) {
617 LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
618 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
619 if (len>127)
620 lpName[127] = '\0';
621 lstrcpyW(favoriteName, lpName);
622 EndDialog(hwndDlg, IDOK);
623 HeapFree(GetProcessHeap(), 0, lpName);
625 return TRUE;
627 case IDCANCEL:
628 EndDialog(hwndDlg, IDCANCEL);
629 return TRUE;
631 break;
633 return FALSE;
636 /*******************************************************************************
638 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
640 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
643 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
645 HKEY hKeyRoot = 0;
646 DWORD valueType;
647 int curIndex;
648 BOOL firstItem = TRUE;
650 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
651 HKEY hKey;
652 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
653 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
654 WCHAR namebuf[KEY_MAX_LEN];
655 BYTE valuebuf[4096];
656 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
657 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
658 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
659 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
660 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
662 RegCloseKey(hKey);
664 return TRUE;
666 switch (LOWORD(wParam)) {
667 case ID_REGISTRY_IMPORTREGISTRYFILE:
668 ImportRegistryFile(hWnd);
669 break;
670 case ID_EDIT_EXPORT:
671 case ID_REGISTRY_EXPORTREGISTRYFILE:
672 ExportRegistryFile(hWnd);
673 break;
674 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
675 break;
676 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
677 break;
678 case ID_REGISTRY_PRINT:
680 const WCHAR empty = 0;
681 PrintRegistryHive(hWnd, &empty);
682 break;
684 case ID_EDIT_DELETE:
686 HWND hWndDelete = GetFocus();
687 if (hWndDelete == g_pChildWnd->hTreeWnd) {
688 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
689 if (keyPath == 0 || *keyPath == 0) {
690 MessageBeep(MB_ICONHAND);
691 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
692 DeleteNode(g_pChildWnd->hTreeWnd, 0);
694 HeapFree(GetProcessHeap(), 0, keyPath);
695 } else if (hWndDelete == g_pChildWnd->hListWnd) {
696 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
697 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
698 while(curIndex != -1) {
699 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
701 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, curIndex, LVNI_SELECTED);
702 if(curIndex != -1 && firstItem) {
703 if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_BOX_TEXT_MULTIPLE),
704 MAKEINTRESOURCEW(IDS_DELETE_BOX_TITLE),
705 MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
706 break;
709 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
711 HeapFree(GetProcessHeap(), 0, valueName);
712 break;
714 firstItem = FALSE;
715 HeapFree(GetProcessHeap(), 0, valueName);
717 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
718 HeapFree(GetProcessHeap(), 0, keyPath);
719 } else if (IsChild(g_pChildWnd->hTreeWnd, hWndDelete) ||
720 IsChild(g_pChildWnd->hListWnd, hWndDelete)) {
721 SendMessage(hWndDelete, WM_KEYDOWN, VK_DELETE, 0);
723 break;
725 case ID_EDIT_MODIFY:
727 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
728 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
729 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
730 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
731 HeapFree(GetProcessHeap(), 0, keyPath);
732 break;
734 case ID_EDIT_FIND:
735 case ID_EDIT_FINDNEXT:
737 HTREEITEM hItem;
738 if (LOWORD(wParam) == ID_EDIT_FIND &&
739 DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
740 break;
741 if (!*searchString)
742 break;
743 hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
744 if (hItem) {
745 int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
746 HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
747 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
748 SetCursor(hcursorOld);
749 if (hItem) {
750 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
751 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
752 UpdateWindow(g_pChildWnd->hTreeWnd);
753 if (row != -1) {
754 ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
755 ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
756 SetFocus(g_pChildWnd->hListWnd);
757 } else {
758 SetFocus(g_pChildWnd->hTreeWnd);
760 } else {
761 error(hWnd, IDS_NOTFOUND, searchString);
764 break;
766 case ID_EDIT_COPYKEYNAME:
768 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
769 if (fullPath) {
770 CopyKeyName(hWnd, fullPath);
771 HeapFree(GetProcessHeap(), 0, fullPath);
773 break;
775 case ID_EDIT_NEW_KEY:
777 WCHAR newKeyW[MAX_NEW_KEY_LEN];
778 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
779 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
780 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
781 StartKeyRename(g_pChildWnd->hTreeWnd);
783 HeapFree(GetProcessHeap(), 0, keyPath);
785 break;
786 case ID_EDIT_NEW_STRINGVALUE:
787 valueType = REG_SZ;
788 goto create_value;
789 case ID_EDIT_NEW_MULTI_STRINGVALUE:
790 valueType = REG_MULTI_SZ;
791 goto create_value;
792 case ID_EDIT_NEW_BINARYVALUE:
793 valueType = REG_BINARY;
794 goto create_value;
795 case ID_EDIT_NEW_DWORDVALUE:
796 valueType = REG_DWORD;
797 /* fall through */
798 create_value:
800 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
801 WCHAR newKey[MAX_NEW_KEY_LEN];
802 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
803 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
804 StartValueRename(g_pChildWnd->hListWnd);
806 HeapFree(GetProcessHeap(), 0, keyPath);
808 break;
809 case ID_EDIT_RENAME:
811 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
812 if (keyPath == 0 || *keyPath == 0) {
813 MessageBeep(MB_ICONHAND);
814 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
815 StartKeyRename(g_pChildWnd->hTreeWnd);
816 } else if (GetFocus() == g_pChildWnd->hListWnd) {
817 StartValueRename(g_pChildWnd->hListWnd);
819 HeapFree(GetProcessHeap(), 0, keyPath);
821 break;
822 case ID_REGISTRY_PRINTERSETUP:
823 /*PRINTDLG pd;*/
824 /*PrintDlg(&pd);*/
825 /*PAGESETUPDLG psd;*/
826 /*PageSetupDlg(&psd);*/
827 break;
828 case ID_REGISTRY_OPENLOCAL:
829 break;
830 case ID_REGISTRY_EXIT:
831 DestroyWindow(hWnd);
832 break;
833 case ID_FAVORITES_ADDTOFAVORITES:
835 HKEY hKey;
836 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
837 if (lpKeyPath) {
838 if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
839 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
840 0, NULL, 0,
841 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
842 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
843 RegCloseKey(hKey);
846 HeapFree(GetProcessHeap(), 0, lpKeyPath);
848 break;
850 case ID_FAVORITES_REMOVEFAVORITE:
852 if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
853 HKEY hKey;
854 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
855 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
856 RegDeleteValueW(hKey, favoriteName);
857 RegCloseKey(hKey);
860 break;
862 case ID_VIEW_REFRESH:
864 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
865 RefreshTreeView(g_pChildWnd->hTreeWnd);
866 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
867 HeapFree(GetProcessHeap(), 0, keyPath);
869 break;
870 /*case ID_OPTIONS_TOOLBAR:*/
871 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
872 /* break;*/
873 case ID_VIEW_STATUSBAR:
874 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
875 break;
876 case ID_HELP_HELPTOPICS:
878 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
879 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
880 break;
882 case ID_HELP_ABOUT:
883 ShowAboutBox(hWnd);
884 break;
885 case ID_VIEW_SPLIT: {
886 RECT rt;
887 POINT pt, pts;
888 GetClientRect(g_pChildWnd->hWnd, &rt);
889 pt.x = rt.left + g_pChildWnd->nSplitPos;
890 pt.y = (rt.bottom / 2);
891 pts = pt;
892 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
893 SetCursorPos(pts.x, pts.y);
894 SetCursor(LoadCursor(0, IDC_SIZEWE));
895 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
897 return TRUE;
899 default:
900 return FALSE;
903 return TRUE;
906 /********************************************************************************
908 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
910 * PURPOSE: Processes messages for the main frame window.
912 * WM_COMMAND - process the application menu
913 * WM_DESTROY - post a quit message and return
917 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
919 switch (message) {
920 case WM_CREATE:
921 CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
922 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
923 hWnd, NULL, hInst, 0);
924 break;
925 case WM_COMMAND:
926 if (!_CmdWndProc(hWnd, message, wParam, lParam))
927 return DefWindowProc(hWnd, message, wParam, lParam);
928 break;
929 case WM_ACTIVATE:
930 if (LOWORD(hWnd))
931 SetFocus(g_pChildWnd->hWnd);
932 break;
933 case WM_SIZE:
934 resize_frame_client(hWnd);
935 break;
936 case WM_TIMER:
937 break;
938 case WM_ENTERMENULOOP:
939 OnEnterMenuLoop(hWnd);
940 break;
941 case WM_EXITMENULOOP:
942 OnExitMenuLoop(hWnd);
943 break;
944 case WM_INITMENUPOPUP:
945 if (!HIWORD(lParam))
946 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
947 break;
948 case WM_MENUSELECT:
949 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
950 break;
951 case WM_DESTROY:
953 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
954 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
955 PostQuitMessage(0);
957 default:
958 return DefWindowProc(hWnd, message, wParam, lParam);
960 return 0;