push 52c8025cfe276c5cfd77ca72ad5fc2909af0f7c3
[wine/hacks.git] / programs / regedit / framewnd.c
blob4d8056e94ec15503f1a793d6a5dd90913eed3312
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 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
282 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
283 HeapFree(GetProcessHeap(), 0, path);
284 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, pOpenFileName->lCustData ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
285 break;
287 case CDN_FILEOK:
288 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
289 break;
291 break;
292 default:
293 break;
295 return 0L;
299 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
301 memset(pofn, 0, sizeof(OPENFILENAMEW));
302 pofn->lStructSize = sizeof(OPENFILENAMEW);
303 pofn->hwndOwner = hWnd;
304 pofn->hInstance = hInst;
306 if (FilterBuffer[0] == 0)
307 LoadStringW(hInst, IDS_FILEDIALOG_FILTER, FilterBuffer, _MAX_PATH);
308 pofn->lpstrFilter = FilterBuffer;
309 pofn->nFilterIndex = 2;
310 pofn->lpstrFile = FileNameBuffer;
311 pofn->nMaxFile = _MAX_PATH;
312 pofn->lpstrFileTitle = FileTitleBuffer;
313 pofn->nMaxFileTitle = _MAX_PATH;
314 pofn->Flags = OFN_HIDEREADONLY;
315 /* some other fields may be set by the caller */
316 return TRUE;
319 static BOOL import_registry_filename(LPTSTR filename)
321 BOOL Success;
322 FILE* reg_file = fopen(filename, "r");
324 if(!reg_file)
325 return FALSE;
327 Success = import_registry_file(reg_file);
329 if(fclose(reg_file) != 0)
330 Success = FALSE;
332 return Success;
335 static BOOL ImportRegistryFile(HWND hWnd)
337 OPENFILENAMEW ofn;
338 WCHAR title[128];
340 InitOpenFileName(hWnd, &ofn);
341 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
342 ofn.lpstrTitle = title;
343 if (GetOpenFileNameW(&ofn)) {
344 CHAR* fileA = GetMultiByteString(ofn.lpstrFile);
345 if (!import_registry_filename(fileA)) {
346 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
347 HeapFree(GetProcessHeap(), 0, fileA);
348 return FALSE;
350 HeapFree(GetProcessHeap(), 0, fileA);
351 } else {
352 CheckCommDlgError(hWnd);
354 RefreshTreeView(g_pChildWnd->hTreeWnd);
355 return TRUE;
359 static BOOL ExportRegistryFile(HWND hWnd, BOOL export_branch)
361 OPENFILENAMEW ofn;
362 WCHAR ExportKeyPath[_MAX_PATH];
363 WCHAR title[128];
365 ExportKeyPath[0] = 0;
366 InitOpenFileName(hWnd, &ofn);
367 LoadStringW(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
368 ofn.lpstrTitle = title;
369 ofn.lCustData = export_branch;
370 ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
371 ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
372 ofn.lpTemplateName = MAKEINTRESOURCEW(IDD_EXPORT_TEMPLATE);
373 if (GetSaveFileNameW(&ofn)) {
374 BOOL result;
375 result = export_registry_key(ofn.lpstrFile, (LPWSTR)ofn.lCustData, ofn.nFilterIndex);
376 if (!result) {
377 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
378 return FALSE;
380 } else {
381 CheckCommDlgError(hWnd);
383 return TRUE;
386 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
388 #if 1
389 PRINTDLGW pd;
391 ZeroMemory(&pd, sizeof(PRINTDLG));
392 pd.lStructSize = sizeof(PRINTDLG);
393 pd.hwndOwner = hWnd;
394 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
395 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
396 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
397 pd.nCopies = 1;
398 pd.nFromPage = 0xFFFF;
399 pd.nToPage = 0xFFFF;
400 pd.nMinPage = 1;
401 pd.nMaxPage = 0xFFFF;
402 if (PrintDlgW(&pd)) {
403 /* GDI calls to render output. */
404 DeleteDC(pd.hDC); /* Delete DC when done.*/
406 #else
407 HRESULT hResult;
408 PRINTDLGEXW pd;
410 hResult = PrintDlgExW(&pd);
411 if (hResult == S_OK) {
412 switch (pd.dwResultAction) {
413 case PD_RESULT_APPLY:
414 /*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. */
415 break;
416 case PD_RESULT_CANCEL:
417 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
418 break;
419 case PD_RESULT_PRINT:
420 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
421 break;
422 default:
423 break;
425 } else {
426 switch (hResult) {
427 case E_OUTOFMEMORY:
428 /*Insufficient memory. */
429 break;
430 case E_INVALIDARG:
431 /* One or more arguments are invalid. */
432 break;
433 case E_POINTER:
434 /*Invalid pointer. */
435 break;
436 case E_HANDLE:
437 /*Invalid handle. */
438 break;
439 case E_FAIL:
440 /*Unspecified error. */
441 break;
442 default:
443 break;
445 return FALSE;
447 #endif
448 return TRUE;
451 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
453 BOOL result;
455 result = OpenClipboard(hWnd);
456 if (result) {
457 result = EmptyClipboard();
458 if (result) {
459 int len = (lstrlenW(keyName)+1)*sizeof(WCHAR);
460 HANDLE hClipData = GlobalAlloc(GHND, len);
461 LPVOID pLoc = GlobalLock(hClipData);
462 lstrcpyW(pLoc, keyName);
463 GlobalUnlock(hClipData);
464 hClipData = SetClipboardData(CF_UNICODETEXT, hClipData);
466 } else {
467 /* error emptying clipboard*/
468 /* DWORD dwError = GetLastError(); */
471 if (!CloseClipboard()) {
472 /* error closing clipboard*/
473 /* DWORD dwError = GetLastError(); */
476 } else {
477 /* error opening clipboard*/
478 /* DWORD dwError = GetLastError(); */
481 return result;
484 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
486 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
488 switch(uMsg) {
489 case WM_INITDIALOG:
490 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
491 CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
492 CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
493 CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
494 CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
495 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
496 SetWindowTextW(hwndValue, searchString);
497 return TRUE;
498 case WM_COMMAND:
499 switch(LOWORD(wParam)) {
500 case IDC_VALUE_NAME:
501 if (HIWORD(wParam) == EN_UPDATE) {
502 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLengthW(hwndValue)>0);
503 return TRUE;
505 break;
506 case IDOK:
507 if (GetWindowTextLengthW(hwndValue)>0) {
508 int mask = 0;
509 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
510 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
511 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
512 if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
513 searchMask = mask;
514 GetWindowTextW(hwndValue, searchString, 128);
515 EndDialog(hwndDlg, IDOK);
517 return TRUE;
518 case IDCANCEL:
519 EndDialog(hwndDlg, IDCANCEL);
520 return TRUE;
522 break;
524 return FALSE;
527 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
529 HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
531 switch(uMsg) {
532 case WM_INITDIALOG:
534 HKEY hKeyRoot = NULL;
535 LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
537 if(!ItemPath || !*ItemPath)
538 ItemPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
539 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
540 SetWindowTextW(hwndValue, ItemPath);
541 SendMessageW(hwndValue, EM_SETLIMITTEXT, 127, 0);
542 HeapFree(GetProcessHeap(), 0, ItemPath);
543 return TRUE;
545 case WM_COMMAND:
546 switch(LOWORD(wParam)) {
547 case IDC_VALUE_NAME:
548 if (HIWORD(wParam) == EN_UPDATE) {
549 EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(hwndValue)>0);
550 return TRUE;
552 break;
553 case IDOK:
554 if (GetWindowTextLengthW(hwndValue)>0) {
555 GetWindowTextW(hwndValue, favoriteName, 128);
556 EndDialog(hwndDlg, IDOK);
558 return TRUE;
559 case IDCANCEL:
560 EndDialog(hwndDlg, IDCANCEL);
561 return TRUE;
563 break;
565 return FALSE;
568 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
570 HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
572 switch(uMsg) {
573 case WM_INITDIALOG: {
574 HKEY hKey;
575 int i = 0;
576 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
577 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
578 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
579 WCHAR namebuf[KEY_MAX_LEN];
580 BYTE valuebuf[4096];
581 DWORD ksize, vsize, type;
582 LONG error;
583 do {
584 ksize = KEY_MAX_LEN;
585 vsize = sizeof(valuebuf);
586 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
587 if (error != ERROR_SUCCESS)
588 break;
589 if (type == REG_SZ) {
590 SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
592 i++;
593 } while(error == ERROR_SUCCESS);
594 RegCloseKey(hKey);
596 else
597 return FALSE;
598 EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
599 SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
600 return TRUE;
602 case WM_COMMAND:
603 switch(LOWORD(wParam)) {
604 case IDC_NAME_LIST:
605 if (HIWORD(wParam) == LBN_SELCHANGE) {
606 EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam != -1);
607 return TRUE;
609 break;
610 case IDOK: {
611 int pos = SendMessageW(hwndList, LB_GETCURSEL, 0, 0);
612 int len = SendMessageW(hwndList, LB_GETTEXTLEN, pos, 0);
613 if (len>0) {
614 LPWSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
615 SendMessageW(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
616 if (len>127)
617 lpName[127] = '\0';
618 lstrcpyW(favoriteName, lpName);
619 EndDialog(hwndDlg, IDOK);
620 HeapFree(GetProcessHeap(), 0, lpName);
622 return TRUE;
624 case IDCANCEL:
625 EndDialog(hwndDlg, IDCANCEL);
626 return TRUE;
628 break;
630 return FALSE;
633 /*******************************************************************************
635 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
637 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
640 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
642 HKEY hKeyRoot = 0;
643 DWORD valueType;
644 int curIndex;
645 BOOL firstItem = TRUE;
647 if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
648 HKEY hKey;
649 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
650 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
651 WCHAR namebuf[KEY_MAX_LEN];
652 BYTE valuebuf[4096];
653 DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
654 if (RegEnumValueW(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL,
655 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
656 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
657 (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (WCHAR *)valuebuf) );
659 RegCloseKey(hKey);
661 return TRUE;
663 switch (LOWORD(wParam)) {
664 case ID_REGISTRY_IMPORTREGISTRYFILE:
665 ImportRegistryFile(hWnd);
666 break;
667 case ID_EDIT_EXPORT:
668 ExportRegistryFile(hWnd, TRUE);
669 break;
670 case ID_REGISTRY_EXPORTREGISTRYFILE:
671 ExportRegistryFile(hWnd, FALSE);
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:
684 if (GetFocus() == g_pChildWnd->hTreeWnd) {
685 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
686 if (keyPath == 0 || *keyPath == 0) {
687 MessageBeep(MB_ICONHAND);
688 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
689 DeleteNode(g_pChildWnd->hTreeWnd, 0);
691 HeapFree(GetProcessHeap(), 0, keyPath);
692 } else if (GetFocus() == g_pChildWnd->hListWnd) {
693 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
694 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_SELECTED);
695 while(curIndex != -1) {
696 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
698 curIndex = ListView_GetNextItem(g_pChildWnd->hListWnd, curIndex, LVNI_SELECTED);
699 if(curIndex != -1 && firstItem) {
700 if (MessageBoxW(hWnd, MAKEINTRESOURCEW(IDS_DELETE_BOX_TEXT_MULTIPLE),
701 MAKEINTRESOURCEW(IDS_DELETE_BOX_TITLE),
702 MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
703 break;
706 if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
708 HeapFree(GetProcessHeap(), 0, valueName);
709 break;
711 firstItem = FALSE;
712 HeapFree(GetProcessHeap(), 0, valueName);
714 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
715 HeapFree(GetProcessHeap(), 0, keyPath);
717 break;
718 case ID_EDIT_MODIFY:
720 LPCWSTR valueName = GetValueName(g_pChildWnd->hListWnd);
721 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
722 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
723 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
724 HeapFree(GetProcessHeap(), 0, keyPath);
725 break;
727 case ID_EDIT_FIND:
728 case ID_EDIT_FINDNEXT:
730 HTREEITEM hItem;
731 if (LOWORD(wParam) == ID_EDIT_FIND &&
732 DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
733 break;
734 if (!*searchString)
735 break;
736 hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
737 if (hItem) {
738 int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
739 HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
740 hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
741 SetCursor(hcursorOld);
742 if (hItem) {
743 SendMessageW( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
744 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
745 UpdateWindow(g_pChildWnd->hTreeWnd);
746 if (row != -1) {
747 ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
748 ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
749 SetFocus(g_pChildWnd->hListWnd);
750 } else {
751 SetFocus(g_pChildWnd->hTreeWnd);
753 } else {
754 CHAR* searchStringA = GetMultiByteString(searchString);
755 error(hWnd, IDS_NOTFOUND, searchStringA);
756 HeapFree(GetProcessHeap(), 0, searchStringA);
759 break;
761 case ID_EDIT_COPYKEYNAME:
763 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
764 if (fullPath) {
765 CopyKeyName(hWnd, fullPath);
766 HeapFree(GetProcessHeap(), 0, fullPath);
768 break;
770 case ID_EDIT_NEW_KEY:
772 WCHAR newKeyW[MAX_NEW_KEY_LEN];
773 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
774 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
775 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
776 StartKeyRename(g_pChildWnd->hTreeWnd);
778 HeapFree(GetProcessHeap(), 0, keyPath);
780 break;
781 case ID_EDIT_NEW_STRINGVALUE:
782 valueType = REG_SZ;
783 goto create_value;
784 case ID_EDIT_NEW_MULTI_STRINGVALUE:
785 valueType = REG_MULTI_SZ;
786 goto create_value;
787 case ID_EDIT_NEW_BINARYVALUE:
788 valueType = REG_BINARY;
789 goto create_value;
790 case ID_EDIT_NEW_DWORDVALUE:
791 valueType = REG_DWORD;
792 /* fall through */
793 create_value:
795 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
796 WCHAR newKey[MAX_NEW_KEY_LEN];
797 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
798 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
799 StartValueRename(g_pChildWnd->hListWnd);
801 HeapFree(GetProcessHeap(), 0, keyPath);
803 break;
804 case ID_EDIT_RENAME:
806 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
807 if (keyPath == 0 || *keyPath == 0) {
808 MessageBeep(MB_ICONHAND);
809 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
810 StartKeyRename(g_pChildWnd->hTreeWnd);
811 } else if (GetFocus() == g_pChildWnd->hListWnd) {
812 StartValueRename(g_pChildWnd->hListWnd);
814 HeapFree(GetProcessHeap(), 0, keyPath);
816 break;
817 case ID_REGISTRY_PRINTERSETUP:
818 /*PRINTDLG pd;*/
819 /*PrintDlg(&pd);*/
820 /*PAGESETUPDLG psd;*/
821 /*PageSetupDlg(&psd);*/
822 break;
823 case ID_REGISTRY_OPENLOCAL:
824 break;
825 case ID_REGISTRY_EXIT:
826 DestroyWindow(hWnd);
827 break;
828 case ID_FAVORITES_ADDTOFAVORITES:
830 HKEY hKey;
831 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
832 if (lpKeyPath) {
833 if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
834 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
835 0, NULL, 0,
836 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
837 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
838 RegCloseKey(hKey);
841 HeapFree(GetProcessHeap(), 0, lpKeyPath);
843 break;
845 case ID_FAVORITES_REMOVEFAVORITE:
847 if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
848 HKEY hKey;
849 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
850 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
851 RegDeleteValueW(hKey, favoriteName);
852 RegCloseKey(hKey);
855 break;
857 case ID_VIEW_REFRESH:
859 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
860 RefreshTreeView(g_pChildWnd->hTreeWnd);
861 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
862 HeapFree(GetProcessHeap(), 0, keyPath);
864 break;
865 /*case ID_OPTIONS_TOOLBAR:*/
866 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
867 /* break;*/
868 case ID_VIEW_STATUSBAR:
869 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
870 break;
871 case ID_HELP_HELPTOPICS:
873 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
874 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
875 break;
877 case ID_HELP_ABOUT:
878 ShowAboutBox(hWnd);
879 break;
880 case ID_VIEW_SPLIT: {
881 RECT rt;
882 POINT pt, pts;
883 GetClientRect(g_pChildWnd->hWnd, &rt);
884 pt.x = rt.left + g_pChildWnd->nSplitPos;
885 pt.y = (rt.bottom / 2);
886 pts = pt;
887 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
888 SetCursorPos(pts.x, pts.y);
889 SetCursor(LoadCursor(0, IDC_SIZEWE));
890 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
892 return TRUE;
894 default:
895 return FALSE;
898 return TRUE;
901 /********************************************************************************
903 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
905 * PURPOSE: Processes messages for the main frame window.
907 * WM_COMMAND - process the application menu
908 * WM_DESTROY - post a quit message and return
912 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
914 switch (message) {
915 case WM_CREATE:
916 CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
917 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
918 hWnd, NULL, hInst, 0);
919 break;
920 case WM_COMMAND:
921 if (!_CmdWndProc(hWnd, message, wParam, lParam))
922 return DefWindowProc(hWnd, message, wParam, lParam);
923 break;
924 case WM_ACTIVATE:
925 if (LOWORD(hWnd))
926 SetFocus(g_pChildWnd->hWnd);
927 break;
928 case WM_SIZE:
929 resize_frame_client(hWnd);
930 break;
931 case WM_TIMER:
932 break;
933 case WM_ENTERMENULOOP:
934 OnEnterMenuLoop(hWnd);
935 break;
936 case WM_EXITMENULOOP:
937 OnExitMenuLoop(hWnd);
938 break;
939 case WM_INITMENUPOPUP:
940 if (!HIWORD(lParam))
941 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
942 break;
943 case WM_MENUSELECT:
944 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
945 break;
946 case WM_DESTROY:
948 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
949 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
950 PostQuitMessage(0);
952 default:
953 return DefWindowProc(hWnd, message, wParam, lParam);
955 return 0;