update for HEAD-2003091401
[reactos.git] / subsys / system / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
40
41 static HWND hChildWnd;
42
43 /*******************************************************************************
44  * Local module support methods
45  */
46
47 static void resize_frame_rect(HWND hWnd, PRECT prect)
48 {
49         RECT rt;
50 /*
51         if (IsWindowVisible(hToolBar)) {
52                 SendMessage(hToolBar, WM_SIZE, 0, 0);
53                 GetClientRect(hToolBar, &rt);
54                 prect->top = rt.bottom+3;
55                 prect->bottom -= rt.bottom+3;
56         }
57  */
58         if (IsWindowVisible(hStatusBar)) {
59                 SetupStatusBar(hWnd, TRUE);
60                 GetClientRect(hStatusBar, &rt);
61                 prect->bottom -= rt.bottom;
62         }
63     MoveWindow(hChildWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
64 }
65
66 void resize_frame_client(HWND hWnd)
67 {
68         RECT rect;
69
70         GetClientRect(hWnd, &rect);
71         resize_frame_rect(hWnd, &rect);
72 }
73
74 /********************************************************************************/
75
76 static void OnEnterMenuLoop(HWND hWnd)
77 {
78     int nParts;
79
80     /* Update the status bar pane sizes */
81     nParts = -1;
82     SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts);
83     bInMenuLoop = TRUE;
84     SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
85 }
86
87 static void OnExitMenuLoop(HWND hWnd)
88 {
89     bInMenuLoop = FALSE;
90     /* Update the status bar pane sizes*/
91         SetupStatusBar(hWnd, TRUE);
92         UpdateStatusBar();
93 }
94
95 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
96 {
97     TCHAR str[100];
98
99     _tcscpy(str, _T(""));
100     if (nFlags & MF_POPUP) {
101         if (hSysMenu != GetMenu(hWnd)) {
102             if (nItemID == 2) nItemID = 5;
103         }
104     }
105     if (LoadString(hInst, nItemID, str, 100)) {
106         /* load appropriate string*/
107         LPTSTR lpsz = str;
108         /* first newline terminates actual string*/
109         lpsz = _tcschr(lpsz, '\n');
110         if (lpsz != NULL)
111             *lpsz = '\0';
112     }
113     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
114 }
115
116 void SetupStatusBar(HWND hWnd, BOOL bResize)
117 {
118     RECT  rc;
119     int nParts;
120     GetClientRect(hWnd, &rc);
121     nParts = rc.right;
122 /*    nParts = -1;*/
123         if (bResize)
124                 SendMessage(hStatusBar, WM_SIZE, 0, 0);
125         SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
126 }
127
128 void UpdateStatusBar(void)
129 {
130     TCHAR text[260];
131         DWORD size;
132
133         size = sizeof(text)/sizeof(TCHAR);
134         GetComputerName(text, &size);
135     SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
136 }
137
138 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
139 {
140         BOOL vis = IsWindowVisible(hchild);
141         HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
142
143         CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
144         ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
145         resize_frame_client(hWnd);
146 }
147
148 static BOOL CheckCommDlgError(HWND hWnd)
149 {
150         DWORD dwErrorCode = CommDlgExtendedError();
151         switch (dwErrorCode) {
152         case CDERR_DIALOGFAILURE:
153             break;
154         case CDERR_FINDRESFAILURE:
155             break;
156         case CDERR_NOHINSTANCE:
157             break;
158         case CDERR_INITIALIZATION:
159             break;
160         case CDERR_NOHOOK:
161             break;
162         case CDERR_LOCKRESFAILURE:
163             break;
164         case CDERR_NOTEMPLATE:
165             break;
166         case CDERR_LOADRESFAILURE:
167             break;
168         case CDERR_STRUCTSIZE:
169             break;
170         case CDERR_LOADSTRFAILURE:
171             break;
172         case FNERR_BUFFERTOOSMALL:
173             break;
174         case CDERR_MEMALLOCFAILURE:
175             break;
176         case FNERR_INVALIDFILENAME:
177             break;
178         case CDERR_MEMLOCKFAILURE:
179             break;
180         case FNERR_SUBCLASSFAILURE:
181             break;
182         default:
183             break;
184         }
185         return TRUE;
186 }
187
188 UINT_PTR CALLBACK ImportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
189 {
190     OPENFILENAME* pOpenFileName;
191     OFNOTIFY* pOfNotify;
192
193     switch (uiMsg) {
194     case WM_INITDIALOG:
195         pOpenFileName = (OPENFILENAME*)lParam;
196         break;
197     case WM_NOTIFY:
198         pOfNotify = (OFNOTIFY*)lParam;
199         if (pOfNotify->hdr.code == CDN_INITDONE) {
200         }
201         break;
202     default:
203         break;
204     }
205     return 0L;
206 }
207
208 #define MAX_CUSTOM_FILTER_SIZE 50
209 TCHAR CustomFilterBuffer[MAX_CUSTOM_FILTER_SIZE];
210 TCHAR FileNameBuffer[_MAX_PATH];
211 TCHAR FileTitleBuffer[_MAX_PATH];
212
213 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
214 {
215     memset(pofn, 0, sizeof(OPENFILENAME));
216     pofn->lStructSize = sizeof(OPENFILENAME);
217     pofn->hwndOwner = hWnd;
218     pofn->hInstance = hInst;
219
220     pofn->lpstrFilter = _T("Registration Files\0*.reg\0Win9x/NT4 Registration Files (REGEDIT4)\0*.reg\0All Files (*.*)\0*.*\0\0");
221     pofn->lpstrCustomFilter = CustomFilterBuffer;
222     pofn->nMaxCustFilter = MAX_CUSTOM_FILTER_SIZE;
223     pofn->nFilterIndex = 0;
224     pofn->lpstrFile = FileNameBuffer;
225     pofn->nMaxFile = _MAX_PATH;
226     pofn->lpstrFileTitle = FileTitleBuffer;
227     pofn->nMaxFileTitle = _MAX_PATH;
228 /*    pofn->lpstrInitialDir = _T("");*/
229 /*    pofn->lpstrTitle = _T("Import Registry File");*/
230 /*    pofn->Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER + OFN_ENABLESIZING;*/
231     pofn->Flags = OFN_HIDEREADONLY;
232 /*    pofn->nFileOffset = ;*/
233 /*    pofn->nFileExtension = ;*/
234 /*    pofn->lpstrDefExt = _T("");*/
235 /*    pofn->lCustData = ;*/
236 /*    pofn->lpfnHook = ImportRegistryFile_OFNHookProc;*/
237 /*    pofn->lpTemplateName = _T("ID_DLG_IMPORT_REGFILE");*/
238 /*    pofn->lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);*/
239 /*    pofn->FlagsEx = ;*/
240         return TRUE;
241 }
242
243 static BOOL ImportRegistryFile(HWND hWnd)
244 {
245     OPENFILENAME ofn;
246
247     InitOpenFileName(hWnd, &ofn);
248     ofn.lpstrTitle = _T("Import Registry File");
249 /*    ofn.lCustData = ;*/
250     if (GetOpenFileName(&ofn)) {
251         if (!import_registry_file(ofn.lpstrFile)) {
252             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
253             return FALSE;
254         }
255 #if 0
256         get_file_name(&s, filename, MAX_PATH);
257         if (!filename[0]) {
258             printf("No file name is specified\n%s", usage);
259             return FALSE;
260             /*exit(1);*/
261         }
262         while (filename[0]) {
263             if (!import_registry_file(filename)) {
264                 perror("");
265                 printf("Can't open file \"%s\"\n", filename);
266                 return FALSE;
267                 /*exit(1);*/
268             }
269             get_file_name(&s, filename, MAX_PATH);
270         }
271 #endif
272     } else {
273         CheckCommDlgError(hWnd);
274     }
275         return TRUE;
276 }
277
278
279 static BOOL ExportRegistryFile(HWND hWnd)
280 {
281     OPENFILENAME ofn;
282     TCHAR ExportKeyPath[_MAX_PATH];
283
284     ExportKeyPath[0] = _T('\0');
285     InitOpenFileName(hWnd, &ofn);
286     ofn.lpstrTitle = _T("Export Registry File");
287 /*    ofn.lCustData = ;*/
288     ofn.Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER;
289     ofn.lpfnHook = ImportRegistryFile_OFNHookProc;
290     ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);
291     if (GetSaveFileName(&ofn)) {
292         BOOL result;
293         result = export_registry_key(ofn.lpstrFile, ExportKeyPath);
294         /*result = export_registry_key(ofn.lpstrFile, NULL);*/
295         /*if (!export_registry_key(ofn.lpstrFile, NULL)) {*/
296         if (!result) {
297             /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
298             return FALSE;
299         }
300 #if 0
301         TCHAR filename[MAX_PATH];
302         filename[0] = '\0';
303         get_file_name(&s, filename, MAX_PATH);
304         if (!filename[0]) {
305             printf("No file name is specified\n%s", usage);
306             return FALSE;
307             /*exit(1);*/
308         }
309         if (s[0]) {
310             TCHAR reg_key_name[KEY_MAX_LEN];
311             get_file_name(&s, reg_key_name, KEY_MAX_LEN);
312             export_registry_key(filename, reg_key_name);
313         } else {
314             export_registry_key(filename, NULL);
315         }
316 #endif
317     } else {
318         CheckCommDlgError(hWnd);
319     }
320         return TRUE;
321 }
322
323 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
324 {
325 #if 1
326     PRINTDLG pd;
327
328     ZeroMemory(&pd, sizeof(PRINTDLG));
329     pd.lStructSize = sizeof(PRINTDLG);
330     pd.hwndOwner   = hWnd;
331     pd.hDevMode    = NULL;     /* Don't forget to free or store hDevMode*/
332     pd.hDevNames   = NULL;     /* Don't forget to free or store hDevNames*/
333     pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
334     pd.nCopies     = 1;
335     pd.nFromPage   = 0xFFFF;
336     pd.nToPage     = 0xFFFF;
337     pd.nMinPage    = 1;
338     pd.nMaxPage    = 0xFFFF;
339     if (PrintDlg(&pd) == TRUE) {
340         /* GDI calls to render output. */
341         DeleteDC(pd.hDC); /* Delete DC when done.*/
342     }
343 #else
344     HRESULT hResult;
345     PRINTDLGEX pd;
346
347     hResult = PrintDlgEx(&pd);
348     if (hResult == S_OK) {
349         switch (pd.dwResultAction) {
350         case PD_RESULT_APPLY:
351             /*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. */
352             break;
353         case PD_RESULT_CANCEL:
354             /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
355             break;
356         case PD_RESULT_PRINT:
357             /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
358             break;
359         default:
360             break;
361         }
362     } else {
363         switch (hResult) {
364         case E_OUTOFMEMORY:
365             /*Insufficient memory. */
366             break;
367         case E_INVALIDARG:
368             /* One or more arguments are invalid. */
369             break;
370         case E_POINTER:
371             /*Invalid pointer. */
372             break;
373         case E_HANDLE:
374             /*Invalid handle. */
375             break;
376         case E_FAIL:
377             /*Unspecified error. */
378             break;
379         default:
380             break;
381         }
382         return FALSE;
383     }
384 #endif
385     return TRUE;
386 }
387
388 BOOL CopyKeyName(HWND hWnd, LPTSTR keyName)
389 {
390     BOOL result;
391
392     result = OpenClipboard(hWnd);
393     if (result) {
394         result = EmptyClipboard();
395         if (result) {
396
397             /*HANDLE hClipData;*/
398             /*hClipData = SetClipboardData(UINT uFormat, HANDLE hMem);*/
399
400         } else {
401             /* error emptying clipboard*/
402             /* DWORD dwError = GetLastError(); */
403             ;
404         }
405         if (!CloseClipboard()) {
406             /* error closing clipboard*/
407             /* DWORD dwError = GetLastError(); */
408             ;
409         }
410     } else {
411         /* error opening clipboard*/
412         /* DWORD dwError = GetLastError(); */
413         ;
414     }
415     return result;
416 }
417
418 BOOL RefreshView(HWND hWnd)
419 {
420     /* TODO:*/
421     MessageBeep(-1);
422     MessageBeep(MB_ICONASTERISK);
423     MessageBeep(MB_ICONEXCLAMATION);
424     MessageBeep(MB_ICONHAND);
425     MessageBeep(MB_ICONQUESTION);
426     MessageBeep(MB_OK);
427     return TRUE;
428 }
429
430 /*******************************************************************************
431  *
432  *  FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
433  *
434  *  PURPOSE:  Processes WM_COMMAND messages for the main frame window.
435  *
436  */
437 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
438 {
439         switch (LOWORD(wParam)) {
440     /* Parse the menu selections:*/
441     case ID_REGISTRY_IMPORTREGISTRYFILE:
442         ImportRegistryFile(hWnd);
443         break;
444     case ID_REGISTRY_EXPORTREGISTRYFILE:
445         ExportRegistryFile(hWnd);
446         break;
447     case ID_REGISTRY_CONNECTNETWORKREGISTRY:
448         break;
449     case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
450         break;
451     case ID_REGISTRY_PRINT:
452         PrintRegistryHive(hWnd, _T(""));
453         break;
454     case ID_EDIT_COPYKEYNAME:
455         CopyKeyName(hWnd, _T(""));
456         break;
457     case ID_REGISTRY_PRINTERSETUP:
458         /*PRINTDLG pd;*/
459         /*PrintDlg(&pd);*/
460         /*PAGESETUPDLG psd;*/
461         /*PageSetupDlg(&psd);*/
462         break;
463     case ID_REGISTRY_OPENLOCAL:
464         break;
465     case ID_REGISTRY_EXIT:
466         DestroyWindow(hWnd);
467         break;
468     case ID_VIEW_REFRESH:
469         RefreshView(hWnd);
470         break;
471 /*      case ID_OPTIONS_TOOLBAR:*/
472 /*              toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
473 /*      break;*/
474         case ID_VIEW_STATUSBAR:
475                 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
476         break;
477     case ID_HELP_HELPTOPICS:
478 /*              WinHelp(hWnd, _T("regedit"), HELP_CONTENTS, 0);*/
479                 WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
480         break;
481     case ID_HELP_ABOUT:
482 #ifdef WINSHELLAPI
483 /*        ShellAbout(hWnd, szTitle, _T(""), LoadIcon(hInst, (LPCTSTR)IDI_REGEDIT));*/
484 #else
485         ShowAboutBox(hWnd);
486 #endif
487         break;
488     default:
489         return FALSE;
490     }
491         return TRUE;
492 }
493
494 /********************************************************************************
495  *
496  *  FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
497  *
498  *  PURPOSE:  Processes messages for the main frame window.
499  *
500  *  WM_COMMAND  - process the application menu
501  *  WM_DESTROY  - post a quit message and return
502  *
503  */
504
505 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
506 {
507     static ChildWnd* pChildWnd = NULL;
508
509     switch (message) {
510     case WM_CREATE:
511         {
512         pChildWnd = HeapAlloc(GetProcessHeap(), 0, sizeof(ChildWnd));
513         _tcsncpy(pChildWnd->szPath, _T("My Computer"), MAX_PATH);
514         hChildWnd = CreateWindowEx(0, szChildClass, _T("regedit child window"),
515 /*                    WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE|WS_BORDER,*/
516                     WS_CHILD|WS_VISIBLE | WS_EX_CLIENTEDGE,
517                     CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
518                     hWnd, (HMENU)0, hInst, pChildWnd);
519         }
520         break;
521     case WM_COMMAND:
522         if (!_CmdWndProc(hWnd, message, wParam, lParam)) {
523             return DefWindowProc(hWnd, message, wParam, lParam);
524         }
525         break;
526     case WM_SIZE:
527         resize_frame_client(hWnd);
528         break;
529     case WM_TIMER:
530         break;
531     case WM_ENTERMENULOOP:
532         OnEnterMenuLoop(hWnd);
533         break;
534     case WM_EXITMENULOOP:
535         OnExitMenuLoop(hWnd);
536         break;
537     case WM_MENUSELECT:
538         OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
539         break;
540     case WM_DESTROY:
541         if (pChildWnd) {
542             HeapFree(GetProcessHeap(), 0, pChildWnd);
543             pChildWnd = NULL;
544         }
545         WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
546         PostQuitMessage(0);
547     default:
548         return DefWindowProc(hWnd, message, wParam, lParam);
549    }
550    return 0;
551 }