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