urlmon: Don't create stgmed_obj for binding to object.
[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
35 /********************************************************************************
36  * Global and Local Variables:
37  */
38
39 static TCHAR favoritesKey[] =  _T("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\RegEdit\\Favorites");
40 static BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
41 static TCHAR favoriteName[128];
42 static TCHAR searchString[128];
43 static int searchMask = SEARCH_KEYS | SEARCH_VALUES | SEARCH_CONTENT;
44
45 static TCHAR FileNameBuffer[_MAX_PATH];
46 static TCHAR FileTitleBuffer[_MAX_PATH];
47 static TCHAR FilterBuffer[_MAX_PATH];
48
49 /*******************************************************************************
50  * Local module support methods
51  */
52
53 static void resize_frame_rect(HWND hWnd, PRECT prect)
54 {
55     RECT rt;
56     /*
57         if (IsWindowVisible(hToolBar)) {
58                 SendMessage(hToolBar, WM_SIZE, 0, 0);
59                 GetClientRect(hToolBar, &rt);
60                 prect->top = rt.bottom+3;
61                 prect->bottom -= rt.bottom+3;
62         }
63      */
64     if (IsWindowVisible(hStatusBar)) {
65         SetupStatusBar(hWnd, TRUE);
66         GetClientRect(hStatusBar, &rt);
67         prect->bottom -= rt.bottom;
68     }
69     MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
70 }
71
72 static void resize_frame_client(HWND hWnd)
73 {
74     RECT rect;
75
76     GetClientRect(hWnd, &rect);
77     resize_frame_rect(hWnd, &rect);
78 }
79
80 /********************************************************************************/
81
82 static void OnEnterMenuLoop(HWND hWnd)
83 {
84     int nParts;
85
86     /* Update the status bar pane sizes */
87     nParts = -1;
88     SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts);
89     bInMenuLoop = TRUE;
90     SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
91 }
92
93 static void OnExitMenuLoop(HWND hWnd)
94 {
95     bInMenuLoop = FALSE;
96     /* Update the status bar pane sizes*/
97     SetupStatusBar(hWnd, TRUE);
98     UpdateStatusBar();
99 }
100
101 static void UpdateMenuItems(HMENU hMenu) {
102     HWND hwndTV = g_pChildWnd->hTreeWnd;
103     BOOL bIsKeySelected = FALSE;
104     HKEY hRootKey = NULL;
105     LPCTSTR keyName;
106     keyName = GetItemPath(hwndTV, TreeView_GetSelection(hwndTV), &hRootKey);
107     if (keyName && *keyName) { /* can't modify root keys */
108         bIsKeySelected = TRUE;
109     }
110     EnableMenuItem(hMenu, ID_EDIT_FIND, MF_ENABLED | MF_BYCOMMAND);
111     EnableMenuItem(hMenu, ID_EDIT_FINDNEXT, MF_ENABLED | MF_BYCOMMAND);
112     EnableMenuItem(hMenu, ID_EDIT_MODIFY, (bIsKeySelected ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
113     EnableMenuItem(hMenu, ID_EDIT_DELETE, (bIsKeySelected ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
114     EnableMenuItem(hMenu, ID_EDIT_RENAME, (bIsKeySelected ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
115     EnableMenuItem(hMenu, ID_FAVORITES_ADDTOFAVORITES, (hRootKey ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
116     EnableMenuItem(hMenu, ID_FAVORITES_REMOVEFAVORITE, 
117         (GetMenuItemCount(hMenu)>2 ? MF_ENABLED : MF_GRAYED) | MF_BYCOMMAND);
118 }
119
120 static void OnInitMenuPopup(HWND hWnd, HMENU hMenu, short wItem)
121 {
122     if (wItem == 3) {
123         HKEY hKey;
124         while(GetMenuItemCount(hMenu)>2)
125             DeleteMenu(hMenu, 2, MF_BYPOSITION);
126         if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
127             0, KEY_READ, &hKey) == ERROR_SUCCESS) {
128             TCHAR namebuf[KEY_MAX_LEN];
129             BYTE valuebuf[4096];
130             int i = 0;
131             BOOL sep = FALSE;
132             DWORD ksize, vsize, type;
133             LONG error;
134             do {
135                 ksize = KEY_MAX_LEN;
136                 vsize = sizeof(valuebuf);
137                 error = RegEnumValue(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
138                 if (error != ERROR_SUCCESS)
139                     break;
140                 if (type == REG_SZ) {
141                     if (!sep) {
142                         AppendMenu(hMenu, MF_SEPARATOR, -1, NULL);
143                         sep = TRUE;
144                     }
145                     AppendMenu(hMenu, MF_STRING, ID_FAVORITE_FIRST+i, namebuf);
146                 }
147                 i++;
148             } while(error == ERROR_SUCCESS);
149             RegCloseKey(hKey);
150         }
151     }
152     UpdateMenuItems(hMenu);
153 }
154
155 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
156 {
157     TCHAR str[100];
158
159     _tcscpy(str, _T(""));
160     if (nFlags & MF_POPUP) {
161         if (hSysMenu != GetMenu(hWnd)) {
162             if (nItemID == 2) nItemID = 5;
163         }
164     }
165     if (LoadString(hInst, nItemID, str, 100)) {
166         /* load appropriate string*/
167         LPTSTR lpsz = str;
168         /* first newline terminates actual string*/
169         lpsz = _tcschr(lpsz, '\n');
170         if (lpsz != NULL)
171             *lpsz = '\0';
172     }
173     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
174 }
175
176 void SetupStatusBar(HWND hWnd, BOOL bResize)
177 {
178     RECT  rc;
179     int nParts;
180     GetClientRect(hWnd, &rc);
181     nParts = rc.right;
182     /*    nParts = -1;*/
183     if (bResize)
184         SendMessage(hStatusBar, WM_SIZE, 0, 0);
185     SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
186     UpdateStatusBar();
187 }
188
189 void UpdateStatusBar(void)
190 {
191     LPTSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, TRUE);
192     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)fullPath);
193     HeapFree(GetProcessHeap(), 0, fullPath);
194 }
195
196 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
197 {
198     BOOL vis = IsWindowVisible(hchild);
199     HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
200
201     CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
202     ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
203     resize_frame_client(hWnd);
204 }
205
206 static BOOL CheckCommDlgError(HWND hWnd)
207 {
208     DWORD dwErrorCode = CommDlgExtendedError();
209     switch (dwErrorCode) {
210     case CDERR_DIALOGFAILURE:
211         break;
212     case CDERR_FINDRESFAILURE:
213         break;
214     case CDERR_NOHINSTANCE:
215         break;
216     case CDERR_INITIALIZATION:
217         break;
218     case CDERR_NOHOOK:
219         break;
220     case CDERR_LOCKRESFAILURE:
221         break;
222     case CDERR_NOTEMPLATE:
223         break;
224     case CDERR_LOADRESFAILURE:
225         break;
226     case CDERR_STRUCTSIZE:
227         break;
228     case CDERR_LOADSTRFAILURE:
229         break;
230     case FNERR_BUFFERTOOSMALL:
231         break;
232     case CDERR_MEMALLOCFAILURE:
233         break;
234     case FNERR_INVALIDFILENAME:
235         break;
236     case CDERR_MEMLOCKFAILURE:
237         break;
238     case FNERR_SUBCLASSFAILURE:
239         break;
240     default:
241         break;
242     }
243     return TRUE;
244 }
245
246 static void ExportRegistryFile_StoreSelection(HWND hdlg, OPENFILENAME *pOpenFileName)
247 {
248     if (IsDlgButtonChecked(hdlg, IDC_EXPORT_SELECTED))
249     {
250         INT len = SendDlgItemMessage(hdlg, IDC_EXPORT_PATH, WM_GETTEXTLENGTH, 0, 0);
251         pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(TCHAR));
252         SendDlgItemMessage(hdlg, IDC_EXPORT_PATH, WM_GETTEXT, len+1, pOpenFileName->lCustData);
253     }
254     else
255         pOpenFileName->lCustData = (LPARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR));
256 }
257
258 static UINT CALLBACK ExportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
259 {
260     static OPENFILENAME* pOpenFileName;
261     OFNOTIFY *pOfNotify;
262     LPTSTR path;
263
264     switch (uiMsg) {
265     case WM_INITDIALOG:
266         pOpenFileName = (OPENFILENAME*)lParam;
267         break;
268     case WM_COMMAND:
269         if (LOWORD(wParam) == IDC_EXPORT_PATH && HIWORD(wParam) == EN_UPDATE)
270             CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_SELECTED);
271         break;
272     case WM_NOTIFY:
273         pOfNotify = (OFNOTIFY*)lParam;
274         switch (pOfNotify->hdr.code)
275         {
276             case CDN_INITDONE:
277                 path = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
278                 SendDlgItemMessage(hdlg, IDC_EXPORT_PATH, WM_SETTEXT, 0, (LPARAM)path);
279                 HeapFree(GetProcessHeap(), 0, path);
280                 CheckRadioButton(hdlg, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, IDC_EXPORT_ALL);
281                 break;
282             case CDN_FILEOK:
283                 ExportRegistryFile_StoreSelection(hdlg, pOpenFileName);
284                 break;
285         }
286         break;
287     default:
288         break;
289     }
290     return 0L;
291 }
292
293
294 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME *pofn)
295 {
296     memset(pofn, 0, sizeof(OPENFILENAME));
297     pofn->lStructSize = sizeof(OPENFILENAME);
298     pofn->hwndOwner = hWnd;
299     pofn->hInstance = hInst;
300
301     if (FilterBuffer[0] == 0)
302         LoadString(hInst, IDS_FILEDIALOG_FILTER, FilterBuffer, _MAX_PATH);
303     pofn->lpstrFilter = FilterBuffer;
304     pofn->nFilterIndex = 1;
305     pofn->lpstrFile = FileNameBuffer;
306     pofn->nMaxFile = _MAX_PATH;
307     pofn->lpstrFileTitle = FileTitleBuffer;
308     pofn->nMaxFileTitle = _MAX_PATH;
309     pofn->Flags = OFN_HIDEREADONLY;
310     /* some other fields may be set by the caller */
311     return TRUE;
312 }
313
314 static BOOL ImportRegistryFile(HWND hWnd)
315 {
316     OPENFILENAME ofn;
317     TCHAR title[128];
318
319     InitOpenFileName(hWnd, &ofn);
320     LoadString(hInst, IDS_FILEDIALOG_IMPORT_TITLE, title, COUNT_OF(title));
321     ofn.lpstrTitle = title;
322     if (GetOpenFileName(&ofn)) {
323         if (!import_registry_file(ofn.lpstrFile)) {
324             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
325             return FALSE;
326         }
327     } else {
328         CheckCommDlgError(hWnd);
329     }
330     RefreshTreeView(g_pChildWnd->hTreeWnd);
331     return TRUE;
332 }
333
334
335 static BOOL ExportRegistryFile(HWND hWnd)
336 {
337     OPENFILENAME ofn;
338     TCHAR ExportKeyPath[_MAX_PATH];
339     TCHAR title[128];
340
341     ExportKeyPath[0] = _T('\0');
342     InitOpenFileName(hWnd, &ofn);
343     LoadString(hInst, IDS_FILEDIALOG_EXPORT_TITLE, title, COUNT_OF(title));
344     ofn.lpstrTitle = title;
345     ofn.lCustData = 0; 
346     ofn.Flags = OFN_ENABLETEMPLATE | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
347     ofn.lpfnHook = ExportRegistryFile_OFNHookProc;
348     ofn.lpTemplateName = MAKEINTRESOURCE(IDD_EXPORT_TEMPLATE);
349     if (GetSaveFileName(&ofn)) {
350         BOOL result;
351         result = export_registry_key(ofn.lpstrFile, (LPTSTR)ofn.lCustData);
352         if (!result) {
353             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
354             return FALSE;
355         }
356     } else {
357         CheckCommDlgError(hWnd);
358     }
359     return TRUE;
360 }
361
362 static BOOL PrintRegistryHive(HWND hWnd, LPCTSTR path)
363 {
364 #if 1
365     PRINTDLG pd;
366
367     ZeroMemory(&pd, sizeof(PRINTDLG));
368     pd.lStructSize = sizeof(PRINTDLG);
369     pd.hwndOwner   = hWnd;
370     pd.hDevMode    = NULL;     /* Don't forget to free or store hDevMode*/
371     pd.hDevNames   = NULL;     /* Don't forget to free or store hDevNames*/
372     pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
373     pd.nCopies     = 1;
374     pd.nFromPage   = 0xFFFF;
375     pd.nToPage     = 0xFFFF;
376     pd.nMinPage    = 1;
377     pd.nMaxPage    = 0xFFFF;
378     if (PrintDlg(&pd)) {
379         /* GDI calls to render output. */
380         DeleteDC(pd.hDC); /* Delete DC when done.*/
381     }
382 #else
383     HRESULT hResult;
384     PRINTDLGEX pd;
385
386     hResult = PrintDlgEx(&pd);
387     if (hResult == S_OK) {
388         switch (pd.dwResultAction) {
389         case PD_RESULT_APPLY:
390             /*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. */
391             break;
392         case PD_RESULT_CANCEL:
393             /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
394             break;
395         case PD_RESULT_PRINT:
396             /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
397             break;
398         default:
399             break;
400         }
401     } else {
402         switch (hResult) {
403         case E_OUTOFMEMORY:
404             /*Insufficient memory. */
405             break;
406         case E_INVALIDARG:
407             /* One or more arguments are invalid. */
408             break;
409         case E_POINTER:
410             /*Invalid pointer. */
411             break;
412         case E_HANDLE:
413             /*Invalid handle. */
414             break;
415         case E_FAIL:
416             /*Unspecified error. */
417             break;
418         default:
419             break;
420         }
421         return FALSE;
422     }
423 #endif
424     return TRUE;
425 }
426
427 static BOOL CopyKeyName(HWND hWnd, LPCTSTR keyName)
428 {
429     BOOL result;
430
431     result = OpenClipboard(hWnd);
432     if (result) {
433         result = EmptyClipboard();
434         if (result) {
435             int len = (_tcslen(keyName)+1)*sizeof(TCHAR);
436             HANDLE hClipData = GlobalAlloc(GHND, len);
437             LPVOID pLoc = GlobalLock(hClipData);
438             _tcscpy(pLoc, keyName);
439             GlobalUnlock(hClipData);
440             hClipData = SetClipboardData(CF_TEXT, hClipData);
441
442         } else {
443             /* error emptying clipboard*/
444             /* DWORD dwError = GetLastError(); */
445             ;
446         }
447         if (!CloseClipboard()) {
448             /* error closing clipboard*/
449             /* DWORD dwError = GetLastError(); */
450             ;
451         }
452     } else {
453         /* error opening clipboard*/
454         /* DWORD dwError = GetLastError(); */
455         ;
456     }
457     return result;
458 }
459
460 static INT_PTR CALLBACK find_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
461 {
462     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
463             
464     switch(uMsg) {
465         case WM_INITDIALOG:
466             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
467             CheckDlgButton(hwndDlg, IDC_FIND_KEYS, searchMask&SEARCH_KEYS ? BST_CHECKED : BST_UNCHECKED);
468             CheckDlgButton(hwndDlg, IDC_FIND_VALUES, searchMask&SEARCH_VALUES ? BST_CHECKED : BST_UNCHECKED);
469             CheckDlgButton(hwndDlg, IDC_FIND_CONTENT, searchMask&SEARCH_CONTENT ? BST_CHECKED : BST_UNCHECKED);
470             CheckDlgButton(hwndDlg, IDC_FIND_WHOLE, searchMask&SEARCH_WHOLE ? BST_CHECKED : BST_UNCHECKED);
471             SendMessage(hwndValue, EM_SETLIMITTEXT, 127, 0);
472             SetWindowText(hwndValue, searchString);
473             return TRUE;
474         case WM_COMMAND:
475             switch(LOWORD(wParam)) {
476             case IDC_VALUE_NAME:
477                 if (HIWORD(wParam) == EN_UPDATE) {
478                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
479                     return TRUE;
480                 }
481                 break;
482             case IDOK:
483                 if (GetWindowTextLength(hwndValue)>0) {
484                     int mask = 0;
485                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_KEYS)) mask |= SEARCH_KEYS;
486                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_VALUES)) mask |= SEARCH_VALUES;
487                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_CONTENT)) mask |= SEARCH_CONTENT;
488                     if (IsDlgButtonChecked(hwndDlg, IDC_FIND_WHOLE)) mask |= SEARCH_WHOLE;
489                     searchMask = mask;
490                     GetWindowText(hwndValue, searchString, 128);
491                     EndDialog(hwndDlg, IDOK);
492                 }
493                 return TRUE;
494             case IDCANCEL:
495                 EndDialog(hwndDlg, IDCANCEL);
496                 return TRUE;
497             }
498             break;
499     }
500     return FALSE;
501 }
502                     
503 static INT_PTR CALLBACK addtofavorites_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
504 {
505     HWND hwndValue = GetDlgItem(hwndDlg, IDC_VALUE_NAME);
506             
507     switch(uMsg) {
508         case WM_INITDIALOG:
509             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
510             SendMessage(hwndValue, EM_SETLIMITTEXT, 127, 0);
511             return TRUE;
512         case WM_COMMAND:
513             switch(LOWORD(wParam)) {
514             case IDC_VALUE_NAME:
515                 if (HIWORD(wParam) == EN_UPDATE) {
516                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  GetWindowTextLength(hwndValue)>0);
517                     return TRUE;
518                 }
519                 break;
520             case IDOK:
521                 if (GetWindowTextLength(hwndValue)>0) {
522                     GetWindowText(hwndValue, favoriteName, 128);
523                     EndDialog(hwndDlg, IDOK);
524                 }
525                 return TRUE;
526             case IDCANCEL:
527                 EndDialog(hwndDlg, IDCANCEL);
528                 return TRUE;
529             }
530             break;
531     }
532     return FALSE;
533 }
534                     
535 static INT_PTR CALLBACK removefavorite_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
536 {
537     HWND hwndList = GetDlgItem(hwndDlg, IDC_NAME_LIST);
538             
539     switch(uMsg) {
540         case WM_INITDIALOG: {
541             HKEY hKey;
542             int i = 0;
543             EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
544             if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
545                 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
546                 TCHAR namebuf[KEY_MAX_LEN];
547                 BYTE valuebuf[4096];
548                 DWORD ksize, vsize, type;
549                 LONG error;
550                 do {
551                     ksize = KEY_MAX_LEN;
552                     vsize = sizeof(valuebuf);
553                     error = RegEnumValue(hKey, i, namebuf, &ksize, NULL, &type, valuebuf, &vsize);
554                     if (error != ERROR_SUCCESS)
555                         break;
556                     if (type == REG_SZ) {
557                         SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)namebuf);
558                     }
559                     i++;
560                 } while(error == ERROR_SUCCESS);
561                 RegCloseKey(hKey);
562             }
563             else
564                 return FALSE;
565             EnableWindow(GetDlgItem(hwndDlg, IDOK), i != 0);
566             SendMessage(hwndList, LB_SETCURSEL, 0, 0);
567             return TRUE;
568         }
569         case WM_COMMAND:
570             switch(LOWORD(wParam)) {
571             case IDC_NAME_LIST:
572                 if (HIWORD(wParam) == LBN_SELCHANGE) {
573                     EnableWindow(GetDlgItem(hwndDlg, IDOK),  lParam != -1);
574                     return TRUE;
575                 }
576                 break;
577             case IDOK: {
578                 int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
579                 int len = SendMessage(hwndList, LB_GETTEXTLEN, pos, 0);
580                 if (len>0) {
581                     LPTSTR lpName = HeapAlloc(GetProcessHeap(), 0, sizeof(TCHAR)*(len+1));
582                     SendMessage(hwndList, LB_GETTEXT, pos, (LPARAM)lpName);
583                     if (len>127)
584                         lpName[127] = '\0';
585                     _tcscpy(favoriteName, lpName);
586                     EndDialog(hwndDlg, IDOK);
587                     HeapFree(GetProcessHeap(), 0, lpName);
588                 }
589                 return TRUE;
590             }
591             case IDCANCEL:
592                 EndDialog(hwndDlg, IDCANCEL);
593                 return TRUE;
594             }
595             break;
596     }
597     return FALSE;
598 }
599                     
600 /*******************************************************************************
601  *
602  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
603  *
604  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
605  *
606  */
607 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
608 {
609     HKEY hKeyRoot = 0;
610     LPCTSTR keyPath;
611     LPCTSTR valueName;
612     TCHAR newKey[MAX_NEW_KEY_LEN];
613     DWORD valueType;
614
615     keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
616     valueName = GetValueName(g_pChildWnd->hListWnd);
617
618     if (LOWORD(wParam) >= ID_FAVORITE_FIRST && LOWORD(wParam) <= ID_FAVORITE_LAST) {
619         HKEY hKey;
620         if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
621             0, KEY_READ, &hKey) == ERROR_SUCCESS) {
622             TCHAR namebuf[KEY_MAX_LEN];
623             BYTE valuebuf[4096];
624             DWORD ksize = KEY_MAX_LEN, vsize = sizeof(valuebuf), type = 0;
625             if (RegEnumValue(hKey, LOWORD(wParam) - ID_FAVORITE_FIRST, namebuf, &ksize, NULL, 
626                 &type, valuebuf, &vsize) == ERROR_SUCCESS) {
627                 SendMessage( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET,
628                              (LPARAM) FindPathInTree(g_pChildWnd->hTreeWnd, (TCHAR *)valuebuf) );
629             }
630             RegCloseKey(hKey);
631         }
632         return TRUE;
633     }
634     switch (LOWORD(wParam)) {
635     case ID_REGISTRY_IMPORTREGISTRYFILE:
636         ImportRegistryFile(hWnd);
637         break;
638     case ID_REGISTRY_EXPORTREGISTRYFILE:
639         ExportRegistryFile(hWnd);
640         break;
641     case ID_REGISTRY_CONNECTNETWORKREGISTRY:
642         break;
643     case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
644         break;
645     case ID_REGISTRY_PRINT:
646         PrintRegistryHive(hWnd, _T(""));
647         break;
648     case ID_EDIT_DELETE:
649         if (GetFocus() == g_pChildWnd->hTreeWnd) {
650             if (keyPath == 0 || *keyPath == 0) {
651                 MessageBeep(MB_ICONHAND); 
652             } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
653                 DeleteNode(g_pChildWnd->hTreeWnd, 0);
654             }
655         } else if (GetFocus() == g_pChildWnd->hListWnd) {
656             if (DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
657                 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
658         }
659         break;
660     case ID_EDIT_MODIFY:
661         if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
662             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
663         break;
664     case ID_EDIT_FIND:
665     case ID_EDIT_FINDNEXT:
666     {
667         HTREEITEM hItem;
668         if (LOWORD(wParam) == ID_EDIT_FIND &&
669             DialogBox(0, MAKEINTRESOURCE(IDD_FIND), hWnd, find_dlgproc) != IDOK)
670             break;
671         if (!*searchString)
672             break;
673         hItem = TreeView_GetSelection(g_pChildWnd->hTreeWnd);
674         if (hItem) {
675             int row = ListView_GetNextItem(g_pChildWnd->hListWnd, -1, LVNI_FOCUSED);
676             HCURSOR hcursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
677             hItem = FindNext(g_pChildWnd->hTreeWnd, hItem, searchString, searchMask, &row);
678             SetCursor(hcursorOld);
679             if (hItem) {
680                 SendMessage( g_pChildWnd->hTreeWnd, TVM_SELECTITEM, TVGN_CARET, (LPARAM) hItem );
681                 InvalidateRect(g_pChildWnd->hTreeWnd, NULL, TRUE);
682                 UpdateWindow(g_pChildWnd->hTreeWnd);
683                 if (row != -1) {
684                     ListView_SetItemState(g_pChildWnd->hListWnd, -1, 0, LVIS_FOCUSED|LVIS_SELECTED);
685                     ListView_SetItemState(g_pChildWnd->hListWnd, row, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
686                     SetFocus(g_pChildWnd->hListWnd);
687                 } else {
688                     SetFocus(g_pChildWnd->hTreeWnd);
689                 }
690             } else {
691                 error(hWnd, IDS_NOTFOUND, searchString);
692             }
693         }
694         break;
695     }
696     case ID_EDIT_COPYKEYNAME:
697     {
698         LPTSTR fullPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
699         if (fullPath) {
700             CopyKeyName(hWnd, fullPath);
701             HeapFree(GetProcessHeap(), 0, fullPath);
702         }
703         break;
704     }
705     case ID_EDIT_NEW_KEY:
706         if (CreateKey(hWnd, hKeyRoot, keyPath, newKey)) {
707             if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKey))
708                 StartKeyRename(g_pChildWnd->hTreeWnd);
709         }
710         break;
711     case ID_EDIT_NEW_STRINGVALUE:
712         valueType = REG_SZ;
713         goto create_value;
714     case ID_EDIT_NEW_MULTI_STRINGVALUE:
715         valueType = REG_MULTI_SZ;
716         goto create_value;
717     case ID_EDIT_NEW_BINARYVALUE:
718         valueType = REG_BINARY;
719         goto create_value;
720     case ID_EDIT_NEW_DWORDVALUE:
721         valueType = REG_DWORD;
722         /* fall through */
723     create_value:
724         if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
725             RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
726             StartValueRename(g_pChildWnd->hListWnd);
727             /* FIXME: start rename */
728         }
729         break;
730     case ID_EDIT_RENAME:
731         if (keyPath == 0 || *keyPath == 0) {
732             MessageBeep(MB_ICONHAND); 
733         } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
734             StartKeyRename(g_pChildWnd->hTreeWnd);
735         } else if (GetFocus() == g_pChildWnd->hListWnd) {
736             StartValueRename(g_pChildWnd->hListWnd);
737         }
738         break;
739     case ID_REGISTRY_PRINTERSETUP:
740         /*PRINTDLG pd;*/
741         /*PrintDlg(&pd);*/
742         /*PAGESETUPDLG psd;*/
743         /*PageSetupDlg(&psd);*/
744         break;
745     case ID_REGISTRY_OPENLOCAL:
746         break;
747     case ID_REGISTRY_EXIT:
748         DestroyWindow(hWnd);
749         break;
750     case ID_FAVORITES_ADDTOFAVORITES:
751     {
752         HKEY hKey;
753         LPTSTR lpKeyPath = GetItemFullPath(g_pChildWnd->hTreeWnd, NULL, FALSE);
754         if (lpKeyPath) {
755             if (DialogBox(0, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd, addtofavorites_dlgproc) == IDOK) {
756                 if (RegCreateKeyEx(HKEY_CURRENT_USER, favoritesKey, 
757                     0, NULL, 0, 
758                     KEY_READ|KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
759                     RegSetValueEx(hKey, favoriteName, 0, REG_SZ, (BYTE *)lpKeyPath, (_tcslen(lpKeyPath)+1)*sizeof(TCHAR));
760                     RegCloseKey(hKey);
761                 }
762             }
763             HeapFree(GetProcessHeap(), 0, lpKeyPath);
764         }
765         break;
766     }
767     case ID_FAVORITES_REMOVEFAVORITE:
768     {
769         if (DialogBox(0, MAKEINTRESOURCE(IDD_DELFAVORITE), hWnd, removefavorite_dlgproc) == IDOK) {
770             HKEY hKey;
771             if (RegOpenKeyEx(HKEY_CURRENT_USER, favoritesKey, 
772                 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) {
773                 RegDeleteValue(hKey, favoriteName); 
774                 RegCloseKey(hKey);
775             }
776         }
777         break;
778     }
779     case ID_VIEW_REFRESH:
780         RefreshTreeView(g_pChildWnd->hTreeWnd);
781         RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
782         break;
783    /*case ID_OPTIONS_TOOLBAR:*/
784    /*   toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
785    /*    break;*/
786     case ID_VIEW_STATUSBAR:
787         toggle_child(hWnd, LOWORD(wParam), hStatusBar);
788         break;
789     case ID_HELP_HELPTOPICS:
790         WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
791         break;
792     case ID_HELP_ABOUT:
793         ShowAboutBox(hWnd);
794         break;
795     case ID_VIEW_SPLIT: {
796         RECT rt;
797         POINT pt, pts;
798         GetClientRect(g_pChildWnd->hWnd, &rt);
799         pt.x = rt.left + g_pChildWnd->nSplitPos;
800         pt.y = (rt.bottom / 2);
801         pts = pt;
802         if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
803             SetCursorPos(pts.x, pts.y);
804             SetCursor(LoadCursor(0, IDC_SIZEWE));
805             SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
806         }
807         return TRUE;
808     }
809     default:
810         return FALSE;
811     }
812
813     return TRUE;
814 }
815
816 /********************************************************************************
817  *
818  *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
819  *
820  *  PURPOSE:  Processes messages for the main frame window.
821  *
822  *  WM_COMMAND  - process the application menu
823  *  WM_DESTROY  - post a quit message and return
824  *
825  */
826
827 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
828 {
829     switch (message) {
830     case WM_CREATE:
831         CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
832                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
833                        hWnd, NULL, hInst, 0);
834         break;
835     case WM_COMMAND:
836         if (!_CmdWndProc(hWnd, message, wParam, lParam))
837             return DefWindowProc(hWnd, message, wParam, lParam);
838         break;
839     case WM_ACTIVATE:
840         if (LOWORD(hWnd)) 
841             SetFocus(g_pChildWnd->hWnd);
842         break;
843     case WM_SIZE:
844         resize_frame_client(hWnd);
845         break;
846     case WM_TIMER:
847         break;
848     case WM_ENTERMENULOOP:
849         OnEnterMenuLoop(hWnd);
850         break;
851     case WM_EXITMENULOOP:
852         OnExitMenuLoop(hWnd);
853         break;
854     case WM_INITMENUPOPUP:
855         if (!HIWORD(lParam))
856             OnInitMenuPopup(hWnd, (HMENU)wParam, LOWORD(lParam));
857         break;
858     case WM_MENUSELECT:
859         OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
860         break;
861     case WM_DESTROY:
862         WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
863         PostQuitMessage(0);
864     default:
865         return DefWindowProc(hWnd, message, wParam, lParam);
866     }
867     return 0;
868 }