1 // MenuPage.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../Common/ZipRegistry.h"
6 
7 #include "../../../Windows/DLL.h"
8 #include "../../../Windows/ErrorMsg.h"
9 #include "../../../Windows/FileFind.h"
10 
11 #include "../Explorer/ContextMenuFlags.h"
12 #include "../Explorer/RegistryContextMenu.h"
13 #include "../Explorer/resource.h"
14 
15 #include "../FileManager/PropertyNameRes.h"
16 
17 #include "../GUI/ExtractDialogRes.h"
18 
19 #include "FormatUtils.h"
20 #include "HelpUtils.h"
21 #include "LangUtils.h"
22 #include "MenuPage.h"
23 #include "MenuPageRes.h"
24 
25 
26 using namespace NWindows;
27 using namespace NContextMenuFlags;
28 
29 static const UInt32 kLangIDs[] =
30 {
31   IDX_SYSTEM_INTEGRATE_TO_MENU,
32   IDX_SYSTEM_CASCADED_MENU,
33   IDX_SYSTEM_ICON_IN_MENU,
34   IDX_EXTRACT_ELIM_DUP,
35   IDT_SYSTEM_CONTEXT_MENU_ITEMS
36 };
37 
38 #define kMenuTopic "fm/options.htm#sevenZip"
39 
40 struct CContextMenuItem
41 {
42   int ControlID;
43   UInt32 Flag;
44 };
45 
46 static const CContextMenuItem kMenuItems[] =
47 {
48   { IDS_CONTEXT_OPEN, kOpen },
49   { IDS_CONTEXT_OPEN, kOpenAs },
50   { IDS_CONTEXT_EXTRACT, kExtract },
51   { IDS_CONTEXT_EXTRACT_HERE, kExtractHere },
52   { IDS_CONTEXT_EXTRACT_TO, kExtractTo },
53 
54   { IDS_CONTEXT_TEST, kTest },
55 
56   { IDS_CONTEXT_COMPRESS, kCompress },
57   { IDS_CONTEXT_COMPRESS_TO, kCompressTo7z },
58   { IDS_CONTEXT_COMPRESS_TO, kCompressToZip },
59 
60   #ifndef UNDER_CE
61   { IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail },
62   { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail },
63   { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail },
64   #endif
65 
66   { IDS_PROP_CHECKSUM, kCRC }
67 };
68 
69 
70 #if !defined(_WIN64)
71 extern bool g_Is_Wow64;
72 #endif
73 
74 #ifndef KEY_WOW64_64KEY
75   #define KEY_WOW64_64KEY (0x0100)
76 #endif
77 
78 #ifndef KEY_WOW64_32KEY
79   #define KEY_WOW64_32KEY (0x0200)
80 #endif
81 
OnInit()82 bool CMenuPage::OnInit()
83 {
84   _initMode = true;
85 
86   Clear_MenuChanged();
87 
88   LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
89 
90   #ifdef UNDER_CE
91 
92   HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU);
93   HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU_2);
94 
95   #else
96 
97   {
98     UString s;
99     {
100       CWindow window(GetItem(IDX_SYSTEM_INTEGRATE_TO_MENU));
101       window.GetText(s);
102     }
103     UString bit64 = LangString(IDS_PROP_BIT64);
104     if (bit64.IsEmpty())
105       bit64 = "64-bit";
106     #ifdef _WIN64
107       bit64.Replace(L"64", L"32");
108     #endif
109     s.Add_Space();
110     s += '(';
111     s += bit64;
112     s += ')';
113     SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s);
114   }
115 
116   const FString prefix = NDLL::GetModuleDirPrefix();
117 
118   _dlls[0].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU;
119   _dlls[1].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU_2;
120 
121   _dlls[0].wow = 0;
122   _dlls[1].wow =
123       #ifdef _WIN64
124         KEY_WOW64_32KEY
125       #else
126         KEY_WOW64_64KEY
127       #endif
128       ;
129 
130   for (unsigned d = 0; d < 2; d++)
131   {
132     CShellDll &dll = _dlls[d];
133 
134     dll.wasChanged = false;
135 
136     #ifndef _WIN64
137     if (d != 0 && !g_Is_Wow64)
138     {
139       HideItem(dll.ctrl);
140       continue;
141     }
142     #endif
143 
144     FString &path = dll.Path;
145     path = prefix;
146     path += (d == 0 ? "7-zip.dll" :
147         #ifdef _WIN64
148           "7-zip32.dll"
149         #else
150           "7-zip64.dll"
151         #endif
152         );
153 
154 
155     if (!NFile::NFind::DoesFileExist(path))
156     {
157       path.Empty();
158       EnableItem(dll.ctrl, false);
159     }
160     else
161     {
162       dll.prevValue = CheckContextMenuHandler(fs2us(path), dll.wow);
163       CheckButton(dll.ctrl, dll.prevValue);
164     }
165   }
166 
167   #endif
168 
169 
170   CContextMenuInfo ci;
171   ci.Load();
172 
173   CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded.Val);
174   CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons.Val);
175   CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val);
176 
177   _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS));
178 
179   const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;
180   _listView.SetExtendedListViewStyle(newFlags, newFlags);
181 
182   _listView.InsertColumn(0, L"", 200);
183 
184   for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
185   {
186     const CContextMenuItem &menuItem = kMenuItems[i];
187 
188     UString s = LangString(menuItem.ControlID);
189     if (menuItem.Flag == kCRC)
190       s = "CRC SHA";
191     if (menuItem.Flag == kOpenAs ||
192         menuItem.Flag == kCRC)
193       s += " >";
194 
195     switch (menuItem.ControlID)
196     {
197       case IDS_CONTEXT_EXTRACT_TO:
198       {
199         s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER));
200         break;
201       }
202       case IDS_CONTEXT_COMPRESS_TO:
203       case IDS_CONTEXT_COMPRESS_TO_EMAIL:
204       {
205         UString s2 = LangString(IDS_CONTEXT_ARCHIVE);
206         switch (menuItem.Flag)
207         {
208           case kCompressTo7z:
209           case kCompressTo7zEmail:
210             s2 += (".7z");
211             break;
212           case kCompressToZip:
213           case kCompressToZipEmail:
214             s2 += (".zip");
215             break;
216         }
217         s = MyFormatNew(s, s2);
218         break;
219       }
220     }
221 
222     int itemIndex = _listView.InsertItem(i, s);
223     _listView.SetCheckState(itemIndex, ((ci.Flags & menuItem.Flag) != 0));
224   }
225 
226   _listView.SetColumnWidthAuto(0);
227   _initMode = false;
228 
229   return CPropertyPage::OnInit();
230 }
231 
232 
233 #ifndef UNDER_CE
234 
ShowMenuErrorMessage(const wchar_t * m,HWND hwnd)235 static void ShowMenuErrorMessage(const wchar_t *m, HWND hwnd)
236 {
237   MessageBoxW(hwnd, m, L"7-Zip", MB_ICONERROR);
238 }
239 
240 #endif
241 
242 
OnApply()243 LONG CMenuPage::OnApply()
244 {
245   #ifndef UNDER_CE
246 
247   for (unsigned d = 2; d != 0;)
248   {
249     d--;
250     CShellDll &dll = _dlls[d];
251     if (dll.wasChanged && !dll.Path.IsEmpty())
252     {
253       bool newVal = IsButtonCheckedBool(dll.ctrl);
254       LONG res = SetContextMenuHandler(newVal, fs2us(dll.Path), dll.wow);
255       if (res != ERROR_SUCCESS && (dll.prevValue != newVal || newVal))
256         ShowMenuErrorMessage(NError::MyFormatMessage(res), *this);
257       dll.prevValue = CheckContextMenuHandler(fs2us(dll.Path), dll.wow);
258       CheckButton(dll.ctrl, dll.prevValue);
259       dll.wasChanged = false;
260     }
261   }
262 
263   #endif
264 
265   if (_cascaded_Changed || _menuIcons_Changed || _elimDup_Changed || _flags_Changed)
266   {
267     CContextMenuInfo ci;
268     ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU);
269     ci.Cascaded.Def = _cascaded_Changed;
270 
271     ci.MenuIcons.Val = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU);
272     ci.MenuIcons.Def = _menuIcons_Changed;
273 
274     ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);
275     ci.ElimDup.Def = _elimDup_Changed;
276 
277     ci.Flags = 0;
278 
279     for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
280       if (_listView.GetCheckState(i))
281         ci.Flags |= kMenuItems[i].Flag;
282 
283     ci.Flags_Def = _flags_Changed;
284     ci.Save();
285 
286     Clear_MenuChanged();
287   }
288 
289   // UnChanged();
290 
291   return PSNRET_NOERROR;
292 }
293 
OnNotifyHelp()294 void CMenuPage::OnNotifyHelp()
295 {
296   ShowHelpWindow(kMenuTopic);
297 }
298 
OnButtonClicked(int buttonID,HWND buttonHWND)299 bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND)
300 {
301   switch (buttonID)
302   {
303     #ifndef UNDER_CE
304     case IDX_SYSTEM_INTEGRATE_TO_MENU:
305     case IDX_SYSTEM_INTEGRATE_TO_MENU_2:
306     {
307       for (unsigned d = 0; d < 2; d++)
308       {
309         CShellDll &dll = _dlls[d];
310         if (buttonID == dll.ctrl && !dll.Path.IsEmpty())
311           dll.wasChanged = true;
312       }
313       break;
314     }
315     #endif
316 
317     case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break;
318     case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break;
319     case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break;
320 
321     default:
322       return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
323   }
324 
325   Changed();
326   return true;
327 }
328 
OnNotify(UINT controlID,LPNMHDR lParam)329 bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam)
330 {
331   if (lParam->hwndFrom == HWND(_listView))
332   {
333     switch (lParam->code)
334     {
335       case (LVN_ITEMCHANGED):
336         return OnItemChanged((const NMLISTVIEW *)lParam);
337     }
338   }
339   return CPropertyPage::OnNotify(controlID, lParam);
340 }
341 
342 
OnItemChanged(const NMLISTVIEW * info)343 bool CMenuPage::OnItemChanged(const NMLISTVIEW *info)
344 {
345   if (_initMode)
346     return true;
347   if ((info->uChanged & LVIF_STATE) != 0)
348   {
349     UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;
350     UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;
351     if (oldState != newState)
352     {
353       _flags_Changed = true;
354       Changed();
355     }
356   }
357   return true;
358 }
359