xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Far/Far.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Far.cpp
2 // Test Align for updating !!!!!!!!!!!!!!!!!!
3 
4 #include "StdAfx.h"
5 
6 #include "../../../Common/MyWindows.h"
7 #include "../../../Common/MyInitGuid.h"
8 
9 #include "../../../Common/StringConvert.h"
10 
11 #include "../../../Windows/FileDir.h"
12 #include "../../../Windows/NtCheck.h"
13 
14 #include "../../Common/FileStreams.h"
15 
16 #include "Messages.h"
17 #include "Plugin.h"
18 #include "ProgressBox.h"
19 
20 using namespace NWindows;
21 using namespace NFile;
22 using namespace NDir;
23 using namespace NFar;
24 
25 static const DWORD kShowProgressTime_ms = 100;
26 
27 static const char * const kCommandPrefix = "7-zip";
28 static const char * const kRegisrtryMainKeyName = NULL; // ""
29 static LPCTSTR const kRegisrtryValueNameEnabled = TEXT("UsedByDefault3");
30 static const char * const kHelpTopicConfig =  "Config";
31 static bool kPluginEnabledDefault = true;
32 
33 extern
34 HINSTANCE g_hInstance;
35 HINSTANCE g_hInstance;
36 
37 namespace NFar {
38 
39 extern
40 const char *g_PluginName_for_Error;
41 const char *g_PluginName_for_Error = "7-Zip";
42 
43 }
44 
45 #if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
46 #define NT_CHECK_FAIL_ACTION return FALSE;
47 #endif
48 
49 BOOL WINAPI DllMain(
50   #ifdef UNDER_CE
51     HANDLE
52   #else
53     HINSTANCE
54   #endif
55   hInstance, DWORD dwReason, LPVOID);
DllMain(HANDLE hInstance,DWORD dwReason,LPVOID)56 BOOL WINAPI DllMain(
57   #ifdef UNDER_CE
58     HANDLE
59   #else
60     HINSTANCE
61   #endif
62   hInstance, DWORD dwReason, LPVOID)
63 {
64   if (dwReason == DLL_PROCESS_ATTACH)
65   {
66     // OutputDebugStringA("7-Zip FAR DLL_PROCESS_ATTACH");
67     g_hInstance = (HINSTANCE)hInstance;
68     NT_CHECK
69   }
70   if (dwReason == DLL_PROCESS_DETACH)
71   {
72     // OutputDebugStringA("7-Zip FAR DLL_PROCESS_DETACH");
73   }
74   return TRUE;
75 }
76 
77 static struct COptions
78 {
79   bool Enabled;
80 } g_Options;
81 
82 static const char * const kPliginNameForRegistry = "7-ZIP";
83 
ExitFAR()84 EXTERN_C void WINAPI ExitFAR()
85 {
86   /* WIN32:
87        it's not allowed to call FreeLibrary() from FreeLibrary().
88        So we try to free all DLLs before destructors */
89   // OutputDebugStringA("-- ExitFAR --- START");
90 
91   FreeGlobalCodecs();
92 
93   // OutputDebugStringA("-- ExitFAR --- END");
94 }
95 
SetStartupInfo(const PluginStartupInfo * info)96 EXTERN_C void WINAPI SetStartupInfo(const PluginStartupInfo *info)
97 {
98   MY_TRY_BEGIN
99   g_StartupInfo.Init(*info, kPliginNameForRegistry);
100   g_Options.Enabled = g_StartupInfo.QueryRegKeyValue(
101       HKEY_CURRENT_USER, kRegisrtryMainKeyName,
102       kRegisrtryValueNameEnabled, kPluginEnabledDefault);
103 
104   // OutputDebugStringA("SetStartupInfo");
105   // LoadGlobalCodecs();
106 
107   MY_TRY_END1("SetStartupInfo")
108 }
109 
110 Z7_CLASS_IMP_COM_3(
111   COpenArchiveCallback
112   , IArchiveOpenCallback
113   , IProgress
114   , ICryptoGetTextPassword
115 )
116   // DWORD m_StartTickValue;
117   bool m_MessageBoxIsShown;
118 
119   bool _numFilesTotalDefined;
120   bool _numBytesTotalDefined;
121 public:
122   bool PasswordIsDefined;
123   UString Password;
124 
125 private:
126   CProgressBox _progressBox;
127 public:
128 
129   COpenArchiveCallback()
130     {}
131 
132   void Init()
133   {
134     PasswordIsDefined = false;
135 
136     _numFilesTotalDefined = false;
137     _numBytesTotalDefined = false;
138 
139     m_MessageBoxIsShown = false;
140 
141     _progressBox.Init(
142         // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
143         g_StartupInfo.GetMsgString(NMessageID::kReading));
144   }
145   void ShowMessage();
146 };
147 
148 static HRESULT CheckBreak2()
149 {
150   return WasEscPressed() ? E_ABORT : S_OK;
151 }
152 
153 void COpenArchiveCallback::ShowMessage()
154 {
155   if (!m_MessageBoxIsShown)
156   {
157     DWORD currentTime = GetTickCount();
158     if (currentTime - _progressBox.StartTick < kShowProgressTime_ms)
159       return;
160     m_MessageBoxIsShown = true;
161   }
162 
163   _progressBox.UseBytesForPercents = !_numFilesTotalDefined;
164   _progressBox.Print();
165 }
166 
167 Z7_COM7F_IMF(COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes))
168 {
169   _numFilesTotalDefined = (numFiles != NULL);
170   if (_numFilesTotalDefined)
171     _progressBox.FilesTotal = *numFiles;
172 
173   _numBytesTotalDefined = (numBytes != NULL);
174   if (_numBytesTotalDefined)
175     _progressBox.Total = *numBytes;
176 
177   return CheckBreak2();
178 }
179 
180 Z7_COM7F_IMF(COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes))
181 {
182   if (numFiles)
183     _progressBox.Files = *numFiles;
184 
185   if (numBytes)
186     _progressBox.Completed = *numBytes;
187 
188   ShowMessage();
189   return CheckBreak2();
190 }
191 
192 
193 Z7_COM7F_IMF(COpenArchiveCallback::SetTotal(const UInt64 /* total */))
194 {
195   return CheckBreak2();
196 }
197 
198 Z7_COM7F_IMF(COpenArchiveCallback::SetCompleted(const UInt64 * /* completed */))
199 {
200   ShowMessage();
201   return CheckBreak2();
202 }
203 
204 HRESULT GetPassword(UString &password);
205 HRESULT GetPassword(UString &password)
206 {
207   if (WasEscPressed())
208     return E_ABORT;
209   password.Empty();
210   CInitDialogItem initItems[]=
211   {
212     { DI_DOUBLEBOX, 3, 1, 72, 4, false, false, 0, false,  NMessageID::kGetPasswordTitle, NULL, NULL },
213     { DI_TEXT, 5, 2, 0, 0, false, false, DIF_SHOWAMPERSAND, false, NMessageID::kEnterPasswordForFile, NULL, NULL },
214     { DI_PSWEDIT, 5, 3, 70, 3, true, false, 0, true, -1, "", NULL }
215   };
216 
217   const int kNumItems = Z7_ARRAY_SIZE(initItems);
218   FarDialogItem dialogItems[kNumItems];
219   g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumItems);
220 
221   // sprintf(DialogItems[1].Data,GetMsg(MGetPasswordForFile),FileName);
222   if (g_StartupInfo.ShowDialog(76, 6, NULL, dialogItems, kNumItems) < 0)
223     return E_ABORT;
224 
225   password = MultiByteToUnicodeString(dialogItems[2].Data, CP_OEMCP);
226   return S_OK;
227 }
228 
229 Z7_COM7F_IMF(COpenArchiveCallback::CryptoGetTextPassword(BSTR *password))
230 {
231   if (!PasswordIsDefined)
232   {
233     RINOK(GetPassword(Password))
234     PasswordIsDefined = true;
235   }
236   return StringToBstr(Password, password);
237 }
238 
239 /*
240 HRESULT OpenArchive(const CSysString &fileName,
241     IInFolderArchive **archiveHandlerResult,
242     CArchiverInfo &archiverInfoResult,
243     UString &defaultName,
244     IArchiveOpenCallback *openArchiveCallback)
245 {
246   HRESULT OpenArchive(const CSysString &fileName,
247     IInArchive **archive,
248     CArchiverInfo &archiverInfoResult,
249     IArchiveOpenCallback *openArchiveCallback);
250 }
251 */
252 
253 static HANDLE MyOpenFilePluginW(const wchar_t *name, bool isAbortCodeSupported)
254 {
255   FString normalizedName = us2fs(name);
256   normalizedName.Trim();
257   FString fullName;
258   MyGetFullPathName(normalizedName, fullName);
259   NFind::CFileInfo fileInfo;
260   if (!fileInfo.Find(fullName))
261     return INVALID_HANDLE_VALUE;
262   if (fileInfo.IsDir())
263     return INVALID_HANDLE_VALUE;
264 
265 
266   CMyComPtr<IInFolderArchive> archiveHandler;
267 
268   // CArchiverInfo archiverInfoResult;
269   // ::OutputDebugStringA("before OpenArchive\n");
270 
271   CScreenRestorer screenRestorer;
272   {
273     screenRestorer.Save();
274   }
275 
276   COpenArchiveCallback *openArchiveCallbackSpec = new COpenArchiveCallback;
277   CMyComPtr<IArchiveOpenCallback> uiCallback = openArchiveCallbackSpec;
278 
279   /* COpenCallbackImp object will exist after Open stage for multivolume archioves */
280   COpenCallbackImp *impSpec = new COpenCallbackImp;
281   CMyComPtr<IArchiveOpenCallback> impCallback = impSpec;
282   impSpec->ReOpenCallback = openArchiveCallbackSpec; // we set pointer without reference counter
283 
284   // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
285   openArchiveCallbackSpec->Init();
286   {
287     FString dirPrefix, fileName;
288     GetFullPathAndSplit(fullName, dirPrefix, fileName);
289     impSpec->Init2(dirPrefix, fileName);
290   }
291 
292   // ::OutputDebugStringA("before OpenArchive\n");
293 
294   CAgent *agent = new CAgent;
295   archiveHandler = agent;
296   CMyComBSTR archiveType;
297   HRESULT result = archiveHandler->Open(NULL,
298       GetUnicodeString(fullName, CP_OEMCP), UString(), &archiveType, impCallback);
299   /*
300   HRESULT result = ::OpenArchive(fullName, &archiveHandler,
301       archiverInfoResult, defaultName, openArchiveCallback);
302   */
303   if (result == E_ABORT)
304   {
305     // fixed 18.06:
306     // OpenFilePlugin() is allowed to return (HANDLE)-2 as abort code
307     // OpenPlugin() is not allowed to return (HANDLE)-2.
308     return isAbortCodeSupported ? (HANDLE)-2 : INVALID_HANDLE_VALUE;
309   }
310 
311   UString errorMessage = agent->GetErrorMessage();
312   if (!errorMessage.IsEmpty())
313     g_StartupInfo.ShowErrorMessage(UnicodeStringToMultiByte(errorMessage, CP_OEMCP));
314 
315   if (result != S_OK)
316   {
317     if (result == S_FALSE)
318       return INVALID_HANDLE_VALUE;
319     ShowSysErrorMessage(result);
320     return INVALID_HANDLE_VALUE;
321   }
322 
323   // ::OutputDebugStringA("after OpenArchive\n");
324 
325   CPlugin *plugin = new CPlugin(
326       fullName,
327       // defaultName,
328       agent,
329       (const wchar_t *)archiveType
330       );
331 
332   plugin->PasswordIsDefined = openArchiveCallbackSpec->PasswordIsDefined;
333   plugin->Password = openArchiveCallbackSpec->Password;
334 
335   // OutputDebugStringA("--- OpenFilePlugin ---- END");
336   return (HANDLE)(plugin);
337 }
338 
339 static HANDLE MyOpenFilePlugin(const char *name, bool isAbortCodeSupported)
340 {
341   UINT codePage =
342   #ifdef UNDER_CE
343     CP_OEMCP;
344   #else
345     ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
346   #endif
347   return MyOpenFilePluginW(GetUnicodeString(name, codePage), isAbortCodeSupported);
348 }
349 
350 EXTERN_C HANDLE WINAPI OpenFilePlugin(char *name, const Byte * /* data */, int /* dataSize */)
351 {
352   MY_TRY_BEGIN
353   // OutputDebugStringA("--- OpenFilePlugin");
354   if (name == NULL || (!g_Options.Enabled))
355   {
356     // if (!Opt.ProcessShiftF1)
357       return(INVALID_HANDLE_VALUE);
358   }
359   return MyOpenFilePlugin(name, true); // isAbortCodeSupported
360   MY_TRY_END2("OpenFilePlugin", INVALID_HANDLE_VALUE)
361 }
362 
363 /*
364 EXTERN_C HANDLE WINAPI OpenFilePluginW(const wchar_t *name,const Byte *Data,int DataSize,int OpMode)
365 {
366   MY_TRY_BEGIN
367   if (name == NULL || (!g_Options.Enabled))
368   {
369     // if (!Opt.ProcessShiftF1)
370       return(INVALID_HANDLE_VALUE);
371   }
372   return MyOpenFilePluginW(name);
373   ::OutputDebugStringA("OpenFilePluginW\n");
374   MY_TRY_END2("OpenFilePluginW", INVALID_HANDLE_VALUE);
375 }
376 */
377 
378 EXTERN_C HANDLE WINAPI OpenPlugin(int openFrom, INT_PTR item)
379 {
380   MY_TRY_BEGIN
381 
382   if (openFrom == OPEN_COMMANDLINE)
383   {
384     AString fileName ((const char *)item);
385     if (fileName.IsEmpty())
386       return INVALID_HANDLE_VALUE;
387     if (fileName.Len() >= 2
388         && fileName[0] == '\"'
389         && fileName.Back() == '\"')
390     {
391       fileName.DeleteBack();
392       fileName.DeleteFrontal(1);
393     }
394     return MyOpenFilePlugin(fileName, false); // isAbortCodeSupported
395   }
396 
397   if (openFrom == OPEN_PLUGINSMENU)
398   {
399     switch (item)
400     {
401       case 0:
402       {
403         PluginPanelItem pluginPanelItem;
404         if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem))
405           throw 142134;
406         return MyOpenFilePlugin(pluginPanelItem.FindData.cFileName, false); // isAbortCodeSupported
407       }
408 
409       case 1:
410       {
411         CObjectVector<PluginPanelItem> pluginPanelItem;
412         if (!g_StartupInfo.ControlGetActivePanelSelectedOrCurrentItems(pluginPanelItem))
413           throw 142134;
414         HRESULT res = CompressFiles(pluginPanelItem);
415         if (res != S_OK && res != E_ABORT)
416         {
417           ShowSysErrorMessage(res);
418         }
419         // if (res == S_OK)
420         {
421           /* int t = */ g_StartupInfo.ControlClearPanelSelection();
422           g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEPANEL, NULL);
423           g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWPANEL, NULL);
424           g_StartupInfo.ControlRequestActivePanel(FCTL_UPDATEANOTHERPANEL, NULL);
425           g_StartupInfo.ControlRequestActivePanel(FCTL_REDRAWANOTHERPANEL, NULL);
426         }
427         return INVALID_HANDLE_VALUE;
428       }
429 
430       default:
431         throw 4282215;
432     }
433   }
434 
435   return INVALID_HANDLE_VALUE;
436   MY_TRY_END2("OpenPlugin", INVALID_HANDLE_VALUE)
437 }
438 
439 EXTERN_C void WINAPI ClosePlugin(HANDLE plugin)
440 {
441   // OutputDebugStringA("-- ClosePlugin --- START");
442   // MY_TRY_BEGIN
443   delete (CPlugin *)plugin;
444   // OutputDebugStringA("-- ClosePlugin --- END");
445   // MY_TRY_END1("ClosePlugin");
446 }
447 
448 EXTERN_C int WINAPI GetFindData(HANDLE plugin, struct PluginPanelItem **panelItems, int *itemsNumber, int opMode)
449 {
450   MY_TRY_BEGIN
451   return(((CPlugin *)plugin)->GetFindData(panelItems, itemsNumber, opMode));
452   MY_TRY_END2("GetFindData", FALSE)
453 }
454 
455 EXTERN_C void WINAPI FreeFindData(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber)
456 {
457   // MY_TRY_BEGIN
458   ((CPlugin *)plugin)->FreeFindData(panelItems, itemsNumber);
459   // MY_TRY_END1("FreeFindData");
460 }
461 
462 EXTERN_C int WINAPI GetFiles(HANDLE plugin, struct PluginPanelItem *panelItems,
463     int itemsNumber, int move, char *destPath, int opMode)
464 {
465   MY_TRY_BEGIN
466   return(((CPlugin *)plugin)->GetFiles(panelItems, (unsigned)itemsNumber, move, destPath, opMode));
467   MY_TRY_END2("GetFiles", NFileOperationReturnCode::kError)
468 }
469 
470 EXTERN_C int WINAPI SetDirectory(HANDLE plugin, const char *dir, int opMode)
471 {
472   MY_TRY_BEGIN
473   return(((CPlugin *)plugin)->SetDirectory(dir, opMode));
474   MY_TRY_END2("SetDirectory", FALSE)
475 }
476 
477 EXTERN_C void WINAPI GetPluginInfo(struct PluginInfo *info)
478 {
479   MY_TRY_BEGIN
480 
481   info->StructSize = sizeof(*info);
482   info->Flags = 0;
483   info->DiskMenuStrings = NULL;
484   info->DiskMenuNumbers = NULL;
485   info->DiskMenuStringsNumber = 0;
486   static char *pluginMenuStrings[2];
487   pluginMenuStrings[0] = const_cast<char *>(g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString));
488   pluginMenuStrings[1] = const_cast<char *>(g_StartupInfo.GetMsgString(NMessageID::kCreateArchiveMenuString));
489   info->PluginMenuStrings = (char **)pluginMenuStrings;
490   info->PluginMenuStringsNumber = 2;
491   static char *pluginCfgStrings[1];
492   pluginCfgStrings[0] = const_cast<char *>(g_StartupInfo.GetMsgString(NMessageID::kOpenArchiveMenuString));
493   info->PluginConfigStrings = (char **)pluginCfgStrings;
494   info->PluginConfigStringsNumber = Z7_ARRAY_SIZE(pluginCfgStrings);
495   info->CommandPrefix = const_cast<char *>(kCommandPrefix);
496   MY_TRY_END1("GetPluginInfo")
497 }
498 
499 EXTERN_C int WINAPI Configure(int /* itemNumber */)
500 {
501   MY_TRY_BEGIN
502 
503   const int kEnabledCheckBoxIndex = 1;
504 
505   const int kYSize = 7;
506 
507   struct CInitDialogItem initItems[]=
508   {
509     { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kConfigTitle, NULL, NULL },
510     { DI_CHECKBOX, 5, 2, 0, 0, true, g_Options.Enabled, 0, false, NMessageID::kConfigPluginEnabled, NULL, NULL },
511     { DI_TEXT, 5, 3, 0, 0, false, false, DIF_BOXCOLOR | DIF_SEPARATOR, false, -1, "", NULL },
512     { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL },
513     { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL },
514   };
515 
516   const int kNumDialogItems = Z7_ARRAY_SIZE(initItems);
517   const int kOkButtonIndex = kNumDialogItems - 2;
518 
519   FarDialogItem dialogItems[kNumDialogItems];
520   g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
521 
522   int askCode = g_StartupInfo.ShowDialog(76, kYSize,
523       kHelpTopicConfig, dialogItems, kNumDialogItems);
524 
525   if (askCode != kOkButtonIndex)
526     return (FALSE);
527 
528   g_Options.Enabled = BOOLToBool(dialogItems[kEnabledCheckBoxIndex].Selected);
529 
530   g_StartupInfo.SetRegKeyValue(HKEY_CURRENT_USER, kRegisrtryMainKeyName,
531       kRegisrtryValueNameEnabled, g_Options.Enabled);
532   return(TRUE);
533   MY_TRY_END2("Configure", FALSE)
534 }
535 
536 EXTERN_C void WINAPI GetOpenPluginInfo(HANDLE plugin,struct OpenPluginInfo *info)
537 {
538   MY_TRY_BEGIN
539   ((CPlugin *)plugin)->GetOpenPluginInfo(info);
540   MY_TRY_END1("GetOpenPluginInfo")
541 }
542 
543 EXTERN_C int WINAPI PutFiles(HANDLE plugin, struct PluginPanelItem *panelItems, int itemsNumber, int move, int opMode)
544 {
545   MY_TRY_BEGIN
546   return (((CPlugin *)plugin)->PutFiles(panelItems, (unsigned)itemsNumber, move, opMode));
547   MY_TRY_END2("PutFiles", NFileOperationReturnCode::kError)
548 }
549 
550 EXTERN_C int WINAPI DeleteFiles(HANDLE plugin, PluginPanelItem *panelItems, int itemsNumber, int opMode)
551 {
552   MY_TRY_BEGIN
553   return (((CPlugin *)plugin)->DeleteFiles(panelItems, (unsigned)itemsNumber, opMode));
554   MY_TRY_END2("DeleteFiles", FALSE)
555 }
556 
557 EXTERN_C int WINAPI ProcessKey(HANDLE plugin, int key, unsigned controlState)
558 {
559   MY_TRY_BEGIN
560   /* FIXME: after folder creation with F7, it doesn't reload new file list
561      We need some to reload it */
562   return (((CPlugin *)plugin)->ProcessKey(key, controlState));
563   MY_TRY_END2("ProcessKey", FALSE)
564 }
565 
566 /*
567 struct MakeDirectoryInfo
568 {
569   size_t StructSize;
570   HANDLE hPanel;
571   const wchar_t *Name;
572   OPERATION_MODES OpMode;
573   void* Instance;
574 };
575 
576 typedef INT_PTR MY_intptr_t;
577 
578 MY_intptr_t WINAPI MakeDirectoryW(struct MakeDirectoryInfo *Info)
579 {
580   MY_TRY_BEGIN
581   if (Info->StructSize < sizeof(MakeDirectoryInfo))
582   {
583     return 0;
584   }
585   return 0;
586   MY_TRY_END2("MakeDirectoryW", FALSE);
587 }
588 */
589