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