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