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