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