po: Update Japanese translation.
[wine/multimedia.git] / programs / regedit / framewnd.c
blob0cdedeccec7248beddad2d4e5bdb37182a37fe12
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 HTREEITEM selection;
110 selection = (HTREEITEM)SendMessageW(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, 0);
111 keyName = GetItemPath(hwndTV, selection, &hRootKey);
112 if (GetFocus() != hwndTV || (keyName && *keyName)) { /* can't modify root keys, but allow for their values */
113 bAllowEdit = TRUE;
115 EnableMenuItem(hMenu, ID_EDIT_FIND, MF_ENABLED | MF_BYCOMMAND);
116 EnableMenuItem(hMenu, ID_EDIT_FINDNEXT, MF_ENABLED | MF_BYCOMMAND);
117 EnableMenuItem(hMenu, ID_EDIT_MODIFY, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
118 EnableMenuItem(hMenu, ID_EDIT_DELETE, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
119 EnableMenuItem(hMenu, ID_EDIT_RENAME, (bAllowEdit ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
120 EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
121 EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE,
122 (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
124 HeapFree(GetProcessHeap(), 0, keyName);
127 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
129 if (wItem == 3) {
130 HKEY hKey;
131 while(GetMenuItemCount(hMenu)>2)
132 DeleteMenu(hMenu, 2, MF_BYPOSITION);
133 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
134 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
135 WCHAR namebuf[KEY_MAX_LEN];
136 BYTE valuebuf[4096];
137 int i = 0;
138 BOOL sep = FALSE;
139 DWORD ksize, vsize, type;
140 LONG error;
141 do {
142 ksize = KEY_MAX_LEN;
143 vsize = sizeof(valuebuf);
144 error = RegEnumValueW(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
145 if (error != ERROR_SUCCESS)
146 break;
147 if (type == REG_SZ) {
148 if (!sep) {
149 AppendMenuW(hMenu, MF_SEPARATOR, -1, NULL);
150 sep = TRUE;
152 AppendMenuW(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
154 i++;
155 } while(error == ERROR_SUCCESS);
156 RegCloseKey(hKey);
159 UpdateMenuItems(hMenu);
162 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
164 WCHAR str[100];
166 str[0] = 0;
167 if (nFlags & MF_POPUP) {
168 if (hSysMenu != GetMenu(hWnd)) {
169 if (nItemID == 2) nItemID = 5;
172 if (LoadStringW(hInst, nItemID, str, 100)) {
173 /* load appropriate string*/
174 LPWSTR lpsz = str;
175 /* first newline terminates actual string*/
176 lpsz = strchrW(lpsz, '\n');
177 if (lpsz != NULL)
178 *lpsz = '\0';
180 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
183 void SetupStatusBar(HWND hWnd, BOOL bResize)
185 RECT rc;
186 int nParts;
187 GetClientRect(hWnd, &rc);
188 nParts = rc.right;
189 /* nParts = -1;*/
190 if (bResize)
191 SendMessageW(hStatusBar, WM_SIZE, 0, 0);
192 SendMessageW(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
193 UpdateStatusBar();
196 void UpdateStatusBar(void)
198 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
199 SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
200 HeapFree(GetProcessHeap(), 0, fullPath);
203 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
205 BOOL vis = IsWindowVisible(hchild);
206 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
208 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
209 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
210 resize_frame_client(hWnd);
213 static BOOL CheckCommDlgError(HWND hWnd)
215 DWORD dwErrorCode = CommDlgExtendedError();
216 switch (dwErrorCode) {
217 case CDERR_DIALOGFAILURE:
218 break;
219 case CDERR_FINDRESFAILURE:
220 break;
221 case CDERR_NOHINSTANCE:
222 break;
223 case CDERR_INITIALIZATION:
224 break;
225 case CDERR_NOHOOK:
226 break;
227 case CDERR_LOCKRESFAILURE:
228 break;
229 case CDERR_NOTEMPLATE:
230 break;
231 case CDERR_LOADRESFAILURE:
232 break;
233 case CDERR_STRUCTSIZE:
234 break;
235 case CDERR_LOADSTRFAILURE:
236 break;
237 case FNERR_BUFFERTOOSMALL:
238 break;
239 case CDERR_MEMALLOCFAILURE:
240 break;
241 case FNERR_INVALIDFILENAME:
242 break;
243 case CDERR_MEMLOCKFAILURE:
244 break;
245 case FNERR_SUBCLASSFAILURE:
246 break;
247 default:
248 break;
250 return TRUE;
253 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
255 if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
257 INT len = SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
258 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
259 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
261 else
262 pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
265 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
267 static OPENFILENAMEW* pOpenFileName;
268 OFNOTIFYW *pOfNotify;
270 switch (uiMsg) {
271 case WM_INITDIALOG:
272 pOpenFileName = (OPENFILENAMEW*)lParam;
273 break;
274 case WM_COMMAND:
275 if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
276 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
277 break;
278 case WM_NOTIFY:
279 pOfNotify = (OFNOTIFYW*)lParam;
280 switch (pOfNotify->hdr.code)
282 case CDN_INITDONE:
284 BOOL export_branch = FALSE;
285 WCHAR* path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
286 SendDlgItemMessageW(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
287 if (path && strlenW(path) > 0)
288 export_branch = TRUE;
289 HeapFree(GetProcessHeap(), 0, path);
290 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, export_branch ? IDC_EXPORT_SELECTED : IDC_EXPORT_ALL);
291 break;
293 case CDN_FILEOK:
294 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
295 break;
297 break;
298 default:
299 break;
301 return 0L;
305 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
307 memset(pofn, 0, sizeof(OPENFILENAMEW));
308 pofn->lStructSize = sizeof(OPENFILENAMEW);
309 pofn->hwndOwner = hWnd;
310 pofn->hInstance = hInst;
312 if (FilterBuffer[0] == 0)
314 static const WCHAR filterW[] = {'%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','r','e','g','%','c','%','s','%','c','*','.','*','%','c',0};
315 WCHAR filter_reg[MAX_PATH], filter_reg4[MAX_PATH], filter_all[MAX_PATH];
317 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG, filter_reg, MAX_PATH);
318 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_REG4, filter_reg4, MAX_PATH);
319 LoadStringW(hInst, IDS_FILEDIALOG_FILTER_ALL, filter_all, MAX_PATH);
320 snprintfW( FilterBuffer, MAX_PATH, filterW, filter_reg, 0, 0, filter_reg4, 0, 0, filter_all, 0, 0 );
322 pofn->lpstrFilter = FilterBuffer;
323 pofn->nFilterIndex = 2;
324 pofn->lpstrFile = FileNameBuffer;
325 pofn->nMaxFile = _MAX_PATH;
326 pofn->lpstrFileTitle = FileTitleBuffer;
327 pofn->nMaxFileTitle = _MAX_PATH;
328 pofn->Flags = OFN_HIDEREADONLY;
329 /* some other fields may be set by the caller */
330 return TRUE;
333 static BOOL import_registry_filename(LPWSTR filename)
335 static const WCHAR mode_r[] = {'r',0};
337 BOOL Success;
338 FILE* reg_file = _wfopen(filename, mode_r);
340 if(!reg_file)
341 return FALSE;
343 Success = import_registry_file(reg_file);
345 if(fclose(reg_file) != 0)
346 Success = FALSE;
348 return Success;
351 static BOOL ImportRegistryFile(HWND hWnd)
353 OPENFILENAMEW ofn;
354 WCHAR title[128];
356 InitOpenFileName(hWnd, &ofn);
357 ofn.Flags |= OFN_ENABLESIZING;
358 LoadStringW(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
359 ofn.lpstrTitle = title;
360 if (GetOpenFileNameW(&ofn)) {
361 if (!import_registry_filename(ofn.lpstrFile))
362 return FALSE;
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(PRINTDLGW));
401 pd.lStructSize = sizeof(PRINTDLGW);
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), GetWindowTextLengthW(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 = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_SELECTED, 0));
700 while(curIndex != -1) {
701 WCHAR* valueName = GetItemText(g_pChildWnd->hListWnd, curIndex);
703 curIndex = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, curIndex, MAKELPARAM(LVNI_SELECTED, 0));
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 SendMessageW(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 DialogBoxW(0, MAKEINTRESOURCEW(IDD_FIND), hWnd, find_dlgproc) != IDOK)
742 break;
743 if (!*searchString)
744 break;
745 hItem = (HTREEITEM)SendMessageW(g_pChildWnd->hTreeWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
746 if (hItem) {
747 int row = SendMessageW(g_pChildWnd->hListWnd, LVM_GETNEXTITEM, -1, MAKELPARAM(LVNI_FOCUSED, 0));
748 HCURSOR hcursorOld = SetCursor(LoadCursorW(NULL, (LPCWSTR)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 LVITEMW item;
758 item.state = 0;
759 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
760 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, (UINT)-1, (LPARAM)&item);
762 item.state = LVIS_FOCUSED | LVIS_SELECTED;
763 item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
764 SendMessageW(g_pChildWnd->hListWnd, LVM_SETITEMSTATE, row, (LPARAM)&item);
765 SetFocus(g_pChildWnd->hListWnd);
766 } else {
767 SetFocus(g_pChildWnd->hTreeWnd);
769 } else {
770 error(hWnd, IDS_NOTFOUND, searchString);
773 break;
775 case ID_EDIT_COPYKEYNAME:
777 LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
778 if (fullPath) {
779 CopyKeyName(hWnd, fullPath);
780 HeapFree(GetProcessHeap(), 0, fullPath);
782 break;
784 case ID_EDIT_NEW_KEY:
786 WCHAR newKeyW[MAX_NEW_KEY_LEN];
787 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
788 if (CreateKey(hWnd, hKeyRoot, keyPath, newKeyW)) {
789 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKeyW))
790 StartKeyRename(g_pChildWnd->hTreeWnd);
792 HeapFree(GetProcessHeap(), 0, keyPath);
794 break;
795 case ID_EDIT_NEW_STRINGVALUE:
796 valueType = REG_SZ;
797 goto create_value;
798 case ID_EDIT_NEW_EXPANDVALUE:
799 valueType = REG_EXPAND_SZ;
800 goto create_value;
801 case ID_EDIT_NEW_MULTI_STRINGVALUE:
802 valueType = REG_MULTI_SZ;
803 goto create_value;
804 case ID_EDIT_NEW_BINARYVALUE:
805 valueType = REG_BINARY;
806 goto create_value;
807 case ID_EDIT_NEW_DWORDVALUE:
808 valueType = REG_DWORD;
809 /* fall through */
810 create_value:
812 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
813 WCHAR newKey[MAX_NEW_KEY_LEN];
814 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
815 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
816 StartValueRename(g_pChildWnd->hListWnd);
818 HeapFree(GetProcessHeap(), 0, keyPath);
820 break;
821 case ID_EDIT_RENAME:
823 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
824 if (keyPath == 0 || *keyPath == 0) {
825 MessageBeep(MB_ICONHAND);
826 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
827 StartKeyRename(g_pChildWnd->hTreeWnd);
828 } else if (GetFocus() == g_pChildWnd->hListWnd) {
829 StartValueRename(g_pChildWnd->hListWnd);
831 HeapFree(GetProcessHeap(), 0, keyPath);
833 break;
834 case ID_REGISTRY_PRINTERSETUP:
835 /*PRINTDLG pd;*/
836 /*PrintDlg(&pd);*/
837 /*PAGESETUPDLG psd;*/
838 /*PageSetupDlg(&psd);*/
839 break;
840 case ID_REGISTRY_OPENLOCAL:
841 break;
842 case ID_REGISTRY_EXIT:
843 DestroyWindow(hWnd);
844 break;
845 case ID_FAVORITES_ADDTOFAVORITES:
847 HKEY hKey;
848 LPWSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
849 if (lpKeyPath) {
850 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
851 if (RegCreateKeyExW(HKEY_CURRENT_USER, favoritesKey,
852 0, NULL, 0,
853 KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
854 RegSetValueExW(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (lstrlenW(lpKeyPath)+1)*sizeof(WCHAR));
855 RegCloseKey(hKey);
858 HeapFree(GetProcessHeap(), 0, lpKeyPath);
860 break;
862 case ID_FAVORITES_REMOVEFAVORITE:
864 if (DialogBoxW(0, MAKEINTRESOURCEW(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
865 HKEY hKey;
866 if (RegOpenKeyExW(HKEY_CURRENT_USER, favoritesKey,
867 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
868 RegDeleteValueW(hKey, favoriteName);
869 RegCloseKey(hKey);
872 break;
874 case ID_VIEW_REFRESH:
876 WCHAR* keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
877 RefreshTreeView(g_pChildWnd->hTreeWnd);
878 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
879 HeapFree(GetProcessHeap(), 0, keyPath);
881 break;
882 /*case ID_OPTIONS_TOOLBAR:*/
883 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
884 /* break;*/
885 case ID_VIEW_STATUSBAR:
886 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
887 break;
888 case ID_HELP_HELPTOPICS:
890 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
891 WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
892 break;
894 case ID_HELP_ABOUT:
895 ShowAboutBox(hWnd);
896 break;
897 case ID_VIEW_SPLIT: {
898 RECT rt;
899 POINT pt, pts;
900 GetClientRect(g_pChildWnd->hWnd, &rt);
901 pt.x = rt.left + g_pChildWnd->nSplitPos;
902 pt.y = (rt.bottom / 2);
903 pts = pt;
904 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
905 SetCursorPos(pts.x, pts.y);
906 SetCursor(LoadCursorW(0, (LPCWSTR)IDC_SIZEWE));
907 SendMessageW(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
909 return TRUE;
911 default:
912 return FALSE;
915 return TRUE;
918 /********************************************************************************
920 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
922 * PURPOSE: Processes messages for the main frame window.
924 * WM_COMMAND - process the application menu
925 * WM_DESTROY - post a quit message and return
929 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
931 static const WCHAR captionW[] = {'r','e','g','e','d','i','t',' ','c','h','i','l','d',' ','w','i','n','d','o','w',0};
933 switch (message) {
934 case WM_CREATE:
935 CreateWindowExW(0, szChildClass, captionW, WS_CHILD | WS_VISIBLE,
936 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
937 hWnd, NULL, hInst, 0);
938 break;
939 case WM_COMMAND:
940 if (!_CmdWndProc(hWnd, message, wParam, lParam))
941 return DefWindowProcW(hWnd, message, wParam, lParam);
942 break;
943 case WM_ACTIVATE:
944 if (LOWORD(hWnd))
945 SetFocus(g_pChildWnd->hWnd);
946 break;
947 case WM_SIZE:
948 resize_frame_client(hWnd);
949 break;
950 case WM_TIMER:
951 break;
952 case WM_ENTERMENULOOP:
953 OnEnterMenuLoop(hWnd);
954 break;
955 case WM_EXITMENULOOP:
956 OnExitMenuLoop(hWnd);
957 break;
958 case WM_INITMENUPOPUP:
959 if (!HIWORD(lParam))
960 OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
961 break;
962 case WM_MENUSELECT:
963 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
964 break;
965 case WM_DESTROY:
967 const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
968 WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
969 PostQuitMessage(0);
971 default:
972 return DefWindowProcW(hWnd, message, wParam, lParam);
974 return 0;