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