xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/FM.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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