Tools.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include <Consts.hpp>
  5. #include <shlobj.h>
  6. #include <stdio.h>
  7. #define INITGUID
  8. #include <propkey.h>
  9. #include <Common.h>
  10. #include <TextsWin.h>
  11. #include <TextsCore.h>
  12. #include <HelpWin.h>
  13. #include <Exceptions.h>
  14. #include <CoreMain.h>
  15. #include <RemoteFiles.h>
  16. #include <PuttyTools.h>
  17. #include "GUITools.h"
  18. #include "VCLCommon.h"
  19. #include "Setup.h"
  20. #include "Tools.h"
  21. #include <WinHelpViewer.hpp>
  22. #include <PasTools.hpp>
  23. #include <System.Win.ComObj.hpp>
  24. #include <StrUtils.hpp>
  25. //---------------------------------------------------------------------------
  26. // WORKAROUND
  27. // VCL includes wininet.h (even with NO_WIN32_LEAN_AND_MEAN)
  28. // and it cannot be compined with winhttp.h as of current Windows SDK.
  29. // This is hack to allow that.
  30. // http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/8f468d9f-3f15-452c-803d-fc63ab3f684e/cannot-use-both-winineth-and-winhttph
  31. #undef BOOLAPI
  32. #undef SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
  33. #undef SECURITY_FLAG_IGNORE_CERT_CN_INVALID
  34. #define URL_COMPONENTS URL_COMPONENTS_ANOTHER
  35. #define URL_COMPONENTSA URL_COMPONENTSA_ANOTHER
  36. #define URL_COMPONENTSW URL_COMPONENTSW_ANOTHER
  37. #define LPURL_COMPONENTS LPURL_COMPONENTS_ANOTHER
  38. #define LPURL_COMPONENTSA LPURL_COMPONENTS_ANOTHER
  39. #define LPURL_COMPONENTSW LPURL_COMPONENTS_ANOTHER
  40. #define INTERNET_SCHEME INTERNET_SCHEME_ANOTHER
  41. #define LPINTERNET_SCHEME LPINTERNET_SCHEME_ANOTHER
  42. #define HTTP_VERSION_INFO HTTP_VERSION_INFO_ANOTHER
  43. #define LPHTTP_VERSION_INFO LPHTTP_VERSION_INFO_ANOTHER
  44. #include <winhttp.h>
  45. #undef URL_COMPONENTS
  46. #undef URL_COMPONENTSA
  47. #undef URL_COMPONENTSW
  48. #undef LPURL_COMPONENTS
  49. #undef LPURL_COMPONENTSA
  50. #undef LPURL_COMPONENTSW
  51. #undef INTERNET_SCHEME
  52. #undef LPINTERNET_SCHEME
  53. #undef HTTP_VERSION_INFO
  54. #undef LPHTTP_VERSION_INFO
  55. //---------------------------------------------------------------------------
  56. #pragma package(smart_init)
  57. //---------------------------------------------------------------------------
  58. TFontStyles __fastcall IntToFontStyles(int value)
  59. {
  60. TFontStyles Result;
  61. for (int i = fsBold; i <= fsStrikeOut; i++)
  62. {
  63. if (value & 1)
  64. {
  65. Result << (TFontStyle)i;
  66. }
  67. value >>= 1;
  68. }
  69. return Result;
  70. }
  71. //---------------------------------------------------------------------------
  72. int __fastcall FontStylesToInt(const TFontStyles value)
  73. {
  74. int Result = 0;
  75. for (int i = fsStrikeOut; i >= fsBold; i--)
  76. {
  77. Result <<= 1;
  78. if (value.Contains((TFontStyle)i))
  79. {
  80. Result |= 1;
  81. }
  82. }
  83. return Result;
  84. }
  85. //---------------------------------------------------------------------------
  86. void __fastcall CenterFormOn(TForm * Form, TControl * CenterOn)
  87. {
  88. TPoint ScreenPoint = CenterOn->ClientToScreen(TPoint(0, 0));
  89. Form->Left = ScreenPoint.x + (CenterOn->Width / 2) - (Form->Width / 2);
  90. Form->Top = ScreenPoint.y + (CenterOn->Height / 2) - (Form->Height / 2);
  91. }
  92. //---------------------------------------------------------------------------
  93. UnicodeString __fastcall GetListViewStr(TListView * ListView)
  94. {
  95. UnicodeString Result;
  96. for (int Index = 0; Index < ListView->Columns->Count; Index++)
  97. {
  98. AddToList(Result, IntToStr(ListView->Column[Index]->Width), L",");
  99. }
  100. // WORKAROUND
  101. // Adding an additional comma after the list,
  102. // to ensure that old versions that did not expect the pixels-per-inch part,
  103. // stop at the comma, otherwise they try to parse the
  104. // "last-column-width;pixels-per-inch" as integer and throw.
  105. // For the other instance of this hack, see TCustomListViewColProperties.GetParamsStr
  106. Result += L",;" + SavePixelsPerInch();
  107. return Result;
  108. }
  109. //---------------------------------------------------------------------------
  110. void __fastcall LoadListViewStr(TListView * ListView, UnicodeString ALayoutStr)
  111. {
  112. UnicodeString LayoutStr = ::CutToChar(ALayoutStr, L';', true);
  113. int PixelsPerInch = LoadPixelsPerInch(::CutToChar(ALayoutStr, L';', true));
  114. int Index = 0;
  115. while (!LayoutStr.IsEmpty() && (Index < ListView->Columns->Count))
  116. {
  117. int Width;
  118. if (TryStrToInt(::CutToChar(LayoutStr, L',', true), Width))
  119. {
  120. ListView->Column[Index]->Width = LoadDimension(Width, PixelsPerInch);
  121. }
  122. Index++;
  123. }
  124. }
  125. //---------------------------------------------------------------------------
  126. void __fastcall RestoreForm(UnicodeString Data, TForm * Form)
  127. {
  128. assert(Form);
  129. if (!Data.IsEmpty())
  130. {
  131. Forms::TMonitor * Monitor = FormMonitor(Form);
  132. UnicodeString LeftStr = ::CutToChar(Data, L';', true);
  133. UnicodeString TopStr = ::CutToChar(Data, L';', true);
  134. UnicodeString RightStr = ::CutToChar(Data, L';', true);
  135. UnicodeString BottomStr = ::CutToChar(Data, L';', true);
  136. TWindowState State = (TWindowState)StrToIntDef(::CutToChar(Data, L';', true), (int)wsNormal);
  137. int PixelsPerInch = LoadPixelsPerInch(::CutToChar(Data, L';', true));
  138. TRect Bounds = Form->BoundsRect;
  139. int Left = StrToDimensionDef(LeftStr, PixelsPerInch, Bounds.Left);
  140. int Top = StrToDimensionDef(TopStr, PixelsPerInch, Bounds.Top);
  141. bool DefaultPos = (Left == -1) && (Top == -1);
  142. if (!DefaultPos)
  143. {
  144. Bounds.Left = Left;
  145. Bounds.Top = Top;
  146. }
  147. else
  148. {
  149. Bounds.Left = 0;
  150. Bounds.Top = 0;
  151. }
  152. Bounds.Right = StrToDimensionDef(RightStr, PixelsPerInch, Bounds.Right);
  153. Bounds.Bottom = StrToDimensionDef(BottomStr, PixelsPerInch, Bounds.Bottom);
  154. Form->WindowState = State;
  155. if (State == wsNormal)
  156. {
  157. // move to the target monitor
  158. OffsetRect(Bounds, Monitor->Left, Monitor->Top);
  159. // reduce window size to that of monitor size
  160. // (this does not cut window into monitor!)
  161. if (Bounds.Width() > Monitor->WorkareaRect.Width())
  162. {
  163. Bounds.Right -= (Bounds.Width() - Monitor->WorkareaRect.Width());
  164. }
  165. if (Bounds.Height() > Monitor->WorkareaRect.Height())
  166. {
  167. Bounds.Bottom -= (Bounds.Height() - Monitor->WorkareaRect.Height());
  168. }
  169. if (DefaultPos ||
  170. ((Bounds.Left < Monitor->Left) ||
  171. (Bounds.Left > Monitor->Left + Monitor->WorkareaRect.Width() - 20) ||
  172. (Bounds.Top < Monitor->Top) ||
  173. (Bounds.Top > Monitor->Top + Monitor->WorkareaRect.Height() - 20)))
  174. {
  175. if (Monitor->Primary)
  176. {
  177. if ((Application->MainForm == NULL) || (Application->MainForm == Form))
  178. {
  179. Form->Position = poDefaultPosOnly;
  180. }
  181. else
  182. {
  183. Form->Position = poOwnerFormCenter;
  184. }
  185. Form->Width = Bounds.Width();
  186. Form->Height = Bounds.Height();
  187. }
  188. else
  189. {
  190. // when positioning on non-primary monitor, we need
  191. // to handle that ourselves, so place window to center
  192. Form->SetBounds(Monitor->Left + ((Monitor->Width - Bounds.Width()) / 2),
  193. Monitor->Top + ((Monitor->Height - Bounds.Height()) / 2),
  194. Bounds.Width(), Bounds.Height());
  195. Form->Position = poDesigned;
  196. }
  197. }
  198. else
  199. {
  200. Form->Position = poDesigned;
  201. Form->BoundsRect = Bounds;
  202. }
  203. }
  204. else if (State == wsMaximized)
  205. {
  206. Form->Position = poDesigned;
  207. Bounds = Form->BoundsRect;
  208. OffsetRect(Bounds, Monitor->Left, Monitor->Top);
  209. Form->BoundsRect = Bounds;
  210. }
  211. }
  212. else if (Form->Position == poDesigned)
  213. {
  214. Form->Position = poDefaultPosOnly;
  215. }
  216. }
  217. //---------------------------------------------------------------------------
  218. UnicodeString __fastcall StoreForm(TCustomForm * Form)
  219. {
  220. assert(Form);
  221. TRect Bounds = Form->BoundsRect;
  222. OffsetRect(Bounds, -Form->Monitor->Left, -Form->Monitor->Top);
  223. return FORMAT(L"%d;%d;%d;%d;%d;%s", (SaveDimension(Bounds.Left), SaveDimension(Bounds.Top),
  224. SaveDimension(Bounds.Right), SaveDimension(Bounds.Bottom),
  225. // we do not want WinSCP to start minimized next time (we cannot handle that anyway).
  226. // note that WindowState is wsNormal when window in minimized for some reason.
  227. // actually it is wsMinimized only when minimized by MSVDM
  228. (int)(Form->WindowState == wsMinimized ? wsNormal : Form->WindowState),
  229. SavePixelsPerInch()));
  230. }
  231. //---------------------------------------------------------------------------
  232. void __fastcall RestoreFormSize(UnicodeString Data, TForm * Form)
  233. {
  234. // This has to be called only after DoFormWindowProc(CM_SHOWINGCHANGED).
  235. // See comment in ResizeForm.
  236. UnicodeString WidthStr = ::CutToChar(Data, L',', true);
  237. UnicodeString HeightStr = ::CutToChar(Data, L',', true);
  238. int PixelsPerInch = LoadPixelsPerInch(::CutToChar(Data, L',', true));
  239. int Width = StrToDimensionDef(WidthStr, PixelsPerInch, Form->Width);
  240. int Height = StrToDimensionDef(HeightStr, PixelsPerInch, Form->Height);
  241. ResizeForm(Form, Width, Height);
  242. }
  243. //---------------------------------------------------------------------------
  244. UnicodeString __fastcall StoreFormSize(TForm * Form)
  245. {
  246. return FORMAT(L"%d,%d,%s", (Form->Width, Form->Height, SavePixelsPerInch()));
  247. }
  248. //---------------------------------------------------------------------------
  249. bool __fastcall ExecuteShellAndWait(const UnicodeString Path, const UnicodeString Params)
  250. {
  251. return ExecuteShellAndWait(Application->Handle, Path, Params,
  252. &Application->ProcessMessages);
  253. }
  254. //---------------------------------------------------------------------------
  255. bool __fastcall ExecuteShellAndWait(const UnicodeString Command)
  256. {
  257. return ExecuteShellAndWait(Application->Handle, Command,
  258. &Application->ProcessMessages);
  259. }
  260. //---------------------------------------------------------------------------
  261. bool __fastcall UseAlternativeFunction()
  262. {
  263. return FLAGSET(GetAsyncKeyState(VK_SHIFT), 0x8000);
  264. }
  265. //---------------------------------------------------------------------------
  266. bool __fastcall OpenInNewWindow()
  267. {
  268. return UseAlternativeFunction();
  269. }
  270. //---------------------------------------------------------------------------
  271. void __fastcall ExecuteNewInstance(const UnicodeString & Param)
  272. {
  273. UnicodeString Arg = Param;
  274. if (!Arg.IsEmpty())
  275. {
  276. Arg = FORMAT(L"\"%s\"", (Arg));
  277. }
  278. if (!ExecuteShell(Application->ExeName, Arg))
  279. {
  280. throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Application->ExeName)));
  281. }
  282. }
  283. //---------------------------------------------------------------------------
  284. IShellLink * __fastcall CreateDesktopShortCut(const UnicodeString & Name,
  285. const UnicodeString &File, const UnicodeString & Params, const UnicodeString & Description,
  286. int SpecialFolder, int IconIndex, bool Return)
  287. {
  288. IShellLink* pLink = NULL;
  289. if (SpecialFolder < 0)
  290. {
  291. SpecialFolder = CSIDL_DESKTOPDIRECTORY;
  292. }
  293. try
  294. {
  295. if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  296. IID_IShellLink, (void **) &pLink)))
  297. {
  298. try
  299. {
  300. pLink->SetPath(File.c_str());
  301. pLink->SetDescription(Description.c_str());
  302. pLink->SetArguments(Params.c_str());
  303. pLink->SetShowCmd(SW_SHOW);
  304. // Explicitly setting icon file,
  305. // without this icons are not shown at least in Windows 7 jumplist
  306. pLink->SetIconLocation(File.c_str(), IconIndex);
  307. IPersistFile* pPersistFile;
  308. if (!Return &&
  309. SUCCEEDED(pLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile)))
  310. {
  311. try
  312. {
  313. LPMALLOC ShellMalloc;
  314. LPITEMIDLIST DesktopPidl;
  315. wchar_t DesktopDir[MAX_PATH];
  316. OleCheck(SHGetMalloc(&ShellMalloc));
  317. try
  318. {
  319. OleCheck(SHGetSpecialFolderLocation(NULL, SpecialFolder, &DesktopPidl));
  320. OleCheck(SHGetPathFromIDList(DesktopPidl, DesktopDir));
  321. }
  322. __finally
  323. {
  324. ShellMalloc->Free(DesktopPidl);
  325. ShellMalloc->Release();
  326. }
  327. WideString strShortCutLocation(DesktopDir);
  328. // Name can contain even path (e.g. to create quick launch icon)
  329. strShortCutLocation += UnicodeString(L"\\") + Name + L".lnk";
  330. OleCheck(pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE));
  331. }
  332. __finally
  333. {
  334. pPersistFile->Release();
  335. }
  336. }
  337. // this is necessary for Windows 7 taskbar jump list links
  338. IPropertyStore * PropertyStore;
  339. if (SUCCEEDED(pLink->QueryInterface(IID_IPropertyStore, (void**)&PropertyStore)))
  340. {
  341. PROPVARIANT Prop;
  342. Prop.vt = VT_LPWSTR;
  343. Prop.pwszVal = Name.c_str();
  344. PropertyStore->SetValue(PKEY_Title, Prop);
  345. PropertyStore->Commit();
  346. PropertyStore->Release();
  347. }
  348. }
  349. catch(...)
  350. {
  351. pLink->Release();
  352. throw;
  353. }
  354. if (!Return)
  355. {
  356. pLink->Release();
  357. pLink = NULL;
  358. }
  359. }
  360. }
  361. catch(Exception & E)
  362. {
  363. throw ExtException(&E, LoadStr(CREATE_SHORTCUT_ERROR));
  364. }
  365. return pLink;
  366. }
  367. //---------------------------------------------------------------------------
  368. IShellLink * __fastcall CreateDesktopSessionShortCut(
  369. const UnicodeString & SessionName, UnicodeString Name,
  370. const UnicodeString & AdditionalParams, int SpecialFolder, int IconIndex,
  371. bool Return)
  372. {
  373. bool DefaultsOnly;
  374. UnicodeString InfoTip;
  375. bool IsFolder = StoredSessions->IsFolder(SessionName);
  376. bool IsWorkspace = StoredSessions->IsWorkspace(SessionName);
  377. if (IsFolder || IsWorkspace)
  378. {
  379. InfoTip = FMTLOAD(
  380. (IsFolder ? SHORTCUT_INFO_TIP_FOLDER : SHORTCUT_INFO_TIP_WORKSPACE),
  381. (SessionName));
  382. if (Name.IsEmpty())
  383. {
  384. // no slashes in filename
  385. Name = UnixExtractFileName(SessionName);
  386. }
  387. }
  388. else
  389. {
  390. TSessionData * SessionData =
  391. StoredSessions->ParseUrl(SessionName, NULL, DefaultsOnly);
  392. InfoTip =
  393. FMTLOAD(SHORTCUT_INFO_TIP, (SessionName, SessionData->InfoTip));
  394. if (Name.IsEmpty())
  395. {
  396. // no slashes in filename
  397. Name = SessionData->LocalName;
  398. }
  399. delete SessionData;
  400. }
  401. return
  402. CreateDesktopShortCut(ValidLocalFileName(Name), Application->ExeName,
  403. FORMAT(L"\"%s\"%s%s", (SessionName, (AdditionalParams.IsEmpty() ? L"" : L" "), AdditionalParams)),
  404. InfoTip, SpecialFolder, IconIndex, Return);
  405. }
  406. //---------------------------------------------------------------------------
  407. template<class TEditControl>
  408. void __fastcall ValidateMaskEditT(const UnicodeString & Mask, TEditControl * Edit, int ForceDirectoryMasks)
  409. {
  410. assert(Edit != NULL);
  411. TFileMasks Masks(ForceDirectoryMasks);
  412. try
  413. {
  414. Masks = Mask;
  415. }
  416. catch(EFileMasksException & E)
  417. {
  418. ShowExtendedException(&E);
  419. Edit->SetFocus();
  420. // This does not work for TEdit and TMemo (descendants of TCustomEdit) anymore,
  421. // as it re-selects whole text on exception in TCustomEdit.CMExit
  422. Edit->SelStart = E.ErrorStart - 1;
  423. Edit->SelLength = E.ErrorLen;
  424. Abort();
  425. }
  426. }
  427. //---------------------------------------------------------------------------
  428. void __fastcall ValidateMaskEdit(TComboBox * Edit)
  429. {
  430. ValidateMaskEditT(Edit->Text, Edit, -1);
  431. }
  432. //---------------------------------------------------------------------------
  433. void __fastcall ValidateMaskEdit(TEdit * Edit)
  434. {
  435. ValidateMaskEditT(Edit->Text, Edit, -1);
  436. }
  437. //---------------------------------------------------------------------------
  438. void __fastcall ValidateMaskEdit(TMemo * Edit, bool Directory)
  439. {
  440. UnicodeString Mask = TFileMasks::ComposeMaskStr(GetUnwrappedMemoLines(Edit), Directory);
  441. ValidateMaskEditT(Mask, Edit, Directory ? 1 : 0);
  442. }
  443. //---------------------------------------------------------------------------
  444. TStrings * __fastcall GetUnwrappedMemoLines(TMemo * Memo)
  445. {
  446. TStrings * Result = new TStringList();
  447. // This removes soft linebreakes when text in memo wraps
  448. // (Memo->Lines includes soft linebreaks, while Memo->Text does not)
  449. Result->Text = Memo->Text;
  450. return Result;
  451. }
  452. //---------------------------------------------------------------------------
  453. void __fastcall ExitActiveControl(TForm * Form)
  454. {
  455. if (Form->ActiveControl != NULL)
  456. {
  457. TNotifyEvent OnExit = ((TEdit*)Form->ActiveControl)->OnExit;
  458. if (OnExit != NULL)
  459. {
  460. OnExit(Form->ActiveControl);
  461. }
  462. }
  463. }
  464. //---------------------------------------------------------------------------
  465. void __fastcall OpenBrowser(UnicodeString URL)
  466. {
  467. UnicodeString HomePageUrl = LoadStr(HOMEPAGE_URL);
  468. if (SameText(URL.SubString(1, HomePageUrl.Length()), HomePageUrl))
  469. {
  470. URL = CampaignUrl(URL);
  471. }
  472. ShellExecute(Application->Handle, L"open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL);
  473. }
  474. //---------------------------------------------------------------------------
  475. bool __fastcall IsFormatInClipboard(unsigned int Format)
  476. {
  477. bool Result = OpenClipboard(0);
  478. if (Result)
  479. {
  480. Result = IsClipboardFormatAvailable(Format);
  481. CloseClipboard();
  482. }
  483. return Result;
  484. }
  485. //---------------------------------------------------------------------------
  486. HANDLE __fastcall OpenTextFromClipboard(const wchar_t *& Text)
  487. {
  488. HANDLE Result = NULL;
  489. if (OpenClipboard(0))
  490. {
  491. // Check also for CF_TEXT?
  492. Result = GetClipboardData(CF_UNICODETEXT);
  493. if (Result != NULL)
  494. {
  495. Text = static_cast<const wchar_t*>(GlobalLock(Result));
  496. }
  497. else
  498. {
  499. CloseClipboard();
  500. }
  501. }
  502. return Result;
  503. }
  504. //---------------------------------------------------------------------------
  505. void __fastcall CloseTextFromClipboard(HANDLE Handle)
  506. {
  507. if (Handle != NULL)
  508. {
  509. GlobalUnlock(Handle);
  510. }
  511. CloseClipboard();
  512. }
  513. //---------------------------------------------------------------------------
  514. bool __fastcall TextFromClipboard(UnicodeString & Text)
  515. {
  516. const wchar_t * AText = NULL;
  517. HANDLE Handle = OpenTextFromClipboard(AText);
  518. bool Result = (Handle != NULL);
  519. if (Result)
  520. {
  521. Text = AText;
  522. CloseTextFromClipboard(Handle);
  523. }
  524. return Result;
  525. }
  526. //---------------------------------------------------------------------------
  527. static bool __fastcall GetResource(
  528. const UnicodeString ResName, void *& Content, unsigned long & Size)
  529. {
  530. HRSRC Resource = FindResourceEx(HInstance, RT_RCDATA, ResName.c_str(),
  531. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
  532. bool Result = (Resource != NULL);
  533. if (Result)
  534. {
  535. Size = SizeofResource(HInstance, Resource);
  536. if (!Size)
  537. {
  538. throw Exception(FORMAT(L"Cannot get size of resource %s", (ResName)));
  539. }
  540. Content = LoadResource(HInstance, Resource);
  541. if (!Content)
  542. {
  543. throw Exception(FORMAT(L"Cannot read resource %s", (ResName)));
  544. }
  545. Content = LockResource(Content);
  546. if (!Content)
  547. {
  548. throw Exception(FORMAT(L"Cannot lock resource %s", (ResName)));
  549. }
  550. }
  551. return Result;
  552. }
  553. //---------------------------------------------------------------------------
  554. bool __fastcall DumpResourceToFile(const UnicodeString ResName,
  555. const UnicodeString FileName)
  556. {
  557. void * Content;
  558. unsigned long Size;
  559. bool Result = GetResource(ResName, Content, Size);
  560. if (Result)
  561. {
  562. FILE * f = _wfopen(FileName.c_str(), L"wb");
  563. if (!f)
  564. {
  565. throw Exception(FORMAT(L"Cannot create file %s", (FileName)));
  566. }
  567. if (fwrite(Content, 1, Size, f) != Size)
  568. {
  569. throw Exception(FORMAT(L"Cannot write to file %s", (FileName)));
  570. }
  571. fclose(f);
  572. }
  573. return Result;
  574. }
  575. //---------------------------------------------------------------------------
  576. UnicodeString __fastcall ReadResource(const UnicodeString ResName)
  577. {
  578. void * Content;
  579. unsigned long Size;
  580. UnicodeString Result;
  581. if (GetResource(ResName, Content, Size))
  582. {
  583. Result = UnicodeString(UTF8String(static_cast<char*>(Content), Size));
  584. }
  585. return Result;
  586. }
  587. //---------------------------------------------------------------------------
  588. template <class T>
  589. void __fastcall BrowseForExecutableT(T * Control, UnicodeString Title,
  590. UnicodeString Filter, bool FileNameCommand, bool Escape)
  591. {
  592. UnicodeString Executable, Program, Params, Dir;
  593. Executable = Control->Text;
  594. if (FileNameCommand)
  595. {
  596. ReformatFileNameCommand(Executable);
  597. }
  598. SplitCommand(Executable, Program, Params, Dir);
  599. TOpenDialog * FileDialog = new TOpenDialog(Application);
  600. try
  601. {
  602. if (Escape)
  603. {
  604. Program = ReplaceStr(Program, L"\\\\", L"\\");
  605. }
  606. UnicodeString ExpandedProgram = ExpandEnvironmentVariables(Program);
  607. FileDialog->FileName = ExpandedProgram;
  608. UnicodeString InitialDir = ExtractFilePath(ExpandedProgram);
  609. if (!InitialDir.IsEmpty())
  610. {
  611. FileDialog->InitialDir = InitialDir;
  612. }
  613. FileDialog->Filter = Filter;
  614. FileDialog->Title = Title;
  615. if (FileDialog->Execute())
  616. {
  617. TNotifyEvent PrevOnChange = Control->OnChange;
  618. Control->OnChange = NULL;
  619. try
  620. {
  621. // preserve unexpanded file, if the destination has not changed actually
  622. if (!CompareFileName(ExpandedProgram, FileDialog->FileName))
  623. {
  624. Program = FileDialog->FileName;
  625. if (Escape)
  626. {
  627. Program = ReplaceStr(Program, L"\\", L"\\\\");
  628. }
  629. }
  630. Control->Text = FormatCommand(Program, Params);
  631. }
  632. __finally
  633. {
  634. Control->OnChange = PrevOnChange;
  635. }
  636. if (Control->OnExit != NULL)
  637. {
  638. Control->OnExit(Control);
  639. }
  640. }
  641. }
  642. __finally
  643. {
  644. delete FileDialog;
  645. }
  646. }
  647. //---------------------------------------------------------------------------
  648. void __fastcall BrowseForExecutable(TEdit * Control, UnicodeString Title,
  649. UnicodeString Filter, bool FileNameCommand, bool Escape)
  650. {
  651. BrowseForExecutableT(Control, Title, Filter, FileNameCommand, Escape);
  652. }
  653. //---------------------------------------------------------------------------
  654. void __fastcall BrowseForExecutable(TComboBox * Control, UnicodeString Title,
  655. UnicodeString Filter, bool FileNameCommand, bool Escape)
  656. {
  657. BrowseForExecutableT(Control, Title, Filter, FileNameCommand, Escape);
  658. }
  659. //---------------------------------------------------------------------------
  660. bool __fastcall FontDialog(TFont * Font)
  661. {
  662. bool Result;
  663. TFontDialog * Dialog = new TFontDialog(Application);
  664. try
  665. {
  666. Dialog->Device = fdScreen;
  667. Dialog->Options = TFontDialogOptions() << fdForceFontExist;
  668. Dialog->Font = Font;
  669. Result = Dialog->Execute();
  670. if (Result)
  671. {
  672. Font->Assign(Dialog->Font);
  673. }
  674. }
  675. __finally
  676. {
  677. delete Dialog;
  678. }
  679. return Result;
  680. }
  681. //---------------------------------------------------------------------------
  682. bool __fastcall SaveDialog(UnicodeString Title, UnicodeString Filter,
  683. UnicodeString DefaultExt, UnicodeString & FileName)
  684. {
  685. bool Result;
  686. #if 0
  687. TFileSaveDialog * Dialog = new TFileSaveDialog(Application);
  688. try
  689. {
  690. Dialog->Title = Title;
  691. FilterToFileTypes(Filter, Dialog->FileTypes);
  692. Dialog->DefaultExtension = DefaultExt;
  693. Dialog->FileName = FileName;
  694. UnicodeString DefaultFolder = ExtractFilePath(FileName);
  695. if (!DefaultFolder.IsEmpty())
  696. {
  697. Dialog->DefaultFolder = DefaultFolder;
  698. }
  699. Dialog->Options = Dialog->Options << fdoOverWritePrompt << fdoForceFileSystem <<
  700. fdoPathMustExist << fdoNoReadOnlyReturn;
  701. Result = Dialog->Execute();
  702. if (Result)
  703. {
  704. FileName = Dialog->FileName;
  705. }
  706. }
  707. __finally
  708. {
  709. delete Dialog;
  710. }
  711. #else
  712. TSaveDialog * Dialog = new TSaveDialog(Application);
  713. try
  714. {
  715. Dialog->Title = Title;
  716. Dialog->Filter = Filter;
  717. Dialog->DefaultExt = DefaultExt;
  718. Dialog->FileName = FileName;
  719. UnicodeString InitialDir = ExtractFilePath(FileName);
  720. if (!InitialDir.IsEmpty())
  721. {
  722. Dialog->InitialDir = InitialDir;
  723. }
  724. Dialog->Options = Dialog->Options << ofOverwritePrompt << ofPathMustExist <<
  725. ofNoReadOnlyReturn;
  726. Result = Dialog->Execute();
  727. if (Result)
  728. {
  729. FileName = Dialog->FileName;
  730. }
  731. }
  732. __finally
  733. {
  734. delete Dialog;
  735. }
  736. #endif
  737. return Result;
  738. }
  739. //---------------------------------------------------------------------------
  740. void __fastcall CopyToClipboard(UnicodeString Text)
  741. {
  742. HANDLE Data;
  743. void * DataPtr;
  744. if (OpenClipboard(0))
  745. {
  746. try
  747. {
  748. size_t Size = (Text.Length() + 1) * sizeof(wchar_t);
  749. Data = GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, Size);
  750. try
  751. {
  752. DataPtr = GlobalLock(Data);
  753. try
  754. {
  755. memcpy(DataPtr, Text.c_str(), Size);
  756. EmptyClipboard();
  757. SetClipboardData(CF_UNICODETEXT, Data);
  758. }
  759. __finally
  760. {
  761. GlobalUnlock(Data);
  762. }
  763. }
  764. catch(...)
  765. {
  766. GlobalFree(Data);
  767. throw;
  768. }
  769. }
  770. __finally
  771. {
  772. CloseClipboard();
  773. }
  774. }
  775. else
  776. {
  777. throw Exception(Vcl_Consts_SCannotOpenClipboard);
  778. }
  779. }
  780. //---------------------------------------------------------------------------
  781. void __fastcall CopyToClipboard(TStrings * Strings)
  782. {
  783. if (Strings->Count > 0)
  784. {
  785. if (Strings->Count == 1)
  786. {
  787. CopyToClipboard(Strings->Strings[0]);
  788. }
  789. else
  790. {
  791. CopyToClipboard(Strings->Text);
  792. }
  793. }
  794. }
  795. //---------------------------------------------------------------------------
  796. bool __fastcall IsWin64()
  797. {
  798. static int Result = -1;
  799. if (Result < 0)
  800. {
  801. Result = 0;
  802. BOOL Wow64Process = FALSE;
  803. if (IsWow64Process(GetCurrentProcess(), &Wow64Process))
  804. {
  805. if (Wow64Process)
  806. {
  807. Result = 1;
  808. }
  809. }
  810. }
  811. return (Result > 0);
  812. }
  813. //---------------------------------------------------------------------------
  814. void __fastcall ShutDownWindows()
  815. {
  816. HANDLE Token;
  817. TOKEN_PRIVILEGES Priv;
  818. // Get a token for this process.
  819. Win32Check(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token));
  820. // Get the LUID for the shutdown privilege.
  821. Win32Check(LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &Priv.Privileges[0].Luid));
  822. Priv.PrivilegeCount = 1; // one privilege to set
  823. Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  824. // Get the shutdown privilege for this process.
  825. Win32Check(AdjustTokenPrivileges(Token, FALSE, &Priv, 0, (PTOKEN_PRIVILEGES)NULL, 0));
  826. // Shut down the system and force all applications to close.
  827. Win32Check(ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF,
  828. SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED));
  829. }
  830. //---------------------------------------------------------------------------
  831. void __fastcall EditSelectBaseName(HWND Edit)
  832. {
  833. UnicodeString Text;
  834. Text.SetLength(GetWindowTextLength(Edit) + 1);
  835. GetWindowText(Edit, Text.c_str(), Text.Length());
  836. int P = Text.LastDelimiter(L".");
  837. if (P > 0)
  838. {
  839. // SendMessage does not work, if edit control is not fully
  840. // initialized yet
  841. PostMessage(Edit, EM_SETSEL, 0, P - 1);
  842. }
  843. }
  844. //---------------------------------------------------------------------------
  845. static void __fastcall DoVerifyKey(
  846. UnicodeString FileName, bool TypeOnly, TSshProt SshProt)
  847. {
  848. if (!FileName.Trim().IsEmpty())
  849. {
  850. FileName = ExpandEnvironmentVariables(FileName);
  851. TKeyType Type = KeyType(FileName);
  852. UnicodeString Message;
  853. UnicodeString HelpKeyword = HELP_LOGIN_KEY_TYPE;
  854. switch (Type)
  855. {
  856. case ktOpenSSH:
  857. Message = FMTLOAD(KEY_TYPE_UNSUPPORTED, (FileName, L"OpenSSH SSH-2"));
  858. HelpKeyword = HELP_KEY_TYPE_UNSUPPORTED;
  859. break;
  860. case ktSSHCom:
  861. Message = FMTLOAD(KEY_TYPE_UNSUPPORTED, (FileName, L"ssh.com SSH-2"));
  862. HelpKeyword = HELP_KEY_TYPE_UNSUPPORTED;
  863. break;
  864. case ktSSH1:
  865. case ktSSH2:
  866. // on file select do not check for SSH version as user may
  867. // intend to change it only after he/she selects key file
  868. if (!TypeOnly)
  869. {
  870. if ((Type == ktSSH1) !=
  871. ((SshProt == ssh1only) || (SshProt == ssh1)))
  872. {
  873. Message = FMTLOAD(KEY_TYPE_DIFFERENT_SSH,
  874. (FileName, (Type == ktSSH1 ? L"SSH-1" : L"PuTTY SSH-2")));
  875. }
  876. }
  877. break;
  878. default:
  879. assert(false);
  880. // fallthru
  881. case ktUnopenable:
  882. case ktUnknown:
  883. Message = FMTLOAD(KEY_TYPE_UNKNOWN, (FileName));
  884. break;
  885. }
  886. if (!Message.IsEmpty())
  887. {
  888. Configuration->Usage->Inc(L"PrivateKeySelectErrors");
  889. if (MessageDialog(Message, qtWarning, qaIgnore | qaAbort,
  890. HelpKeyword) == qaAbort)
  891. {
  892. Abort();
  893. }
  894. }
  895. }
  896. }
  897. //---------------------------------------------------------------------------
  898. void __fastcall VerifyKey(UnicodeString FileName)
  899. {
  900. DoVerifyKey(FileName, true, TSshProt(0));
  901. }
  902. //---------------------------------------------------------------------------
  903. void __fastcall VerifyKeyIncludingVersion(UnicodeString FileName, TSshProt SshProt)
  904. {
  905. DoVerifyKey(FileName, false, SshProt);
  906. }
  907. //---------------------------------------------------------------------------
  908. // Code from http://gentoo.osuosl.org/distfiles/cl331.zip/io/
  909. //---------------------------------------------------------------------------
  910. // this was moved to global scope in past in some attempt to fix crashes,
  911. // not sure it really helped
  912. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyInfo;
  913. //---------------------------------------------------------------------------
  914. static bool __fastcall GetProxyUrlFromIE(UnicodeString & Proxy)
  915. {
  916. bool Result = false;
  917. memset(&IEProxyInfo, 0, sizeof(IEProxyInfo));
  918. if (WinHttpGetIEProxyConfigForCurrentUser(&IEProxyInfo))
  919. {
  920. if (IEProxyInfo.lpszProxy != NULL)
  921. {
  922. UnicodeString IEProxy = IEProxyInfo.lpszProxy;
  923. Proxy = L"";
  924. while (Proxy.IsEmpty() && !IEProxy.IsEmpty())
  925. {
  926. UnicodeString Str = ::CutToChar(IEProxy, L';', true);
  927. if (Str.Pos(L"=") == 0)
  928. {
  929. Proxy = Str;
  930. }
  931. else
  932. {
  933. UnicodeString Protocol = ::CutToChar(Str, L'=', true);
  934. if (SameText(Protocol, L"http"))
  935. {
  936. Proxy = Str;
  937. }
  938. }
  939. }
  940. GlobalFree(IEProxyInfo.lpszProxy);
  941. Result = true;
  942. }
  943. if (IEProxyInfo.lpszAutoConfigUrl != NULL)
  944. {
  945. GlobalFree(IEProxyInfo.lpszAutoConfigUrl);
  946. }
  947. if (IEProxyInfo.lpszProxyBypass != NULL)
  948. {
  949. GlobalFree(IEProxyInfo.lpszProxyBypass);
  950. }
  951. }
  952. return Result;
  953. }
  954. //---------------------------------------------------------------------------
  955. bool __fastcall AutodetectProxyUrl(UnicodeString & Proxy)
  956. {
  957. bool Result = false;
  958. /* Forst we try for proxy info direct from the registry if
  959. it's available. */
  960. WINHTTP_PROXY_INFO ProxyInfo;
  961. memset(&ProxyInfo, 0, sizeof(ProxyInfo));
  962. if (WinHttpGetDefaultProxyConfiguration(&ProxyInfo))
  963. {
  964. if (ProxyInfo.lpszProxy != NULL)
  965. {
  966. Proxy = ProxyInfo.lpszProxy;
  967. GlobalFree(ProxyInfo.lpszProxy);
  968. Result = true;
  969. }
  970. if (ProxyInfo.lpszProxyBypass != NULL)
  971. {
  972. GlobalFree(ProxyInfo.lpszProxyBypass);
  973. }
  974. }
  975. /* The next fallback is to get the proxy info from MSIE. This is also
  976. usually much quicker than WinHttpGetProxyForUrl(), although sometimes
  977. it seems to fall back to that, based on the longish delay involved.
  978. Another issue with this is that it won't work in a service process
  979. that isn't impersonating an interactive user (since there isn't a
  980. current user), but in that case we just fall back to
  981. WinHttpGetProxyForUrl() */
  982. if (!Result)
  983. {
  984. Result = GetProxyUrlFromIE(Proxy);
  985. }
  986. // We can also use WinHttpGetProxyForUrl, but it is lengthy
  987. // See the source address of the code for example
  988. return Result;
  989. }
  990. //---------------------------------------------------------------------------
  991. //---------------------------------------------------------------------------
  992. class TWinHelpTester : public TInterfacedObject, public IWinHelpTester
  993. {
  994. public:
  995. virtual bool __fastcall CanShowALink(const UnicodeString ALink, const UnicodeString FileName);
  996. virtual bool __fastcall CanShowTopic(const UnicodeString Topic, const UnicodeString FileName);
  997. virtual bool __fastcall CanShowContext(const int Context, const UnicodeString FileName);
  998. virtual TStringList * __fastcall GetHelpStrings(const UnicodeString ALink);
  999. virtual UnicodeString __fastcall GetHelpPath();
  1000. virtual UnicodeString __fastcall GetDefaultHelpFile();
  1001. IUNKNOWN
  1002. };
  1003. //---------------------------------------------------------------------------
  1004. class TCustomHelpSelector : public TInterfacedObject, public IHelpSelector
  1005. {
  1006. public:
  1007. __fastcall TCustomHelpSelector(const UnicodeString & Name);
  1008. virtual int __fastcall SelectKeyword(TStrings * Keywords);
  1009. virtual int __fastcall TableOfContents(TStrings * Contents);
  1010. IUNKNOWN
  1011. private:
  1012. UnicodeString FName;
  1013. };
  1014. //---------------------------------------------------------------------------
  1015. void __fastcall AssignHelpSelector(IHelpSelector * HelpSelector)
  1016. {
  1017. _di_IHelpSystem HelpSystem;
  1018. if (GetHelpSystem(HelpSystem))
  1019. {
  1020. HelpSystem->AssignHelpSelector(HelpSelector);
  1021. }
  1022. }
  1023. //---------------------------------------------------------------------------
  1024. void __fastcall InitializeCustomHelp(ICustomHelpViewer * HelpViewer)
  1025. {
  1026. _di_IHelpManager HelpManager;
  1027. RegisterViewer(HelpViewer, HelpManager);
  1028. // Register dummy tester that disables win help
  1029. WinHelpTester = new TWinHelpTester();
  1030. AssignHelpSelector(new TCustomHelpSelector(HelpViewer->GetViewerName()));
  1031. }
  1032. //---------------------------------------------------------------------------
  1033. void __fastcall FinalizeCustomHelp()
  1034. {
  1035. AssignHelpSelector(NULL);
  1036. }
  1037. //---------------------------------------------------------------------------
  1038. //---------------------------------------------------------------------------
  1039. bool __fastcall TWinHelpTester::CanShowALink(const UnicodeString ALink,
  1040. const UnicodeString FileName)
  1041. {
  1042. return !Application->HelpFile.IsEmpty();
  1043. }
  1044. //---------------------------------------------------------------------------
  1045. bool __fastcall TWinHelpTester::CanShowTopic(const UnicodeString Topic,
  1046. const UnicodeString FileName)
  1047. {
  1048. assert(false);
  1049. return !Application->HelpFile.IsEmpty();
  1050. }
  1051. //---------------------------------------------------------------------------
  1052. bool __fastcall TWinHelpTester::CanShowContext(const int /*Context*/,
  1053. const UnicodeString FileName)
  1054. {
  1055. assert(false);
  1056. return !Application->HelpFile.IsEmpty();
  1057. }
  1058. //---------------------------------------------------------------------------
  1059. TStringList * __fastcall TWinHelpTester::GetHelpStrings(const UnicodeString ALink)
  1060. {
  1061. assert(false);
  1062. TStringList * Result = new TStringList();
  1063. Result->Add(ViewerName + L": " + ALink);
  1064. return Result;
  1065. }
  1066. //---------------------------------------------------------------------------
  1067. UnicodeString __fastcall TWinHelpTester::GetHelpPath()
  1068. {
  1069. // never called on windows anyway
  1070. return ExtractFilePath(Application->HelpFile);
  1071. }
  1072. //---------------------------------------------------------------------------
  1073. UnicodeString __fastcall TWinHelpTester::GetDefaultHelpFile()
  1074. {
  1075. return Application->HelpFile;
  1076. }
  1077. //---------------------------------------------------------------------------
  1078. //---------------------------------------------------------------------------
  1079. __fastcall TCustomHelpSelector::TCustomHelpSelector(const UnicodeString & Name) :
  1080. FName(Name)
  1081. {
  1082. }
  1083. //---------------------------------------------------------------------------
  1084. int __fastcall TCustomHelpSelector::SelectKeyword(TStrings * /*Keywords*/)
  1085. {
  1086. FAIL;
  1087. return 0;
  1088. }
  1089. //---------------------------------------------------------------------------
  1090. int __fastcall TCustomHelpSelector::TableOfContents(TStrings * Contents)
  1091. {
  1092. return Contents->IndexOf(FName);
  1093. }