GUITools.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. //---------------------------------------------------------------------------
  2. #define NO_WIN32_LEAN_AND_MEAN
  3. #include <vcl.h>
  4. #pragma hdrstop
  5. #include <shlobj.h>
  6. #include <Common.h>
  7. #include "GUITools.h"
  8. #include "GUIConfiguration.h"
  9. #include <TextsCore.h>
  10. #include <CoreMain.h>
  11. #include <SessionData.h>
  12. //---------------------------------------------------------------------------
  13. #pragma package(smart_init)
  14. //---------------------------------------------------------------------------
  15. extern const UnicodeString PageantTool = L"pageant.exe";
  16. extern const UnicodeString PuttygenTool = L"puttygen.exe";
  17. //---------------------------------------------------------------------------
  18. bool __fastcall FindFile(UnicodeString & Path)
  19. {
  20. bool Result = FileExists(Path);
  21. if (!Result)
  22. {
  23. int Len = GetEnvironmentVariable(L"PATH", NULL, 0);
  24. if (Len > 0)
  25. {
  26. UnicodeString Paths;
  27. Paths.SetLength(Len - 1);
  28. GetEnvironmentVariable(L"PATH", Paths.c_str(), Len);
  29. UnicodeString NewPath = FileSearch(ExtractFileName(Path), Paths);
  30. Result = !NewPath.IsEmpty();
  31. if (Result)
  32. {
  33. Path = NewPath;
  34. }
  35. }
  36. }
  37. return Result;
  38. }
  39. //---------------------------------------------------------------------------
  40. bool __fastcall FileExistsEx(UnicodeString Path)
  41. {
  42. return FindFile(Path);
  43. }
  44. //---------------------------------------------------------------------------
  45. void __fastcall OpenSessionInPutty(const UnicodeString PuttyPath,
  46. TSessionData * SessionData, UnicodeString Password)
  47. {
  48. UnicodeString Program, Params, Dir;
  49. SplitCommand(PuttyPath, Program, Params, Dir);
  50. Program = ExpandEnvironmentVariables(Program);
  51. if (FindFile(Program))
  52. {
  53. UnicodeString SessionName;
  54. TRegistryStorage * Storage = NULL;
  55. TSessionData * ExportData = NULL;
  56. TRegistryStorage * SourceStorage = NULL;
  57. try
  58. {
  59. Storage = new TRegistryStorage(Configuration->PuttySessionsKey);
  60. Storage->AccessMode = smReadWrite;
  61. // make it compatible with putty
  62. Storage->MungeStringValues = false;
  63. Storage->ForceAnsi = true;
  64. if (Storage->OpenRootKey(true))
  65. {
  66. if (Storage->KeyExists(SessionData->StorageKey))
  67. {
  68. SessionName = SessionData->SessionName;
  69. }
  70. else
  71. {
  72. SourceStorage = new TRegistryStorage(Configuration->PuttySessionsKey);
  73. SourceStorage->MungeStringValues = false;
  74. SourceStorage->ForceAnsi = true;
  75. if (SourceStorage->OpenSubKey(StoredSessions->DefaultSettings->Name, false) &&
  76. Storage->OpenSubKey(GUIConfiguration->PuttySession, true))
  77. {
  78. Storage->Copy(SourceStorage);
  79. Storage->CloseSubKey();
  80. }
  81. ExportData = new TSessionData(L"");
  82. ExportData->Assign(SessionData);
  83. ExportData->Modified = true;
  84. ExportData->Name = GUIConfiguration->PuttySession;
  85. ExportData->Password = L"";
  86. if (SessionData->FSProtocol == fsFTP)
  87. {
  88. if (GUIConfiguration->TelnetForFtpInPutty)
  89. {
  90. ExportData->Protocol = ptTelnet;
  91. ExportData->PortNumber = 23;
  92. // PuTTY does not allow -pw for telnet
  93. Password = L"";
  94. }
  95. else
  96. {
  97. ExportData->Protocol = ptSSH;
  98. ExportData->PortNumber = 22;
  99. }
  100. }
  101. ExportData->Save(Storage, true);
  102. SessionName = GUIConfiguration->PuttySession;
  103. }
  104. }
  105. }
  106. __finally
  107. {
  108. delete Storage;
  109. delete ExportData;
  110. delete SourceStorage;
  111. }
  112. if (!Params.IsEmpty())
  113. {
  114. Params += L" ";
  115. }
  116. if (!Password.IsEmpty())
  117. {
  118. Params += FORMAT(L"-pw %s ", (EscapePuttyCommandParam(Password)));
  119. }
  120. Params += FORMAT(L"-load %s", (EscapePuttyCommandParam(SessionName)));
  121. if (!ExecuteShell(Program, Params))
  122. {
  123. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Program)));
  124. }
  125. }
  126. else
  127. {
  128. throw Exception(FMTLOAD(FILE_NOT_FOUND, (Program)));
  129. }
  130. }
  131. //---------------------------------------------------------------------------
  132. bool __fastcall FindTool(const UnicodeString & Name, UnicodeString & Path)
  133. {
  134. UnicodeString AppPath = IncludeTrailingBackslash(ExtractFilePath(Application->ExeName));
  135. Path = AppPath + Name;
  136. bool Result = true;
  137. if (!FileExists(Path))
  138. {
  139. Path = AppPath + L"PuTTY\\" + Name;
  140. if (!FileExists(Path))
  141. {
  142. Path = Name;
  143. if (!FindFile(Path))
  144. {
  145. Result = false;
  146. }
  147. }
  148. }
  149. return Result;
  150. }
  151. //---------------------------------------------------------------------------
  152. bool __fastcall ExecuteShell(const UnicodeString Path, const UnicodeString Params)
  153. {
  154. return ((int)ShellExecute(NULL, L"open", (wchar_t*)Path.data(),
  155. (wchar_t*)Params.data(), NULL, SW_SHOWNORMAL) > 32);
  156. }
  157. //---------------------------------------------------------------------------
  158. bool __fastcall ExecuteShell(const UnicodeString Path, const UnicodeString Params,
  159. HANDLE & Handle)
  160. {
  161. bool Result;
  162. TShellExecuteInfoW ExecuteInfo;
  163. memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
  164. ExecuteInfo.cbSize = sizeof(ExecuteInfo);
  165. ExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  166. ExecuteInfo.hwnd = Application->Handle;
  167. ExecuteInfo.lpFile = (wchar_t*)Path.data();
  168. ExecuteInfo.lpParameters = (wchar_t*)Params.data();
  169. ExecuteInfo.nShow = SW_SHOW;
  170. Result = (ShellExecuteEx(&ExecuteInfo) != 0);
  171. if (Result)
  172. {
  173. Handle = ExecuteInfo.hProcess;
  174. }
  175. return Result;
  176. }
  177. //---------------------------------------------------------------------------
  178. bool __fastcall ExecuteShellAndWait(HWND Handle, const UnicodeString Path,
  179. const UnicodeString Params, TProcessMessagesEvent ProcessMessages)
  180. {
  181. bool Result;
  182. TShellExecuteInfoW ExecuteInfo;
  183. memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
  184. ExecuteInfo.cbSize = sizeof(ExecuteInfo);
  185. ExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  186. ExecuteInfo.hwnd = Handle;
  187. ExecuteInfo.lpFile = (wchar_t*)Path.data();
  188. ExecuteInfo.lpParameters = (wchar_t*)Params.data();
  189. ExecuteInfo.nShow = SW_SHOW;
  190. Result = (ShellExecuteEx(&ExecuteInfo) != 0);
  191. if (Result)
  192. {
  193. if (ProcessMessages != NULL)
  194. {
  195. unsigned long WaitResult;
  196. do
  197. {
  198. WaitResult = WaitForSingleObject(ExecuteInfo.hProcess, 200);
  199. if (WaitResult == WAIT_FAILED)
  200. {
  201. throw Exception(LoadStr(DOCUMENT_WAIT_ERROR));
  202. }
  203. ProcessMessages();
  204. }
  205. while (WaitResult == WAIT_TIMEOUT);
  206. }
  207. else
  208. {
  209. WaitForSingleObject(ExecuteInfo.hProcess, INFINITE);
  210. }
  211. }
  212. return Result;
  213. }
  214. //---------------------------------------------------------------------------
  215. bool __fastcall ExecuteShellAndWait(HWND Handle, const UnicodeString Command,
  216. TProcessMessagesEvent ProcessMessages)
  217. {
  218. UnicodeString Program, Params, Dir;
  219. SplitCommand(Command, Program, Params, Dir);
  220. return ExecuteShellAndWait(Handle, Program, Params, ProcessMessages);
  221. }
  222. //---------------------------------------------------------------------------
  223. bool __fastcall SpecialFolderLocation(int PathID, UnicodeString & Path)
  224. {
  225. LPITEMIDLIST Pidl;
  226. wchar_t Buf[256];
  227. if (SHGetSpecialFolderLocation(NULL, PathID, &Pidl) == NO_ERROR &&
  228. SHGetPathFromIDList(Pidl, Buf))
  229. {
  230. Path = UnicodeString(Buf);
  231. return true;
  232. }
  233. return false;
  234. }
  235. //---------------------------------------------------------------------------
  236. UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat,
  237. const UnicodeString MultiItemsFormat, int Count, const UnicodeString FirstItem)
  238. {
  239. UnicodeString Result;
  240. if (Count == 1)
  241. {
  242. Result = FORMAT(SingleItemFormat, (FirstItem));
  243. }
  244. else
  245. {
  246. Result = FORMAT(MultiItemsFormat, (Count));
  247. }
  248. return Result;
  249. }
  250. //---------------------------------------------------------------------------
  251. UnicodeString __fastcall ItemsFormatString(const UnicodeString SingleItemFormat,
  252. const UnicodeString MultiItemsFormat, TStrings * Items)
  253. {
  254. return ItemsFormatString(SingleItemFormat, MultiItemsFormat,
  255. Items->Count, (Items->Count > 0 ? Items->Strings[0] : UnicodeString()));
  256. }
  257. //---------------------------------------------------------------------------
  258. UnicodeString __fastcall FileNameFormatString(const UnicodeString SingleFileFormat,
  259. const UnicodeString MultiFilesFormat, TStrings * Files, bool Remote)
  260. {
  261. assert(Files != NULL);
  262. UnicodeString Item;
  263. if (Files->Count > 0)
  264. {
  265. Item = Remote ? UnixExtractFileName(Files->Strings[0]) :
  266. ExtractFileName(Files->Strings[0]);
  267. }
  268. return ItemsFormatString(SingleFileFormat, MultiFilesFormat,
  269. Files->Count, Item);
  270. }
  271. //---------------------------------------------------------------------------
  272. UnicodeString __fastcall UniqTempDir(const UnicodeString BaseDir, const UnicodeString Identity,
  273. bool Mask)
  274. {
  275. UnicodeString TempDir;
  276. do
  277. {
  278. TempDir = BaseDir.IsEmpty() ? SystemTemporaryDirectory() : BaseDir;
  279. TempDir = IncludeTrailingBackslash(TempDir) + Identity;
  280. if (Mask)
  281. {
  282. TempDir += L"?????";
  283. }
  284. else
  285. {
  286. TempDir += IncludeTrailingBackslash(FormatDateTime(L"nnzzz", Now()));
  287. };
  288. }
  289. while (!Mask && DirectoryExists(TempDir));
  290. return TempDir;
  291. }
  292. //---------------------------------------------------------------------------
  293. bool __fastcall DeleteDirectory(const UnicodeString DirName)
  294. {
  295. TSearchRec sr;
  296. bool retval = true;
  297. if (FindFirst(DirName + L"\\*", faAnyFile, sr) == 0) // VCL Function
  298. {
  299. if (FLAGSET(sr.Attr, faDirectory))
  300. {
  301. if (sr.Name != L"." && sr.Name != L"..")
  302. retval = DeleteDirectory(DirName + L"\\" + sr.Name);
  303. }
  304. else
  305. {
  306. retval = DeleteFile(DirName + L"\\" + sr.Name);
  307. }
  308. if (retval)
  309. {
  310. while (FindNext(sr) == 0)
  311. { // VCL Function
  312. if (FLAGSET(sr.Attr, faDirectory))
  313. {
  314. if (sr.Name != L"." && sr.Name != L"..")
  315. retval = DeleteDirectory(DirName + L"\\" + sr.Name);
  316. }
  317. else
  318. {
  319. retval = DeleteFile(DirName + L"\\" + sr.Name);
  320. }
  321. if (!retval) break;
  322. }
  323. }
  324. }
  325. FindClose(sr);
  326. if (retval) retval = RemoveDir(DirName); // VCL function
  327. return retval;
  328. }
  329. //---------------------------------------------------------------------------
  330. UnicodeString __fastcall FormatDateTimeSpan(const UnicodeString TimeFormat, TDateTime DateTime)
  331. {
  332. UnicodeString Result;
  333. if (int(DateTime) > 0)
  334. {
  335. Result = IntToStr(int(DateTime)) + L", ";
  336. }
  337. // days are decremented, because when there are to many of them,
  338. // "integer overflow" error occurs
  339. Result += FormatDateTime(TimeFormat, DateTime - int(DateTime));
  340. return Result;
  341. }
  342. //---------------------------------------------------------------------------
  343. TLocalCustomCommand::TLocalCustomCommand()
  344. {
  345. }
  346. //---------------------------------------------------------------------------
  347. TLocalCustomCommand::TLocalCustomCommand(const TCustomCommandData & Data,
  348. const UnicodeString & Path) :
  349. TFileCustomCommand(Data, Path)
  350. {
  351. }
  352. //---------------------------------------------------------------------------
  353. TLocalCustomCommand::TLocalCustomCommand(const TCustomCommandData & Data,
  354. const UnicodeString & Path, const UnicodeString & FileName,
  355. const UnicodeString & LocalFileName, const UnicodeString & FileList) :
  356. TFileCustomCommand(Data, Path, FileName, FileList)
  357. {
  358. FLocalFileName = LocalFileName;
  359. }
  360. //---------------------------------------------------------------------------
  361. int __fastcall TLocalCustomCommand::PatternLen(int Index, wchar_t PatternCmd)
  362. {
  363. int Len;
  364. if (PatternCmd == L'^')
  365. {
  366. Len = 3;
  367. }
  368. else
  369. {
  370. Len = TFileCustomCommand::PatternLen(Index, PatternCmd);
  371. }
  372. return Len;
  373. }
  374. //---------------------------------------------------------------------------
  375. bool __fastcall TLocalCustomCommand::PatternReplacement(int Index,
  376. const UnicodeString & Pattern, UnicodeString & Replacement, bool & Delimit)
  377. {
  378. bool Result;
  379. if (Pattern == L"!^!")
  380. {
  381. Replacement = FLocalFileName;
  382. Result = true;
  383. }
  384. else
  385. {
  386. Result = TFileCustomCommand::PatternReplacement(Index, Pattern, Replacement, Delimit);
  387. }
  388. return Result;
  389. }
  390. //---------------------------------------------------------------------------
  391. void __fastcall TLocalCustomCommand::DelimitReplacement(
  392. UnicodeString & /*Replacement*/, wchar_t /*Quote*/)
  393. {
  394. // never delimit local commands
  395. }
  396. //---------------------------------------------------------------------------
  397. bool __fastcall TLocalCustomCommand::HasLocalFileName(const UnicodeString & Command)
  398. {
  399. return FindPattern(Command, L'^');
  400. }
  401. //---------------------------------------------------------------------------
  402. bool __fastcall TLocalCustomCommand::IsFileCommand(const UnicodeString & Command)
  403. {
  404. return TFileCustomCommand::IsFileCommand(Command) || HasLocalFileName(Command);
  405. }