1 // FM.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/MyWindows.h"
6
7 #if defined(__MINGW32__) || defined(__MINGW64__)
8 #include <shlwapi.h>
9 #else
10 #include <Shlwapi.h>
11 #endif
12
13 #include "../../../../C/Compiler.h"
14 #include "../../../../C/Alloc.h"
15 #ifdef _WIN32
16 #include "../../../../C/DllSecur.h"
17 #endif
18
19 #include "../../../Common/StringConvert.h"
20 #include "../../../Common/StringToInt.h"
21
22 #include "../../../Windows/ErrorMsg.h"
23 #include "../../../Windows/MemoryLock.h"
24 #include "../../../Windows/NtCheck.h"
25 #include "../../../Windows/System.h"
26
27 #ifndef UNDER_CE
28 #include "../../../Windows/SecurityUtils.h"
29 #endif
30
31 #include "../GUI/ExtractRes.h"
32
33 #include "resource.h"
34
35 #include "App.h"
36 #include "FormatUtils.h"
37 #include "LangUtils.h"
38 #include "MyLoadMenu.h"
39 #include "Panel.h"
40 #include "RegistryUtils.h"
41 #include "StringUtils.h"
42 #include "ViewSettings.h"
43
44 using namespace NWindows;
45 using namespace NFile;
46 using namespace NFind;
47
48 // #define MAX_LOADSTRING 100
49
50 extern
51 bool g_DisableUserQuestions;
52 bool g_DisableUserQuestions;
53
54 extern
55 bool g_RAM_Size_Defined;
56 bool g_RAM_Size_Defined;
57
58 extern
59 bool g_LargePagesMode;
60 bool g_LargePagesMode = false;
61 // static bool g_OpenArchive = false;
62
63 static bool g_Maximized = false;
64
65 extern
66 size_t g_RAM_Size;
67 size_t g_RAM_Size;
68
69 #ifdef _WIN32
70 extern
71 HINSTANCE g_hInstance;
72 HINSTANCE g_hInstance;
73 #endif
74
75 HWND g_HWND;
76
77 static UString g_MainPath;
78 static UString g_ArcFormat;
79
80 // HRESULT LoadGlobalCodecs();
81 void FreeGlobalCodecs();
82
83 #ifndef UNDER_CE
84
85 #ifdef Z7_USE_DYN_ComCtl32Version
86 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
87
88 DWORD g_ComCtl32Version;
89
GetDllVersion(LPCTSTR dllName)90 static DWORD GetDllVersion(LPCTSTR dllName)
91 {
92 DWORD dwVersion = 0;
93 const HMODULE hmodule = LoadLibrary(dllName);
94 if (hmodule)
95 {
96 const
97 DLLGETVERSIONPROC f_DllGetVersion = Z7_GET_PROC_ADDRESS(
98 DLLGETVERSIONPROC, hmodule,
99 "DllGetVersion");
100 if (f_DllGetVersion)
101 {
102 DLLVERSIONINFO dvi;
103 ZeroMemory(&dvi, sizeof(dvi));
104 dvi.cbSize = sizeof(dvi);
105 const HRESULT hr = f_DllGetVersion(&dvi);
106 if (SUCCEEDED(hr))
107 dwVersion = (DWORD)MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
108 }
109 FreeLibrary(hmodule);
110 }
111 return dwVersion;
112 }
113
114 #endif
115 #endif
116
117 bool g_IsSmallScreen = false;
118
119 extern
120 bool g_LVN_ITEMACTIVATE_Support;
121 bool g_LVN_ITEMACTIVATE_Support = true;
122 // LVN_ITEMACTIVATE replaces both NM_DBLCLK & NM_RETURN
123 // Windows 2000
124 // NT/98 + IE 3 (g_ComCtl32Version >= 4.70)
125
126
127 static const int kNumDefaultPanels = 1;
128 static const int kSplitterWidth = 4;
129 static const int kSplitterRateMax = 1 << 16;
130 static const int kPanelSizeMin = 120;
131
132
133 class CSplitterPos
134 {
135 int _ratio; // 10000 is max
136 int _pos;
137 int _fullWidth;
SetRatioFromPos(HWND hWnd)138 void SetRatioFromPos(HWND hWnd)
139 { _ratio = (_pos + kSplitterWidth / 2) * kSplitterRateMax /
140 MyMax(GetWidth(hWnd), 1); }
141 public:
GetPos() const142 int GetPos() const
143 { return _pos; }
GetWidth(HWND hWnd) const144 int GetWidth(HWND hWnd) const
145 {
146 RECT rect;
147 ::GetClientRect(hWnd, &rect);
148 return rect.right;
149 }
SetRatio(HWND hWnd,int aRatio)150 void SetRatio(HWND hWnd, int aRatio)
151 {
152 _ratio = aRatio;
153 SetPosFromRatio(hWnd);
154 }
SetPosPure(HWND hWnd,int pos)155 void SetPosPure(HWND hWnd, int pos)
156 {
157 int posMax = GetWidth(hWnd) - kSplitterWidth;
158 if (posMax < kPanelSizeMin * 2)
159 pos = posMax / 2;
160 else
161 {
162 if (pos > posMax - kPanelSizeMin)
163 pos = posMax - kPanelSizeMin;
164 else if (pos < kPanelSizeMin)
165 pos = kPanelSizeMin;
166 }
167 _pos = pos;
168 }
SetPos(HWND hWnd,int pos)169 void SetPos(HWND hWnd, int pos)
170 {
171 _fullWidth = GetWidth(hWnd);
172 SetPosPure(hWnd, pos);
173 SetRatioFromPos(hWnd);
174 }
SetPosFromRatio(HWND hWnd)175 void SetPosFromRatio(HWND hWnd)
176 {
177 int fullWidth = GetWidth(hWnd);
178 if (_fullWidth != fullWidth && fullWidth != 0)
179 {
180 _fullWidth = fullWidth;
181 SetPosPure(hWnd, GetWidth(hWnd) * _ratio / kSplitterRateMax - kSplitterWidth / 2);
182 }
183 }
184 };
185
186 static bool g_CanChangeSplitter = false;
187 static UInt32 g_SplitterPos = 0;
188 static CSplitterPos g_Splitter;
189 static bool g_PanelsInfoDefined = false;
190 static bool g_WindowWasCreated = false;
191
192 static int g_StartCaptureMousePos;
193 static int g_StartCaptureSplitterPos;
194
195 CApp g_App;
196
197 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
198
199 static const wchar_t * const kWindowClass = L"7-Zip::FM";
200
201 #ifdef UNDER_CE
202 #define WS_OVERLAPPEDWINDOW ( \
203 WS_OVERLAPPED | \
204 WS_CAPTION | \
205 WS_SYSMENU | \
206 WS_THICKFRAME | \
207 WS_MINIMIZEBOX | \
208 WS_MAXIMIZEBOX)
209 #endif
210
211
212 /*
213 typedef HRESULT (WINAPI *Func_SetWindowTheme)(
214 HWND hwnd,
215 LPCWSTR pszSubAppName,
216 LPCWSTR pszSubIdList
217 );
218
219 typedef BOOL (WINAPI *Func_AllowDarkModeForWindow)(
220 HWND a_HWND, BOOL a_Allow);
221
222 enum PreferredAppMode
223 {
224 Default,
225 AllowDark,
226 ForceDark,
227 ForceLight,
228 Max
229 };
230 // ordinal 135, in 1903
231 typedef BOOL (WINAPI *Func_SetPreferredAppMode)(PreferredAppMode appMode);
232
233 typedef HRESULT (WINAPI *Func_DwmSetWindowAttribute)(
234 HWND hwnd,
235 DWORD dwAttribute,
236 LPCVOID pvAttribute,
237 DWORD cbAttribute
238 );
239 */
240
InitInstance(int nCmdShow)241 static BOOL InitInstance(int nCmdShow)
242 {
243 CWindow wnd;
244
245 // LoadString(hInstance, IDS_CLASS, windowClass, MAX_LOADSTRING);
246
247 UString title ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
248
249 /*
250 //If it is already running, then focus on the window
251 hWnd = FindWindow(windowClass, title);
252 if (hWnd)
253 {
254 SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
255 return 0;
256 }
257 */
258
259 WNDCLASSW wc;
260
261 // wc.style = CS_HREDRAW | CS_VREDRAW;
262 wc.style = 0;
263 wc.lpfnWndProc = (WNDPROC) WndProc;
264 wc.cbClsExtra = 0;
265 wc.cbWndExtra = 0;
266 wc.hInstance = g_hInstance;
267 wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
268
269 // wc.hCursor = LoadCursor (NULL, IDC_ARROW);
270 wc.hCursor = ::LoadCursor(NULL, IDC_SIZEWE);
271 // wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
272 wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
273
274 wc.lpszMenuName =
275 #ifdef UNDER_CE
276 0
277 #else
278 MAKEINTRESOURCEW(IDM_MENU)
279 #endif
280 ;
281
282 wc.lpszClassName = kWindowClass;
283
284 if (MyRegisterClass(&wc) == 0)
285 return FALSE;
286
287 // RECT rect;
288 // GetClientRect(hWnd, &rect);
289
290 DWORD style = WS_OVERLAPPEDWINDOW;
291 // DWORD style = 0;
292
293 CWindowInfo info;
294 info.maximized = false;
295 int x, y, xSize, ySize;
296 x = y = xSize = ySize = CW_USEDEFAULT;
297 bool windowPosIsRead;
298 info.Read(windowPosIsRead, g_PanelsInfoDefined);
299
300 if (windowPosIsRead)
301 {
302 x = info.rect.left;
303 y = info.rect.top;
304
305 xSize = RECT_SIZE_X(info.rect);
306 ySize = RECT_SIZE_Y(info.rect);
307 }
308
309
310 if (g_PanelsInfoDefined)
311 {
312 g_SplitterPos = info.splitterPos;
313 if (info.numPanels < 1 || info.numPanels > 2)
314 info.numPanels = kNumDefaultPanels;
315 if (info.currentPanel >= 2)
316 info.currentPanel = 0;
317 }
318 else
319 {
320 info.numPanels = kNumDefaultPanels;
321 info.currentPanel = 0;
322 }
323
324 g_App.NumPanels = info.numPanels;
325 g_App.LastFocusedPanel = info.currentPanel;
326
327 if (!wnd.Create(kWindowClass, title, style,
328 x, y, xSize, ySize, NULL, NULL, g_hInstance, NULL))
329 return FALSE;
330
331 /*
332 // doesn't work
333 {
334 const HMODULE hmodule = LoadLibrary("UxTheme.dll");
335 if (hmodule)
336 {
337 {
338 const
339 Func_AllowDarkModeForWindow f = Z7_GET_PROC_ADDRESS(
340 Func_AllowDarkModeForWindow, hmodule,
341 MAKEINTRESOURCEA(133));
342 if (f)
343 {
344 BOOL res = f((HWND)wnd, TRUE);
345 res = res;
346 }
347 }
348 {
349 const
350 Func_SetPreferredAppMode f = Z7_GET_PROC_ADDRESS(
351 Func_SetPreferredAppMode, hmodule,
352 MAKEINTRESOURCEA(135));
353 if (f)
354 {
355 f(ForceDark);
356 }
357 }
358 {
359 const
360 Func_SetWindowTheme f = Z7_GET_PROC_ADDRESS(
361 Func_SetWindowTheme, hmodule,
362 "SetWindowTheme");
363 if (f)
364 {
365 // HRESULT hres = f((HWND)wnd, L"DarkMode_Explorer", NULL);
366 HRESULT hres = f((HWND)wnd, L"Explorer", NULL);
367 hres = hres;
368 }
369 }
370 FreeLibrary(hmodule);
371 }
372 }
373 {
374 const HMODULE hmodule = LoadLibrary("Dwmapi.dll");
375 if (hmodule)
376 {
377 const
378 Func_DwmSetWindowAttribute f = Z7_GET_PROC_ADDRESS(
379 Func_DwmSetWindowAttribute, hmodule,
380 "DwmSetWindowAttribute");
381 if (f)
382 {
383 #ifndef Z7_WIN_DWMWA_USE_IMMERSIVE_DARK_MODE
384 #define Z7_WIN_DWMWA_USE_IMMERSIVE_DARK_MODE 20
385 #endif
386 BOOL value = TRUE;
387 f((HWND)wnd, Z7_WIN_DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
388 }
389 FreeLibrary(hmodule);
390 }
391 }
392 */
393
394 if (nCmdShow == SW_SHOWNORMAL ||
395 nCmdShow == SW_SHOW
396 #ifndef UNDER_CE
397 || nCmdShow == SW_SHOWDEFAULT
398 #endif
399 )
400 {
401 if (info.maximized)
402 nCmdShow = SW_SHOWMAXIMIZED;
403 else
404 nCmdShow = SW_SHOWNORMAL;
405 }
406
407 if (nCmdShow == SW_SHOWMAXIMIZED)
408 g_Maximized = true;
409
410 #ifndef UNDER_CE
411 WINDOWPLACEMENT placement;
412 placement.length = sizeof(placement);
413 if (wnd.GetPlacement(&placement))
414 {
415 if (windowPosIsRead)
416 placement.rcNormalPosition = info.rect;
417 placement.showCmd = (UINT)nCmdShow;
418 wnd.SetPlacement(&placement);
419 }
420 else
421 #endif
422 wnd.Show(nCmdShow);
423
424 return TRUE;
425 }
426
427 /*
428 static void GetCommands(const UString &aCommandLine, UString &aCommands)
429 {
430 UString aProgramName;
431 aCommands.Empty();
432 bool aQuoteMode = false;
433 for (int i = 0; i < aCommandLine.Length(); i++)
434 {
435 wchar_t aChar = aCommandLine[i];
436 if (aChar == L'\"')
437 aQuoteMode = !aQuoteMode;
438 else if (aChar == L' ' && !aQuoteMode)
439 {
440 if (!aQuoteMode)
441 {
442 i++;
443 break;
444 }
445 }
446 else
447 aProgramName += aChar;
448 }
449 aCommands = aCommandLine.Ptr(i);
450 }
451 */
452
453 #if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE)
454
455 extern
456 bool g_Is_Wow64;
457 bool g_Is_Wow64;
458
459 typedef BOOL (WINAPI *Func_IsWow64Process)(HANDLE, PBOOL);
460
Set_Wow64()461 static void Set_Wow64()
462 {
463 g_Is_Wow64 = false;
464 const
465 Func_IsWow64Process fn = Z7_GET_PROC_ADDRESS(
466 Func_IsWow64Process, GetModuleHandleA("kernel32.dll"),
467 "IsWow64Process");
468 if (fn)
469 {
470 BOOL isWow;
471 if (fn(GetCurrentProcess(), &isWow))
472 g_Is_Wow64 = (isWow != FALSE);
473 }
474 }
475
476 #endif
477
478 #if _MSC_VER > 1400 /* && _MSC_VER <= 1900 */
479 // GetVersion was declared deprecated
480 #pragma warning(disable : 4996)
481 #endif
482 #ifdef __clang__
483 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
484 #endif
485
486 bool IsLargePageSupported();
IsLargePageSupported()487 bool IsLargePageSupported()
488 {
489 #ifdef _WIN64
490 return true;
491 #else
492
493 DWORD v = GetVersion();
494 // low byte is major version:
495 // next byte is minor version:
496 v = ((v & 0xff) << 8) | ((v >> 8) & 0xFF);
497 return (v > 0x501);
498 // if ((Byte)v < 5) return false;
499 // if ((Byte)v > 5) return true;
500 // return ((Byte)(v >> 8) > 1);
501 /* large pages work in 5.1 (XP-32bit) if it's (g_Is_Wow64) mode;
502 but here we don't enable them in (XP-32bit). */
503 #endif
504 }
505
506 #ifndef UNDER_CE
507
SetMemoryLock()508 static void SetMemoryLock()
509 {
510 if (!IsLargePageSupported())
511 return;
512 // if (ReadLockMemoryAdd())
513 NSecurity::AddLockMemoryPrivilege();
514
515 if (ReadLockMemoryEnable())
516 if (NSecurity::Get_LargePages_RiskLevel() == 0)
517 {
518 // note: child processes can inherit that Privilege
519 g_LargePagesMode = NSecurity::EnablePrivilege_LockMemory();
520 }
521 }
522
523 extern
524 bool g_SymLink_Supported;
525 bool g_SymLink_Supported = false;
526
Set_SymLink_Supported()527 static void Set_SymLink_Supported()
528 {
529 // g_SymLink_Supported = false;
530 const DWORD v = GetVersion();
531 // low byte is major version:
532 if ((Byte)v < 6)
533 return;
534 g_SymLink_Supported = true;
535 // if (g_SymLink_Supported)
536 {
537 NSecurity::EnablePrivilege_SymLink();
538 }
539 }
540
541 #endif
542
543 /*
544 static const int kNumSwitches = 1;
545
546 namespace NKey {
547 enum Enum
548 {
549 kOpenArachive = 0
550 };
551
552 }
553
554 static const CSwitchForm kSwitchForms[kNumSwitches] =
555 {
556 { L"SOA", NSwitchType::kSimple, false },
557 };
558 */
559
560 // int APIENTRY WinMain2(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */);
561
ErrorMessage(const wchar_t * s)562 static void ErrorMessage(const wchar_t *s)
563 {
564 MessageBoxW(NULL, s, L"7-Zip", MB_ICONERROR);
565 }
566
ErrorMessage(const char * s)567 static void ErrorMessage(const char *s)
568 {
569 ErrorMessage(GetUnicodeString(s));
570 }
571
572
573 #if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
574 #define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return 1;
575 #endif
576
WinMain2(int nCmdShow)577 static int WINAPI WinMain2(int nCmdShow)
578 {
579 g_RAM_Size_Defined = NSystem::GetRamSize(g_RAM_Size);
580
581 #ifdef _WIN32
582
583 /*
584 #ifndef _WIN64
585 #ifndef UNDER_CE
586 {
587 HMODULE hMod = GetModuleHandle("Kernel32.dll");
588 if (hMod)
589 {
590 typedef BOOL (WINAPI *PSETDEP)(DWORD);
591 #define MY_PROCESS_DEP_ENABLE 1
592 PSETDEP procSet = (PSETDEP)GetProcAddress(hMod,"SetProcessDEPPolicy");
593 if (procSet)
594 procSet(MY_PROCESS_DEP_ENABLE);
595
596 typedef BOOL (WINAPI *HSI)(HANDLE, HEAP_INFORMATION_CLASS ,PVOID, SIZE_T);
597 HSI hsi = (HSI)GetProcAddress(hMod, "HeapSetInformation");
598 #define MY_HeapEnableTerminationOnCorruption ((HEAP_INFORMATION_CLASS)1)
599 if (hsi)
600 hsi(NULL, MY_HeapEnableTerminationOnCorruption, NULL, 0);
601 }
602 }
603 #endif
604 #endif
605 */
606
607 NT_CHECK
608 #ifdef Z7_LARGE_PAGES
609 SetLargePageSize();
610 #endif
611
612 #endif
613
614 #ifdef Z7_LANG
615 LoadLangOneTime();
616 #endif
617
618 InitCommonControls();
619
620 #ifdef Z7_USE_DYN_ComCtl32Version
621 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
622 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
623 #endif
624
625 #if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE)
626 Set_Wow64();
627 #endif
628
629
630 g_IsSmallScreen = !NWindows::NControl::IsDialogSizeOK(200, 200);
631
632 // OleInitialize is required for drag and drop.
633 #ifndef UNDER_CE
634 OleInitialize(NULL);
635 #endif
636 // Maybe needs CoInitializeEx also ?
637 // NCOM::CComInitializer comInitializer;
638
639 UString commandsString;
640 // MessageBoxW(NULL, GetCommandLineW(), L"", 0);
641
642 #ifdef UNDER_CE
643 commandsString = GetCommandLineW();
644 #else
645 UString programString;
646 SplitStringToTwoStrings(GetCommandLineW(), programString, commandsString);
647 #endif
648
649 commandsString.Trim();
650 UString paramString, tailString;
651 SplitStringToTwoStrings(commandsString, paramString, tailString);
652 paramString.Trim();
653 tailString.Trim();
654 if (tailString.IsPrefixedBy(L"-t"))
655 g_ArcFormat = tailString.Ptr(2);
656
657 /*
658 UStringVector switches;
659 for (;;)
660 {
661 if (tailString.IsEmpty())
662 break;
663 UString s1, s2;
664 SplitStringToTwoStrings(tailString, s1, s2);
665 if (s2.IsEmpty())
666 {
667 tailString.Trim();
668 switches.Add(tailString);
669 break;
670 }
671 s1.Trim();
672 switches.Add(s1);
673 tailString = s2;
674 }
675
676 FOR_VECTOR(i, switches)
677 {
678 const UString &sw = switches[i];
679 if (sw.IsPrefixedBy(L"-t"))
680 g_ArcFormat = sw.Ptr(2);
681 //
682 else if (sw.IsPrefixedBy(L"-stp"))
683 {
684 const wchar_t *end;
685 UInt32 val = ConvertStringToUInt32(sw.Ptr(4), &end);
686 if (*end != 0)
687 throw 111;
688 g_TypeParseLevel = val;
689 }
690 else
691 //
692 throw 112;
693 }
694 */
695
696 if (!paramString.IsEmpty())
697 {
698 g_MainPath = paramString;
699 // return WinMain2(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
700
701 // MessageBoxW(NULL, paramString, L"", 0);
702 }
703 /*
704 UStringVector commandStrings;
705 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
706 NCommandLineParser::CParser parser(kNumSwitches);
707 try
708 {
709 parser.ParseStrings(kSwitchForms, commandStrings);
710 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
711 if (nonSwitchStrings.Size() > 1)
712 {
713 g_MainPath = nonSwitchStrings[1];
714 // g_OpenArchive = parser[NKey::kOpenArachive].ThereIs;
715 CFileInfoW fileInfo;
716 if (FindFile(g_MainPath, fileInfo))
717 {
718 if (!fileInfo.IsDir())
719 g_OpenArchive = true;
720 }
721 }
722 }
723 catch(...) { }
724 */
725
726
727 #if defined(_WIN32) && !defined(UNDER_CE)
728 SetMemoryLock();
729 Set_SymLink_Supported();
730 #endif
731
732 g_App.ReloadLangItems();
733
734 MSG msg;
735 if (!InitInstance (nCmdShow))
736 return FALSE;
737
738 // we will load Global_Codecs at first use instead.
739 /*
740 OutputDebugStringW(L"Before LoadGlobalCodecs");
741 LoadGlobalCodecs();
742 OutputDebugStringW(L"After LoadGlobalCodecs");
743 */
744
745 #ifndef _UNICODE
746 if (g_IsNT)
747 {
748 HACCEL hAccels = LoadAcceleratorsW(g_hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1));
749 while (GetMessageW(&msg, NULL, 0, 0))
750 {
751 if (TranslateAcceleratorW(g_HWND, hAccels, &msg) == 0)
752 {
753 TranslateMessage(&msg);
754 DispatchMessageW(&msg);
755 }
756 }
757 }
758 else
759 #endif
760 {
761 HACCEL hAccels = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
762 while (GetMessage(&msg, NULL, 0, 0))
763 {
764 if (TranslateAccelerator(g_HWND, hAccels, &msg) == 0)
765 {
766 // if (g_Hwnd != NULL || !IsDialogMessage(g_Hwnd, &msg))
767 // if (!IsDialogMessage(g_Hwnd, &msg))
768 TranslateMessage(&msg);
769 DispatchMessage(&msg);
770 }
771 }
772 }
773
774 // Destructor of g_CodecsReleaser can release DLLs.
775 // But we suppose that it's better to release DLLs here (before destructor).
776 FreeGlobalCodecs();
777
778 g_HWND = NULL;
779 #ifndef UNDER_CE
780 OleUninitialize();
781 #endif
782 return (int)msg.wParam;
783 }
784
WinMain(HINSTANCE hInstance,HINSTANCE,LPWSTR,int nCmdShow)785 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
786 #ifdef UNDER_CE
787 LPWSTR
788 #else
789 LPSTR
790 #endif
791 /* lpCmdLine */, int nCmdShow)
792 {
793 g_hInstance = hInstance;
794
795 try
796 {
797 try
798 {
799 #ifdef _WIN32
800 My_SetDefaultDllDirectories();
801 #endif
802 return WinMain2(nCmdShow);
803 }
804 catch (...)
805 {
806 g_ExitEventLauncher.Exit(true);
807 throw;
808 }
809 }
810 catch(const CNewException &)
811 {
812 ErrorMessage(LangString(IDS_MEM_ERROR));
813 return 1;
814 }
815 catch(const UString &s)
816 {
817 ErrorMessage(s);
818 return 1;
819 }
820 catch(const AString &s)
821 {
822 ErrorMessage(s.Ptr());
823 return 1;
824 }
825 catch(const wchar_t *s)
826 {
827 ErrorMessage(s);
828 return 1;
829 }
830 catch(const char *s)
831 {
832 ErrorMessage(s);
833 return 1;
834 }
835 catch(int v)
836 {
837 AString e ("Error: ");
838 e.Add_UInt32((unsigned)v);
839 ErrorMessage(e);
840 return 1;
841 }
842 catch(...)
843 {
844 ErrorMessage("Unknown error");
845 return 1;
846 }
847 }
848
SaveWindowInfo(HWND aWnd)849 static void SaveWindowInfo(HWND aWnd)
850 {
851 CWindowInfo info;
852
853 #ifdef UNDER_CE
854
855 if (!::GetWindowRect(aWnd, &info.rect))
856 return;
857 info.maximized = g_Maximized;
858
859 #else
860
861 WINDOWPLACEMENT placement;
862 placement.length = sizeof(placement);
863 if (!::GetWindowPlacement(aWnd, &placement))
864 return;
865 info.rect = placement.rcNormalPosition;
866 info.maximized = BOOLToBool(::IsZoomed(aWnd));
867
868 #endif
869
870 info.numPanels = g_App.NumPanels;
871 info.currentPanel = g_App.LastFocusedPanel;
872 info.splitterPos = (unsigned)g_Splitter.GetPos();
873
874 info.Save();
875 }
876
ExecuteCommand(UINT commandID)877 static void ExecuteCommand(UINT commandID)
878 {
879 CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);
880 CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);
881
882 switch (commandID)
883 {
884 case kMenuCmdID_Toolbar_Add: g_App.AddToArchive(); break;
885 case kMenuCmdID_Toolbar_Extract: g_App.ExtractArchives(); break;
886 case kMenuCmdID_Toolbar_Test: g_App.TestArchives(); break;
887 }
888 }
889
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)890 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
891 {
892 switch (message)
893 {
894 case WM_COMMAND:
895 {
896 unsigned wmId = LOWORD(wParam);
897 unsigned wmEvent = HIWORD(wParam);
898 if ((HWND) lParam != NULL && wmEvent != 0)
899 break;
900 if (wmId >= kMenuCmdID_Toolbar_Start && wmId < kMenuCmdID_Toolbar_End)
901 {
902 ExecuteCommand(wmId);
903 return 0;
904 }
905 if (OnMenuCommand(hWnd, wmId))
906 return 0;
907 break;
908 }
909 case WM_INITMENUPOPUP:
910 OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam));
911 break;
912
913 /*
914 It doesn't help
915 case WM_EXITMENULOOP:
916 {
917 OnMenuUnActivating(hWnd);
918 break;
919 }
920 case WM_UNINITMENUPOPUP:
921 OnMenuUnActivating(hWnd, HMENU(wParam), lParam);
922 break;
923 */
924
925 case WM_CREATE:
926 {
927 g_HWND = hWnd;
928 /*
929 INITCOMMONCONTROLSEX icex;
930 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
931 icex.dwICC = ICC_BAR_CLASSES;
932 InitCommonControlsEx(&icex);
933
934 // Toolbar buttons used to create the first 4 buttons.
935 TBBUTTON tbb [ ] =
936 {
937 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
938 // {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
939 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
940 {VIEW_NEWFOLDER, ID_FILE_CREATEFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
941 };
942
943 int baseID = 100;
944 NWindows::NControl::CToolBar aToolBar;
945 aToolBar.Attach(::CreateToolbarEx (hWnd,
946 WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, // | TBSTYLE_FLAT
947 baseID + 2, 11,
948 (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR,
949 (LPCTBBUTTON)&tbb, Z7_ARRAY_SIZE(tbb),
950 0, 0, 100, 30, sizeof (TBBUTTON)));
951 */
952 // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE);
953 // ::SetCursor(cursor);
954
955 if (g_PanelsInfoDefined)
956 g_Splitter.SetPos(hWnd, (int)g_SplitterPos);
957 else
958 {
959 g_Splitter.SetRatio(hWnd, kSplitterRateMax / 2);
960 g_SplitterPos = (unsigned)g_Splitter.GetPos();
961 }
962
963 RECT rect;
964 ::GetClientRect(hWnd, &rect);
965 const int xSize = rect.right;
966 int xSizes[2];
967 xSizes[0] = g_Splitter.GetPos();
968 xSizes[1] = xSize - kSplitterWidth - xSizes[0];
969 if (xSizes[1] < 0)
970 xSizes[1] = 0;
971
972 g_App.CreateDragTarget();
973
974 COpenResult openRes;
975 bool needOpenArc = false;
976
977 UString fullPath = g_MainPath;
978 if (!fullPath.IsEmpty() /* && g_OpenArchive */)
979 {
980 if (!NFile::NName::IsAbsolutePath(fullPath))
981 {
982 FString fullPathF;
983 if (NFile::NName::GetFullPath(us2fs(fullPath), fullPathF))
984 fullPath = fs2us(fullPathF);
985 }
986 if (NFile::NFind::DoesFileExist_FollowLink(us2fs(fullPath)))
987 needOpenArc = true;
988 }
989
990 HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes,
991 needOpenArc,
992 openRes);
993
994 if (res == E_ABORT)
995 return -1;
996
997 if ((needOpenArc && !openRes.ArchiveIsOpened) || res != S_OK)
998 {
999 UString m ("Error");
1000 if (res == S_FALSE || res == S_OK)
1001 {
1002 m = MyFormatNew(openRes.Encrypted ?
1003 IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
1004 IDS_CANT_OPEN_ARCHIVE,
1005 fullPath);
1006 }
1007 else if (res != S_OK)
1008 m = HResultToMessage(res);
1009 if (!openRes.ErrorMessage.IsEmpty())
1010 {
1011 m.Add_LF();
1012 m += openRes.ErrorMessage;
1013 }
1014 ErrorMessage(m);
1015 return -1;
1016 }
1017
1018 g_WindowWasCreated = true;
1019
1020 // g_SplitterPos = 0;
1021
1022 // ::DragAcceptFiles(hWnd, TRUE);
1023 RegisterDragDrop(hWnd, g_App._dropTarget);
1024
1025 break;
1026 }
1027
1028 case WM_CLOSE:
1029 {
1030 // why do we use WA_INACTIVE here ?
1031 SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd);
1032 g_ExitEventLauncher.Exit(false);
1033 // ::DragAcceptFiles(hWnd, FALSE);
1034 RevokeDragDrop(hWnd);
1035 g_App._dropTarget.Release();
1036
1037 if (g_WindowWasCreated)
1038 g_App.Save();
1039
1040 g_App.ReleaseApp();
1041
1042 if (g_WindowWasCreated)
1043 SaveWindowInfo(hWnd);
1044
1045 g_ExitEventLauncher.Exit(true);
1046 // default DefWindowProc will call DestroyWindow / WM_DESTROY
1047 break;
1048 }
1049
1050 case WM_DESTROY:
1051 {
1052 PostQuitMessage(0);
1053 break;
1054 }
1055
1056 // case WM_MOVE: break;
1057
1058 case WM_LBUTTONDOWN:
1059 g_StartCaptureMousePos = LOWORD(lParam);
1060 g_StartCaptureSplitterPos = g_Splitter.GetPos();
1061 ::SetCapture(hWnd);
1062 break;
1063
1064 case WM_LBUTTONUP:
1065 {
1066 ::ReleaseCapture();
1067 break;
1068 }
1069
1070 case WM_MOUSEMOVE:
1071 {
1072 if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd)
1073 {
1074 g_Splitter.SetPos(hWnd, g_StartCaptureSplitterPos +
1075 (short)LOWORD(lParam) - g_StartCaptureMousePos);
1076 g_App.MoveSubWindows();
1077 }
1078 break;
1079 }
1080
1081 case WM_SIZE:
1082 {
1083 if (g_CanChangeSplitter)
1084 g_Splitter.SetPosFromRatio(hWnd);
1085 else
1086 {
1087 g_Splitter.SetPos(hWnd, (int)g_SplitterPos );
1088 g_CanChangeSplitter = true;
1089 }
1090
1091 g_Maximized = (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_MAXSHOW);
1092
1093 g_App.MoveSubWindows();
1094 /*
1095 int xSize = LOWORD(lParam);
1096 int ySize = HIWORD(lParam);
1097 // int xSplitter = 2;
1098 int xWidth = g_SplitPos;
1099 // int xSplitPos = xWidth;
1100 g_Panel[0]._listView.MoveWindow(0, 0, xWidth, ySize);
1101 g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize);
1102 */
1103 return 0;
1104 // break;
1105 }
1106
1107 case WM_SETFOCUS:
1108 // g_App.SetFocus(g_App.LastFocusedPanel);
1109 g_App.SetFocusToLastItem();
1110 break;
1111
1112 /*
1113 case WM_ACTIVATE:
1114 {
1115 int fActive = LOWORD(wParam);
1116 switch (fActive)
1117 {
1118 case WA_INACTIVE:
1119 {
1120 // g_FocusIndex = g_App.LastFocusedPanel;
1121 // g_App.LastFocusedPanel = g_App.GetFocusedPanelIndex();
1122 // return 0;
1123 }
1124 }
1125 break;
1126 }
1127 */
1128
1129 /*
1130 case kLangWasChangedMessage:
1131 MyLoadMenu();
1132 return 0;
1133 */
1134
1135 /*
1136 case WM_SETTINGCHANGE:
1137 break;
1138 */
1139
1140 case WM_NOTIFY:
1141 {
1142 g_App.OnNotify((int)wParam, (LPNMHDR)lParam);
1143 break;
1144 }
1145
1146 /*
1147 case WM_DROPFILES:
1148 {
1149 g_App.GetFocusedPanel().CompressDropFiles((HDROP)wParam);
1150 return 0 ;
1151 }
1152 */
1153 }
1154 #ifndef _UNICODE
1155 if (g_IsNT)
1156 return DefWindowProcW(hWnd, message, wParam, lParam);
1157 else
1158 #endif
1159 return DefWindowProc(hWnd, message, wParam, lParam);
1160
1161 }
1162
Window_GetRealHeight(NWindows::CWindow & w)1163 static int Window_GetRealHeight(NWindows::CWindow &w)
1164 {
1165 RECT rect;
1166 w.GetWindowRect(&rect);
1167 int res = RECT_SIZE_Y(rect);
1168 #ifndef UNDER_CE
1169 WINDOWPLACEMENT placement;
1170 if (w.GetPlacement(&placement))
1171 res += placement.rcNormalPosition.top;
1172 #endif
1173 return res;
1174 }
1175
MoveSubWindows()1176 void CApp::MoveSubWindows()
1177 {
1178 HWND hWnd = _window;
1179 RECT rect;
1180 if (!hWnd)
1181 return;
1182 ::GetClientRect(hWnd, &rect);
1183 int xSize = rect.right;
1184 if (xSize == 0)
1185 return;
1186 int headerSize = 0;
1187
1188 #ifdef UNDER_CE
1189 _commandBar.AutoSize();
1190 {
1191 _commandBar.Show(true); // maybe we need it for
1192 headerSize += _commandBar.Height();
1193 }
1194 #endif
1195
1196 if (_toolBar)
1197 {
1198 _toolBar.AutoSize();
1199 #ifdef UNDER_CE
1200 int h2 = Window_GetRealHeight(_toolBar);
1201 _toolBar.Move(0, headerSize, xSize, h2);
1202 #endif
1203 headerSize += Window_GetRealHeight(_toolBar);
1204 }
1205
1206 int ySize = MyMax((int)(rect.bottom - headerSize), 0);
1207
1208 if (NumPanels > 1)
1209 {
1210 Panels[0].Move(0, headerSize, g_Splitter.GetPos(), ySize);
1211 int xWidth1 = g_Splitter.GetPos() + kSplitterWidth;
1212 Panels[1].Move(xWidth1, headerSize, xSize - xWidth1, ySize);
1213 }
1214 else
1215 {
1216 /*
1217 int otherPanel = 1 - LastFocusedPanel;
1218 if (PanelsCreated[otherPanel])
1219 Panels[otherPanel].Move(0, headerSize, 0, ySize);
1220 */
1221 Panels[LastFocusedPanel].Move(0, headerSize, xSize, ySize);
1222 }
1223 }
1224