Use Interlocked* functions in AddRef and Release.
[wine.git] / programs / regedit / framewnd.c
blob9ec5c52bf43d1224f7d52392e07a081bbc59c703
1 /*
2 * Regedit frame window
4 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
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.
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.
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
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
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>
32 #include "main.h"
33 #include "regproc.h"
35 /********************************************************************************
36 * Global and Local Variables:
39 static BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
41 /*******************************************************************************
42 * Local module support methods
45 static void resize_frame_rect(HWND hWnd, PRECT prect)
47 RECT rt;
49 if (IsWindowVisible(hToolBar)) {
50 SendMessage(hToolBar, WM_SIZE, 0, 0);
51 GetClientRect(hToolBar, &rt);
52 prect->top = rt.bottom+3;
53 prect->bottom -= rt.bottom+3;
56 if (IsWindowVisible(hStatusBar)) {
57 SetupStatusBar(hWnd, TRUE);
58 GetClientRect(hStatusBar, &rt);
59 prect->bottom -= rt.bottom;
61 MoveWindow(g_pChildWnd->hWnd, prect->left, prect->top, prect->right, prect->bottom, TRUE);
64 void resize_frame_client(HWND hWnd)
66 RECT rect;
68 GetClientRect(hWnd, &rect);
69 resize_frame_rect(hWnd, &rect);
72 /********************************************************************************/
74 static void OnEnterMenuLoop(HWND hWnd)
76 int nParts;
78 /* Update the status bar pane sizes */
79 nParts = -1;
80 SendMessage(hStatusBar, SB_SETPARTS, 1, (long)&nParts);
81 bInMenuLoop = TRUE;
82 SendMessage(hStatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
85 static void OnExitMenuLoop(HWND hWnd)
87 bInMenuLoop = FALSE;
88 /* Update the status bar pane sizes*/
89 SetupStatusBar(hWnd, TRUE);
90 UpdateStatusBar();
93 static void OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
95 TCHAR str[100];
97 _tcscpy(str, _T(""));
98 if (nFlags & MF_POPUP) {
99 if (hSysMenu != GetMenu(hWnd)) {
100 if (nItemID == 2) nItemID = 5;
103 if (LoadString(hInst, nItemID, str, 100)) {
104 /* load appropriate string*/
105 LPTSTR lpsz = str;
106 /* first newline terminates actual string*/
107 lpsz = _tcschr(lpsz, '\n');
108 if (lpsz != NULL)
109 *lpsz = '\0';
111 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)str);
114 void SetupStatusBar(HWND hWnd, BOOL bResize)
116 RECT rc;
117 int nParts;
118 GetClientRect(hWnd, &rc);
119 nParts = rc.right;
120 /* nParts = -1;*/
121 if (bResize)
122 SendMessage(hStatusBar, WM_SIZE, 0, 0);
123 SendMessage(hStatusBar, SB_SETPARTS, 1, (LPARAM)&nParts);
126 void UpdateStatusBar(void)
128 TCHAR text[260];
129 DWORD size;
131 size = sizeof(text)/sizeof(TCHAR);
132 GetComputerName(text, &size);
133 SendMessage(hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
136 static void toggle_child(HWND hWnd, UINT cmd, HWND hchild)
138 BOOL vis = IsWindowVisible(hchild);
139 HMENU hMenuView = GetSubMenu(hMenuFrame, ID_VIEW_MENU);
141 CheckMenuItem(hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
142 ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
143 resize_frame_client(hWnd);
146 static BOOL CheckCommDlgError(HWND hWnd)
148 DWORD dwErrorCode = CommDlgExtendedError();
149 switch (dwErrorCode) {
150 case CDERR_DIALOGFAILURE:
151 break;
152 case CDERR_FINDRESFAILURE:
153 break;
154 case CDERR_NOHINSTANCE:
155 break;
156 case CDERR_INITIALIZATION:
157 break;
158 case CDERR_NOHOOK:
159 break;
160 case CDERR_LOCKRESFAILURE:
161 break;
162 case CDERR_NOTEMPLATE:
163 break;
164 case CDERR_LOADRESFAILURE:
165 break;
166 case CDERR_STRUCTSIZE:
167 break;
168 case CDERR_LOADSTRFAILURE:
169 break;
170 case FNERR_BUFFERTOOSMALL:
171 break;
172 case CDERR_MEMALLOCFAILURE:
173 break;
174 case FNERR_INVALIDFILENAME:
175 break;
176 case CDERR_MEMLOCKFAILURE:
177 break;
178 case FNERR_SUBCLASSFAILURE:
179 break;
180 default:
181 break;
183 return TRUE;
186 UINT_PTR CALLBACK ImportRegistryFile_OFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
188 OPENFILENAME* pOpenFileName;
189 OFNOTIFY* pOfNotify;
191 switch (uiMsg) {
192 case WM_INITDIALOG:
193 pOpenFileName = (OPENFILENAME*)lParam;
194 break;
195 case WM_NOTIFY:
196 pOfNotify = (OFNOTIFY*)lParam;
197 if (pOfNotify->hdr.code == CDN_INITDONE) {}
198 break;
199 default:
200 break;
202 return 0L;
205 #define MAX_CUSTOM_FILTER_SIZE 50
206 TCHAR CustomFilterBuffer[MAX_CUSTOM_FILTER_SIZE];
207 TCHAR FileNameBuffer[_MAX_PATH];
208 TCHAR FileTitleBuffer[_MAX_PATH];
210 static BOOL InitOpenFileName(HWND hWnd, OPENFILENAME* pofn)
212 memset(pofn, 0, sizeof(OPENFILENAME));
213 pofn->lStructSize = sizeof(OPENFILENAME);
214 pofn->hwndOwner = hWnd;
215 pofn->hInstance = hInst;
217 pofn->lpstrFilter = _T("Registration Files\0*.reg\0Win9x/NT4 Registration Files (REGEDIT4)\0*.reg\0All Files (*.*)\0*.*\0\0");
218 pofn->lpstrCustomFilter = CustomFilterBuffer;
219 pofn->nMaxCustFilter = MAX_CUSTOM_FILTER_SIZE;
220 pofn->nFilterIndex = 0;
221 pofn->lpstrFile = FileNameBuffer;
222 pofn->nMaxFile = _MAX_PATH;
223 pofn->lpstrFileTitle = FileTitleBuffer;
224 pofn->nMaxFileTitle = _MAX_PATH;
225 /* pofn->lpstrInitialDir = _T("");*/
226 /* pofn->lpstrTitle = _T("Import Registry File");*/
227 /* pofn->Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER + OFN_ENABLESIZING;*/
228 pofn->Flags = OFN_HIDEREADONLY;
229 /* pofn->nFileOffset = ;*/
230 /* pofn->nFileExtension = ;*/
231 /* pofn->lpstrDefExt = _T("");*/
232 /* pofn->lCustData = ;*/
233 /* pofn->lpfnHook = ImportRegistryFile_OFNHookProc;*/
234 /* pofn->lpTemplateName = _T("ID_DLG_IMPORT_REGFILE");*/
235 /* pofn->lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);*/
236 /* pofn->FlagsEx = ;*/
237 return TRUE;
240 static BOOL ImportRegistryFile(HWND hWnd)
242 OPENFILENAME ofn;
244 InitOpenFileName(hWnd, &ofn);
245 ofn.lpstrTitle = _T("Import Registry File");
246 /* ofn.lCustData = ;*/
247 if (GetOpenFileName(&ofn)) {
248 if (!import_registry_file(ofn.lpstrFile)) {
249 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
250 return FALSE;
252 #if 0
253 get_file_name(&s, filename, MAX_PATH);
254 if (!filename[0]) {
255 printf("No file name is specified\n%s", usage);
256 return FALSE;
257 /*exit(1);*/
259 while (filename[0]) {
260 if (!import_registry_file(filename)) {
261 perror("");
262 printf("Can't open file \"%s\"\n", filename);
263 return FALSE;
264 /*exit(1);*/
266 get_file_name(&s, filename, MAX_PATH);
268 #endif
270 } else {
271 CheckCommDlgError(hWnd);
273 return TRUE;
277 static BOOL ExportRegistryFile(HWND hWnd)
279 OPENFILENAME ofn;
280 TCHAR ExportKeyPath[_MAX_PATH];
282 ExportKeyPath[0] = _T('\0');
283 InitOpenFileName(hWnd, &ofn);
284 ofn.lpstrTitle = _T("Export Registry File");
285 /* ofn.lCustData = ;*/
286 ofn.Flags = OFN_ENABLETEMPLATE + OFN_EXPLORER;
287 ofn.lpfnHook = ImportRegistryFile_OFNHookProc;
288 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);
289 if (GetSaveFileName(&ofn)) {
290 BOOL result;
291 result = export_registry_key(ofn.lpstrFile, ExportKeyPath);
292 /*result = export_registry_key(ofn.lpstrFile, NULL);*/
293 /*if (!export_registry_key(ofn.lpstrFile, NULL)) {*/
294 if (!result) {
295 /*printf("Can't open file \"%s\"\n", ofn.lpstrFile);*/
296 return FALSE;
298 #if 0
299 TCHAR filename[MAX_PATH];
300 filename[0] = '\0';
301 get_file_name(&s, filename, MAX_PATH);
302 if (!filename[0]) {
303 printf("No file name is specified\n%s", usage);
304 return FALSE;
305 /*exit(1);*/
307 if (s[0]) {
308 TCHAR reg_key_name[KEY_MAX_LEN];
309 get_file_name(&s, reg_key_name, KEY_MAX_LEN);
310 export_registry_key(filename, reg_key_name);
311 } else {
312 export_registry_key(filename, NULL);
314 #endif
316 } else {
317 CheckCommDlgError(hWnd);
319 return TRUE;
322 BOOL PrintRegistryHive(HWND hWnd, LPTSTR path)
324 #if 1
325 PRINTDLG pd;
327 ZeroMemory(&pd, sizeof(PRINTDLG));
328 pd.lStructSize = sizeof(PRINTDLG);
329 pd.hwndOwner = hWnd;
330 pd.hDevMode = NULL; /* Don't forget to free or store hDevMode*/
331 pd.hDevNames = NULL; /* Don't forget to free or store hDevNames*/
332 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
333 pd.nCopies = 1;
334 pd.nFromPage = 0xFFFF;
335 pd.nToPage = 0xFFFF;
336 pd.nMinPage = 1;
337 pd.nMaxPage = 0xFFFF;
338 if (PrintDlg(&pd) == TRUE) {
339 /* GDI calls to render output. */
340 DeleteDC(pd.hDC); /* Delete DC when done.*/
342 #else
343 HRESULT hResult;
344 PRINTDLGEX pd;
346 hResult = PrintDlgEx(&pd);
347 if (hResult == S_OK) {
348 switch (pd.dwResultAction) {
349 case PD_RESULT_APPLY:
350 /*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. */
351 break;
352 case PD_RESULT_CANCEL:
353 /*The user clicked the Cancel button. The information in the PRINTDLGEX structure is unchanged. */
354 break;
355 case PD_RESULT_PRINT:
356 /*The user clicked the Print button. The PRINTDLGEX structure contains the information specified by the user. */
357 break;
358 default:
359 break;
361 } else {
362 switch (hResult) {
363 case E_OUTOFMEMORY:
364 /*Insufficient memory. */
365 break;
366 case E_INVALIDARG:
367 /* One or more arguments are invalid. */
368 break;
369 case E_POINTER:
370 /*Invalid pointer. */
371 break;
372 case E_HANDLE:
373 /*Invalid handle. */
374 break;
375 case E_FAIL:
376 /*Unspecified error. */
377 break;
378 default:
379 break;
381 return FALSE;
383 #endif
384 return TRUE;
387 BOOL CopyKeyName(HWND hWnd, LPTSTR keyName)
389 BOOL result;
391 result = OpenClipboard(hWnd);
392 if (result) {
393 result = EmptyClipboard();
394 if (result) {
396 /*HANDLE hClipData;*/
397 /*hClipData = SetClipboardData(UINT uFormat, HANDLE hMem);*/
399 } else {
400 /* error emptying clipboard*/
401 /* DWORD dwError = GetLastError(); */
404 if (!CloseClipboard()) {
405 /* error closing clipboard*/
406 /* DWORD dwError = GetLastError(); */
409 } else {
410 /* error opening clipboard*/
411 /* DWORD dwError = GetLastError(); */
414 return result;
417 BOOL RefreshView(HWND hWnd)
419 /* TODO:*/
420 MessageBeep(-1);
421 MessageBeep(MB_ICONASTERISK);
422 MessageBeep(MB_ICONEXCLAMATION);
423 MessageBeep(MB_ICONHAND);
424 MessageBeep(MB_ICONQUESTION);
425 MessageBeep(MB_OK);
426 return TRUE;
429 /*******************************************************************************
431 * FUNCTION: _CmdWndProc(HWND, unsigned, WORD, LONG)
433 * PURPOSE: Processes WM_COMMAND messages for the main frame window.
436 static BOOL _CmdWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
438 HKEY hKeyRoot = 0;
439 LPCTSTR keyPath;
440 LPCTSTR valueName;
441 TCHAR newKey[MAX_NEW_KEY_LEN];
442 DWORD valueType;
444 keyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
445 valueName = GetValueName(g_pChildWnd->hListWnd);
447 switch (LOWORD(wParam)) {
448 case ID_REGISTRY_IMPORTREGISTRYFILE:
449 ImportRegistryFile(hWnd);
450 break;
451 case ID_REGISTRY_EXPORTREGISTRYFILE:
452 ExportRegistryFile(hWnd);
453 break;
454 case ID_REGISTRY_CONNECTNETWORKREGISTRY:
455 break;
456 case ID_REGISTRY_DISCONNECTNETWORKREGISTRY:
457 break;
458 case ID_REGISTRY_PRINT:
459 PrintRegistryHive(hWnd, _T(""));
460 break;
461 case ID_EDIT_DELETE:
462 if (GetFocus() == g_pChildWnd->hTreeWnd) {
463 if (keyPath == 0 || *keyPath == 0) {
464 MessageBeep(MB_ICONHAND);
465 } else if (DeleteKey(hWnd, hKeyRoot, keyPath)) {
466 DeleteNode(g_pChildWnd->hTreeWnd, 0);
468 } else if (GetFocus() == g_pChildWnd->hListWnd) {
469 if (DeleteValue(hWnd, hKeyRoot, keyPath, valueName))
470 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, NULL);
472 break;
473 case ID_EDIT_MODIFY:
474 if (ModifyValue(hWnd, hKeyRoot, keyPath, valueName))
475 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, valueName);
476 break;
477 case ID_EDIT_COPYKEYNAME:
478 CopyKeyName(hWnd, _T(""));
479 break;
480 case ID_EDIT_NEW_KEY:
481 if (CreateKey(hWnd, hKeyRoot, keyPath, newKey)) {
482 if (InsertNode(g_pChildWnd->hTreeWnd, 0, newKey))
483 StartKeyRename(g_pChildWnd->hTreeWnd);
485 break;
486 case ID_EDIT_NEW_STRINGVALUE:
487 valueType = REG_SZ;
488 goto create_value;
489 case ID_EDIT_NEW_BINARYVALUE:
490 valueType = REG_BINARY;
491 goto create_value;
492 case ID_EDIT_NEW_DWORDVALUE:
493 valueType = REG_DWORD;
494 /* fall through */
495 create_value:
496 if (CreateValue(hWnd, hKeyRoot, keyPath, valueType, newKey)) {
497 RefreshListView(g_pChildWnd->hListWnd, hKeyRoot, keyPath, newKey);
498 StartValueRename(g_pChildWnd->hListWnd);
499 /* FIXME: start rename */
501 break;
502 case ID_EDIT_RENAME:
503 if (keyPath == 0 || *keyPath == 0) {
504 MessageBeep(MB_ICONHAND);
505 } else if (GetFocus() == g_pChildWnd->hTreeWnd) {
506 StartKeyRename(g_pChildWnd->hTreeWnd);
507 } else if (GetFocus() == g_pChildWnd->hListWnd) {
508 StartValueRename(g_pChildWnd->hListWnd);
510 break;
511 break;
512 case ID_REGISTRY_PRINTERSETUP:
513 /*PRINTDLG pd;*/
514 /*PrintDlg(&pd);*/
515 /*PAGESETUPDLG psd;*/
516 /*PageSetupDlg(&psd);*/
517 break;
518 case ID_REGISTRY_OPENLOCAL:
519 break;
520 case ID_REGISTRY_EXIT:
521 DestroyWindow(hWnd);
522 break;
523 case ID_VIEW_REFRESH:
524 RefreshView(hWnd);
525 break;
526 /*case ID_OPTIONS_TOOLBAR:*/
527 /* toggle_child(hWnd, LOWORD(wParam), hToolBar);*/
528 /* break;*/
529 case ID_VIEW_STATUSBAR:
530 toggle_child(hWnd, LOWORD(wParam), hStatusBar);
531 break;
532 case ID_HELP_HELPTOPICS:
533 WinHelp(hWnd, _T("regedit"), HELP_FINDER, 0);
534 break;
535 case ID_HELP_ABOUT:
536 ShowAboutBox(hWnd);
537 break;
538 case ID_VIEW_SPLIT: {
539 RECT rt;
540 POINT pt, pts;
541 GetClientRect(g_pChildWnd->hWnd, &rt);
542 pt.x = rt.left + g_pChildWnd->nSplitPos;
543 pt.y = (rt.bottom / 2);
544 pts = pt;
545 if(ClientToScreen(g_pChildWnd->hWnd, &pts)) {
546 SetCursorPos(pts.x, pts.y);
547 SetCursor(LoadCursor(0, IDC_SIZEWE));
548 SendMessage(g_pChildWnd->hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
550 return TRUE;
552 default:
553 return FALSE;
556 return TRUE;
559 /********************************************************************************
561 * FUNCTION: FrameWndProc(HWND, unsigned, WORD, LONG)
563 * PURPOSE: Processes messages for the main frame window.
565 * WM_COMMAND - process the application menu
566 * WM_DESTROY - post a quit message and return
570 LRESULT CALLBACK FrameWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
572 switch (message) {
573 case WM_CREATE:
574 CreateWindowEx(0, szChildClass, _T("regedit child window"), WS_CHILD | WS_VISIBLE,
575 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
576 hWnd, (HMENU)0, hInst, 0);
577 break;
578 case WM_COMMAND:
579 if (!_CmdWndProc(hWnd, message, wParam, lParam))
580 return DefWindowProc(hWnd, message, wParam, lParam);
581 break;
582 case WM_ACTIVATE:
583 if (LOWORD(hWnd))
584 SetFocus(g_pChildWnd->hWnd);
585 break;
586 case WM_SIZE:
587 resize_frame_client(hWnd);
588 break;
589 case WM_TIMER:
590 break;
591 case WM_ENTERMENULOOP:
592 OnEnterMenuLoop(hWnd);
593 break;
594 case WM_EXITMENULOOP:
595 OnExitMenuLoop(hWnd);
596 break;
597 case WM_MENUSELECT:
598 OnMenuSelect(hWnd, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
599 break;
600 case WM_DESTROY:
601 WinHelp(hWnd, _T("regedit"), HELP_QUIT, 0);
602 PostQuitMessage(0);
603 default:
604 return DefWindowProc(hWnd, message, wParam, lParam);
606 return 0;