regedit: Update Portuguese translation.
[wine] / programs / regedit / framewnd.c
1 /*
2  * Regedit frame window
3  *
4  * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #define WIN32_LEAN_AND_MEAN     /* Exclude rarely-used stuff from Windows headers */
22
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>
31
32 #include "main.h"
33 #include "regproc.h"
34 #include "wine/unicode.h"
35
36 /********************************************************************************
37  * Global and Local Variables:
38  */
39
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;
45
46 static WCHAR FileNameBuffer[_MAX_PATH];
47 static WCHAR FileTitleBuffer[_MAX_PATH];
48 static WCHAR FilterBuffer[_MAX_PATH];
49
50 /*******************************************************************************
51  * Local module support methods
52  */
53
54 static void resize_frame_rect(HWND hWnd, PRECT prect)
55 {
56     RECT rt;
57     /*
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;
63         }
64      */
65     if (IsWindowVisible(hStatusBar)) {
66         SetupStatusBar(hWnd, TRUE);
67         GetClientRect(hStatusBar, &rt);
68         prect->bottom -= rt.bottom;
69     }
70     MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
71 }
72
73 static void resize_frame_client(HWND hWnd)
74 {
75     RECT rect;
76
77     GetClientRect(hWnd, &rect);
78     resize_frame_rect(hWnd, &rect);
79 }
80
81 /********************************************************************************/
82
83 static void OnEnterMenuLoop(HWND hWnd)
84 {
85     int nParts;
86     WCHAR empty = 0;
87
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);
93 }
94
95 static void OnExitMenuLoop(HWND hWnd)
96 {
97     bInMenuLoop = FALSE;
98     /* Update the status bar pane sizes*/
99     SetupStatusBar(hWnd, TRUE);
100     UpdateStatusBar();
101 }
102
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;
111     }
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);
120
121     HeapFree(GetProcessHeap(), 0, keyName);
122 }
123
124 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
125 {
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;
148                     }
149                     AppendMenuW(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
150                 }
151                 i++;
152             } while(error == ERROR_SUCCESS);
153             RegCloseKey(hKey);
154         }
155     }
156     UpdateMenuItems(hMenu);
157 }
158
159 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
160 {
161     WCHAR str[100];
162
163     str[0] = 0;
164     if (nFlags & MF_POPUP) {
165         if (hSysMenu != GetMenu(hWnd)) {
166             if (nItemID == 2) nItemID = 5;
167         }
168     }
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';
176     }
177     SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)str);
178 }
179
180 void SetupStatusBar(HWND hWnd, BOOL bResize)
181 {
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();
191 }
192
193 void UpdateStatusBar(void)
194 {
195     LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
196     SendMessageW(hStatusBar, SB_SETTEXTW, 0, (LPARAM)fullPath);
197     HeapFree(GetProcessHeap(), 0, fullPath);
198 }
199
200 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
201 {
202     BOOL vis = IsWindowVisible(hchild);
203     HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
204
205     CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
206     ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
207     resize_frame_client(hWnd);
208 }
209
210 static BOOL CheckCommDlgError(HWND hWnd)
211 {
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;
246     }
247     return TRUE;
248 }
249
250 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAMEW *pOpenFileName)
251 {
252     if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
253     {
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);
257     }
258     else
259         pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR));
260 }
261
262 static UINT_PTR CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
263 {
264     static OPENFILENAMEW* pOpenFileName;
265     OFNOTIFYW *pOfNotify;
266
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)
278         {
279             case CDN_INITDONE:
280             {
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;
289             }
290             case CDN_FILEOK:
291                 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
292                 break;
293         }
294         break;
295     default:
296         break;
297     }
298     return 0L;
299 }
300
301
302 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAMEW *pofn)
303 {
304     memset(pofn, 0, sizeof(OPENFILENAMEW));
305     pofn->lStructSize = sizeof(OPENFILENAMEW);
306     pofn->hwndOwner = hWnd;
307     pofn->hInstance = hInst;
308
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;
320 }
321
322 static BOOL import_registry_filename(LPTSTR filename)
323 {
324     BOOL Success;
325     FILE* reg_file = fopen(filename, "r");
326
327     if(!reg_file)
328         return FALSE;
329
330     Success = import_registry_file(reg_file);
331
332     if(fclose(reg_file) != 0)
333         Success = FALSE;
334
335     return Success;
336 }
337
338 static BOOL ImportRegistryFile(HWND hWnd)
339 {
340     OPENFILENAMEW ofn;
341     WCHAR title[128];
342
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;
353         }
354         HeapFree(GetProcessHeap(), 0, fileA);
355     } else {
356         CheckCommDlgError(hWnd);
357     }
358     RefreshTreeView(g_pChildWnd->hTreeWnd);
359     return TRUE;
360 }
361
362
363 static BOOL ExportRegistryFile(HWND hWnd)
364 {
365     OPENFILENAMEW ofn;
366     WCHAR ExportKeyPath[_MAX_PATH];
367     WCHAR title[128];
368
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;
382         }
383     } else {
384         CheckCommDlgError(hWnd);
385     }
386     return TRUE;
387 }
388
389 static BOOL PrintRegistryHive(HWND hWnd, LPCWSTR path)
390 {
391 #if 1
392     PRINTDLGW pd;
393
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.*/
408     }
409 #else
410     HRESULT hResult;
411     PRINTDLGEXW pd;
412
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;
427         }
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;
447         }
448         return FALSE;
449     }
450 #endif
451     return TRUE;
452 }
453
454 static BOOL CopyKeyName(HWND hWnd, LPCWSTR keyName)
455 {
456     BOOL result;
457
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);
468
469         } else {
470             /* error emptying clipboard*/
471             /* DWORD dwError = GetLastError(); */
472             ;
473         }
474         if (!CloseClipboard()) {
475             /* error closing clipboard*/
476             /* DWORD dwError = GetLastError(); */
477             ;
478         }
479     } else {
480         /* error opening clipboard*/
481         /* DWORD dwError = GetLastError(); */
482         ;
483     }
484     return result;
485 }
486
487 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
488 {
489     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
490             
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;
507                 }
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);
519                 }
520                 return TRUE;
521             case IDCANCEL:
522                 EndDialog(hwndDlg, IDCANCEL);
523                 return TRUE;
524             }
525             break;
526     }
527     return FALSE;
528 }
529                     
530 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
531 {
532     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
533             
534     switch(uMsg) {
535         case WM_INITDIALOG:
536         {
537             HKEY hKeyRoot = NULL;
538             LPWSTR ItemPath = GetItemPath(g_pChildWnd->hTreeWnd, NULL, &hKeyRoot);
539
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;
547         }
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;
554                 }
555                 break;
556             case IDOK:
557                 if (GetWindowTextLengthW(hwndValue)>0) {
558                     GetWindowTextW(hwndValue, favoriteName, 128);
559                     EndDialog(hwndDlg, IDOK);
560                 }
561                 return TRUE;
562             case IDCANCEL:
563                 EndDialog(hwndDlg, IDCANCEL);
564                 return TRUE;
565             }
566             break;
567     }
568     return FALSE;
569 }
570                     
571 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
572 {
573     HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
574             
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);
594                     }
595                     i++;
596                 } while(error == ERROR_SUCCESS);
597                 RegCloseKey(hKey);
598             }
599             else
600                 return FALSE;
601             EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
602             SendMessageW(hwndList, LB_SETCURSEL, 0, 0);
603             return TRUE;
604         }
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;
611                 }
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);
624                 }
625                 return TRUE;
626             }
627             case IDCANCEL:
628                 EndDialog(hwndDlg, IDCANCEL);
629                 return TRUE;
630             }
631             break;
632     }
633     return FALSE;
634 }
635                     
636 /*******************************************************************************
637  *
638  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
639  *
640  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
641  *
642  */
643 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
644 {
645     HKEY hKeyRoot = 0;
646     DWORD valueType;
647     int curIndex;
648     BOOL firstItem = TRUE;
649
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) );
661             }
662             RegCloseKey(hKey);
663         }
664         return TRUE;
665     }
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:
679     {
680         const WCHAR empty = 0;
681         PrintRegistryHive(hWnd, &empty);
682         break;
683     }
684     case ID_EDIT_DELETE:
685     {
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);
693             }
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);
700
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;
707             }
708
709             if (!DeleteValue(hWnd, hKeyRoot, keyPath, valueName, curIndex==-1 && firstItem))
710             {
711                 HeapFree(GetProcessHeap(), 0, valueName);
712                 break;
713             }
714             firstItem = FALSE;
715             HeapFree(GetProcessHeap(), 0, valueName);
716         }
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);
722         }
723         break;
724     }
725     case ID_EDIT_MODIFY:
726     {
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;
733     }
734     case ID_EDIT_FIND:
735     case ID_EDIT_FINDNEXT:
736     {
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);
759                 }
760             } else {
761                 error(hWnd, IDS_NOTFOUND, searchString);
762             }
763         }
764         break;
765     }
766     case ID_EDIT_COPYKEYNAME:
767     {
768         LPWSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
769         if (fullPath) {
770             CopyKeyName(hWnd, fullPath);
771             HeapFree(GetProcessHeap(), 0, fullPath);
772         }
773         break;
774     }
775     case ID_EDIT_NEW_KEY:
776     {
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);
782         }
783         HeapFree(GetProcessHeap(), 0, keyPath);
784     }
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:
799     {
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);
805         }
806         HeapFree(GetProcessHeap(), 0, keyPath);
807     }
808         break;
809     case ID_EDIT_RENAME:
810     {
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);
818         }
819         HeapFree(GetProcessHeap(), 0, keyPath);
820     }
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:
834     {
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);
844                 }
845             }
846             HeapFree(GetProcessHeap(), 0, lpKeyPath);
847         }
848         break;
849     }
850     case ID_FAVORITES_REMOVEFAVORITE:
851     {
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);
858             }
859         }
860         break;
861     }
862     case ID_VIEW_REFRESH:
863     {
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);
868     }
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:
877     {
878         const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
879         WinHelpW(hWnd, help_regedit, HELP_FINDER, 0);
880         break;
881     }
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));
896         }
897         return TRUE;
898     }
899     default:
900         return FALSE;
901     }
902
903     return TRUE;
904 }
905
906 /********************************************************************************
907  *
908  *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
909  *
910  *  PURPOSE:  Processes messages for the main frame window.
911  *
912  *  WM_COMMAND  - process the application menu
913  *  WM_DESTROY  - post a quit message and return
914  *
915  */
916
917 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
918 {
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:
952     {
953         const WCHAR help_regedit[] = {'r','e','g','e','d','i','t',0};
954         WinHelpW(hWnd, help_regedit, HELP_QUIT, 0);
955         PostQuitMessage(0);
956     }
957     default:
958         return DefWindowProc(hWnd, message, wParam, lParam);
959     }
960     return 0;
961 }