Common.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Exceptions.h"
  6. #include "TextsCore.h"
  7. #include "Interface.h"
  8. #include <math.h>
  9. #include <shellapi.h>
  10. //---------------------------------------------------------------------------
  11. #pragma package(smart_init)
  12. //---------------------------------------------------------------------------
  13. #ifdef _DEBUG
  14. #include <stdio.h>
  15. void __fastcall Trace(const AnsiString SourceFile, const AnsiString Func,
  16. int Line, const AnsiString Message)
  17. {
  18. const char * FileName = getenv(TRACEENV);
  19. // !!!
  20. if (FileName == NULL)
  21. {
  22. FileName = "c:\\winscptrace.log";
  23. }
  24. // !!!
  25. if (FileName != NULL)
  26. {
  27. FILE * File = fopen(FileName, "a");
  28. if (File != NULL)
  29. {
  30. fprintf(File, "[%s] %s:%d:%s\n %s\n",
  31. Now().TimeString().c_str(),
  32. ExtractFileName(SourceFile).c_str(), Line, Func.c_str(), Message.c_str());
  33. fclose(File);
  34. }
  35. }
  36. }
  37. #endif // ifdef _DEBUG
  38. //---------------------------------------------------------------------------
  39. // TCriticalSection
  40. //---------------------------------------------------------------------------
  41. __fastcall TCriticalSection::TCriticalSection()
  42. {
  43. InitializeCriticalSection(&FSection);
  44. }
  45. //---------------------------------------------------------------------------
  46. __fastcall TCriticalSection::~TCriticalSection()
  47. {
  48. DeleteCriticalSection(&FSection);
  49. }
  50. //---------------------------------------------------------------------------
  51. void __fastcall TCriticalSection::Enter()
  52. {
  53. EnterCriticalSection(&FSection);
  54. }
  55. //---------------------------------------------------------------------------
  56. void __fastcall TCriticalSection::Leave()
  57. {
  58. LeaveCriticalSection(&FSection);
  59. }
  60. //---------------------------------------------------------------------------
  61. // TGuard
  62. //---------------------------------------------------------------------------
  63. __fastcall TGuard::TGuard(TCriticalSection * ACriticalSection) :
  64. FCriticalSection(ACriticalSection)
  65. {
  66. assert(ACriticalSection != NULL);
  67. FCriticalSection->Enter();
  68. }
  69. //---------------------------------------------------------------------------
  70. __fastcall TGuard::~TGuard()
  71. {
  72. FCriticalSection->Leave();
  73. }
  74. //---------------------------------------------------------------------------
  75. //---------------------------------------------------------------------------
  76. const char EngShortMonthNames[12][4] =
  77. {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  78. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  79. //---------------------------------------------------------------------------
  80. AnsiString ReplaceChar(AnsiString Str, Char A, Char B)
  81. {
  82. for (Integer Index = 0; Index < Str.Length(); Index++)
  83. if (Str[Index+1] == A) Str[Index+1] = B;
  84. return Str;
  85. }
  86. //---------------------------------------------------------------------------
  87. AnsiString DeleteChar(AnsiString Str, Char C)
  88. {
  89. int P;
  90. while ((P = Str.Pos(C)) > 0)
  91. {
  92. Str.Delete(P, 1);
  93. }
  94. return Str;
  95. }
  96. //---------------------------------------------------------------------------
  97. void PackStr(AnsiString &Str)
  98. {
  99. // Following will free unnecessary bytes
  100. Str = Str.c_str();
  101. }
  102. //---------------------------------------------------------------------------
  103. AnsiString MakeValidFileName(AnsiString FileName)
  104. {
  105. AnsiString IllegalChars = ";,=+<>|\"[] \\/?*";
  106. for (int Index = 0; Index < IllegalChars.Length(); Index++)
  107. {
  108. ReplaceChar(FileName, IllegalChars[Index+1], '-');
  109. }
  110. return FileName;
  111. }
  112. //---------------------------------------------------------------------------
  113. AnsiString RootKeyToStr(HKEY RootKey)
  114. {
  115. if (RootKey == HKEY_USERS) return "HKEY_USERS";
  116. else
  117. if (RootKey == HKEY_LOCAL_MACHINE) return "HKEY_LOCAL_MACHINE";
  118. else
  119. if (RootKey == HKEY_CURRENT_USER) return "HKEY_CURRENT_USER";
  120. else
  121. if (RootKey == HKEY_CLASSES_ROOT) return "HKEY_CLASSES_ROOT";
  122. else
  123. if (RootKey == HKEY_CURRENT_CONFIG) return "HKEY_CURRENT_CONFIG";
  124. else
  125. if (RootKey == HKEY_DYN_DATA) return "HKEY_DYN_DATA";
  126. else
  127. { Abort(); return ""; };
  128. }
  129. //---------------------------------------------------------------------------
  130. AnsiString BooleanToEngStr(bool B)
  131. {
  132. return B ? "Yes" : "No";
  133. }
  134. //---------------------------------------------------------------------------
  135. AnsiString BooleanToStr(bool B)
  136. {
  137. return B ? LoadStr(YES_STR) : LoadStr(NO_STR);
  138. }
  139. //---------------------------------------------------------------------------
  140. AnsiString CutToChar(AnsiString &Str, Char Ch, bool Trim)
  141. {
  142. Integer P = Str.Pos(Ch);
  143. AnsiString Result;
  144. if (P)
  145. {
  146. Result = Str.SubString(1, P-1);
  147. Str.Delete(1, P);
  148. }
  149. else
  150. {
  151. Result = Str;
  152. Str = "";
  153. }
  154. if (Trim)
  155. {
  156. Result = Result.TrimRight();
  157. Str = Str.TrimLeft();
  158. }
  159. return Result;
  160. }
  161. //---------------------------------------------------------------------------
  162. AnsiString ExceptionLogString(Exception *E)
  163. {
  164. assert(E);
  165. if (E->InheritsFrom(__classid(Exception)))
  166. {
  167. AnsiString Msg;
  168. Msg = FORMAT("(%s) %s", (E->ClassName(), E->Message));
  169. if (E->InheritsFrom(__classid(ExtException)))
  170. {
  171. TStrings * MoreMessages = ((ExtException*)E)->MoreMessages;
  172. if (MoreMessages)
  173. {
  174. Msg += "\n" +
  175. StringReplace(MoreMessages->Text, "\r", "", TReplaceFlags() << rfReplaceAll);
  176. }
  177. }
  178. return Msg;
  179. }
  180. else
  181. {
  182. char Buffer[1024];
  183. ExceptionErrorMessage(ExceptObject(), ExceptAddr(), Buffer, sizeof(Buffer));
  184. return AnsiString(Buffer);
  185. }
  186. }
  187. //---------------------------------------------------------------------------
  188. bool IsDots(const AnsiString Str)
  189. {
  190. char * str = Str.c_str();
  191. return (str[strspn(str, ".")] == '\0');
  192. }
  193. //---------------------------------------------------------------------------
  194. AnsiString __fastcall SystemTemporaryDirectory()
  195. {
  196. AnsiString TempDir;
  197. TempDir.SetLength(MAX_PATH);
  198. TempDir.SetLength(GetTempPath(MAX_PATH, TempDir.c_str()));
  199. return TempDir;
  200. }
  201. //---------------------------------------------------------------------------
  202. AnsiString __fastcall StripPathQuotes(const AnsiString Path)
  203. {
  204. if ((Path.Length() >= 2) &&
  205. (Path[1] == '\"') && (Path[Path.Length()] == '\"'))
  206. {
  207. return Path.SubString(2, Path.Length() - 2);
  208. }
  209. else
  210. {
  211. return Path;
  212. }
  213. }
  214. //---------------------------------------------------------------------------
  215. AnsiString __fastcall AddPathQuotes(AnsiString Path)
  216. {
  217. Path = StripPathQuotes(Path);
  218. if (Path.Pos(" "))
  219. {
  220. Path = "\"" + Path + "\"";
  221. }
  222. return Path;
  223. }
  224. //---------------------------------------------------------------------------
  225. void __fastcall SplitCommand(AnsiString Command, AnsiString &Program,
  226. AnsiString & Params, AnsiString & Dir)
  227. {
  228. Command = Command.Trim();
  229. Params = "";
  230. Dir = "";
  231. if (!Command.IsEmpty() && (Command[1] == '\"'))
  232. {
  233. Command.Delete(1, 1);
  234. int P = Command.Pos('"');
  235. if (P)
  236. {
  237. Program = Command.SubString(1, P-1).Trim();
  238. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  239. }
  240. else
  241. {
  242. throw Exception(FMTLOAD(INVALID_SHELL_COMMAND, ("\"" + Command)));
  243. }
  244. }
  245. else
  246. {
  247. int P = Command.Pos(" ");
  248. if (P)
  249. {
  250. Program = Command.SubString(1, P).Trim();
  251. Params = Command.SubString(P + 1, Command.Length() - P).Trim();
  252. }
  253. else
  254. {
  255. Program = Command;
  256. }
  257. }
  258. int B = Program.LastDelimiter("\\/");
  259. if (B)
  260. {
  261. Dir = Program.SubString(1, B).Trim();
  262. }
  263. }
  264. //---------------------------------------------------------------------------
  265. AnsiString __fastcall FormatCommand(AnsiString Program, AnsiString Params)
  266. {
  267. Program = Program.Trim();
  268. Params = Params.Trim();
  269. if (!Params.IsEmpty()) Params = " " + Params;
  270. if (Program.Pos(" ")) Program = "\"" + Program + "\"";
  271. return Program + Params;
  272. }
  273. //---------------------------------------------------------------------------
  274. bool __fastcall IsDisplayableStr(const AnsiString Str)
  275. {
  276. bool Displayable = true;
  277. int Index = 1;
  278. while ((Index <= Str.Length()) && Displayable)
  279. {
  280. if (Str[Index] < '\32')
  281. {
  282. Displayable = false;
  283. }
  284. Index++;
  285. }
  286. return Displayable;
  287. }
  288. //---------------------------------------------------------------------------
  289. AnsiString __fastcall StrToHex(const AnsiString Str)
  290. {
  291. AnsiString Result;
  292. for (int i = 1; i <= Str.Length(); i++)
  293. {
  294. Result += IntToHex(Str[i], 2);
  295. }
  296. return Result;
  297. }
  298. //---------------------------------------------------------------------------
  299. AnsiString __fastcall HexToStr(const AnsiString Hex)
  300. {
  301. static AnsiString Digits = "0123456789ABCDEF";
  302. AnsiString Result;
  303. int L, P1, P2;
  304. L = Hex.Length();
  305. if (L % 2 == 0)
  306. {
  307. for (int i = 1; i <= Hex.Length(); i += 2)
  308. {
  309. P1 = Digits.Pos(Hex[i]);
  310. P2 = Digits.Pos(Hex[i + 1]);
  311. if (P1 <= 0 || P2 <= 0)
  312. {
  313. break;
  314. }
  315. else
  316. {
  317. Result += static_cast<char>((P1 - 1) * 16 + P2 - 1);
  318. }
  319. }
  320. }
  321. return Result;
  322. }
  323. //---------------------------------------------------------------------------
  324. bool __fastcall FileSearchRec(const AnsiString FileName, TSearchRec & Rec)
  325. {
  326. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  327. bool Result = (FindFirst(FileName, FindAttrs, Rec) == 0);
  328. if (Result)
  329. {
  330. FindClose(Rec);
  331. }
  332. return Result;
  333. }
  334. //---------------------------------------------------------------------------
  335. void __fastcall ProcessLocalDirectory(AnsiString DirName,
  336. TProcessLocalFileEvent CallBackFunc, void * Param,
  337. int FindAttrs)
  338. {
  339. assert(CallBackFunc);
  340. if (FindAttrs < 0)
  341. {
  342. FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  343. }
  344. TSearchRec SearchRec;
  345. DirName = IncludeTrailingBackslash(DirName);
  346. if (FindFirst(DirName + "*.*", FindAttrs, SearchRec) == 0)
  347. {
  348. try
  349. {
  350. do
  351. {
  352. if ((SearchRec.Name != ".") && (SearchRec.Name != ".."))
  353. {
  354. CallBackFunc(DirName + SearchRec.Name, SearchRec, Param);
  355. }
  356. } while (FindNext(SearchRec) == 0);
  357. }
  358. __finally
  359. {
  360. FindClose(SearchRec);
  361. }
  362. }
  363. }
  364. //---------------------------------------------------------------------------
  365. struct TDateTimeParams
  366. {
  367. TDateTime UnixEpoch;
  368. double BaseDifference;
  369. long BaseDifferenceSec;
  370. double CurrentDaylightDifference;
  371. long CurrentDaylightDifferenceSec;
  372. double CurrentDifference;
  373. long CurrentDifferenceSec;
  374. double StandardDifference;
  375. long StandardDifferenceSec;
  376. double DaylightDifference;
  377. long DaylightDifferenceSec;
  378. SYSTEMTIME StandardDate;
  379. SYSTEMTIME DaylightDate;
  380. };
  381. static bool DateTimeParamsInitialized = false;
  382. static TDateTimeParams DateTimeParams;
  383. static TCriticalSection DateTimeParamsSection;
  384. //---------------------------------------------------------------------------
  385. static TDateTimeParams * __fastcall GetDateTimeParams()
  386. {
  387. if (!DateTimeParamsInitialized)
  388. {
  389. TGuard Guard(&DateTimeParamsSection);
  390. if (!DateTimeParamsInitialized)
  391. {
  392. TIME_ZONE_INFORMATION TZI;
  393. unsigned long GTZI;
  394. GTZI = GetTimeZoneInformation(&TZI);
  395. switch (GTZI)
  396. {
  397. case TIME_ZONE_ID_UNKNOWN:
  398. DateTimeParams.CurrentDifferenceSec = 0;
  399. DateTimeParams.CurrentDaylightDifferenceSec = 0;
  400. break;
  401. case TIME_ZONE_ID_STANDARD:
  402. DateTimeParams.CurrentDaylightDifferenceSec = TZI.StandardBias;
  403. break;
  404. case TIME_ZONE_ID_DAYLIGHT:
  405. DateTimeParams.CurrentDaylightDifferenceSec = TZI.DaylightBias;
  406. break;
  407. case TIME_ZONE_ID_INVALID:
  408. default:
  409. throw Exception(TIMEZONE_ERROR);
  410. }
  411. // Is it same as SysUtils::UnixDateDelta = 25569 ??
  412. DateTimeParams.UnixEpoch = EncodeDate(1970, 1, 1);
  413. DateTimeParams.BaseDifferenceSec = TZI.Bias;
  414. DateTimeParams.BaseDifference = double(TZI.Bias) / 1440;
  415. DateTimeParams.BaseDifferenceSec *= 60;
  416. DateTimeParams.CurrentDifferenceSec = TZI.Bias +
  417. DateTimeParams.CurrentDaylightDifferenceSec;
  418. DateTimeParams.CurrentDifference =
  419. double(DateTimeParams.CurrentDifferenceSec) / 1440;
  420. DateTimeParams.CurrentDifferenceSec *= 60;
  421. DateTimeParams.CurrentDaylightDifference =
  422. double(DateTimeParams.CurrentDaylightDifferenceSec) / 1440;
  423. DateTimeParams.CurrentDaylightDifferenceSec *= 60;
  424. DateTimeParams.DaylightDifferenceSec = TZI.DaylightBias * 60;
  425. DateTimeParams.DaylightDifference = double(TZI.DaylightBias) / 1440;
  426. DateTimeParams.StandardDifferenceSec = TZI.StandardBias * 60;
  427. DateTimeParams.StandardDifference = double(TZI.StandardBias) / 1440;
  428. DateTimeParams.StandardDate = TZI.StandardDate;
  429. DateTimeParams.DaylightDate = TZI.DaylightDate;
  430. DateTimeParamsInitialized = true;
  431. }
  432. }
  433. return &DateTimeParams;
  434. }
  435. //---------------------------------------------------------------------------
  436. static void __fastcall EncodeDSTMargin(const SYSTEMTIME & Date, unsigned short Year,
  437. TDateTime & Result)
  438. {
  439. if (Date.wYear == 0)
  440. {
  441. TDateTime Temp = EncodeDate(Year, Date.wMonth, 1);
  442. Result = Temp + ((Date.wDayOfWeek - DayOfWeek(Temp) + 8) % 7) +
  443. (7 * (Date.wDay - 1));
  444. if (Date.wDay == 5)
  445. {
  446. unsigned short Month = static_cast<unsigned short>(Date.wMonth + 1);
  447. if (Month > 12)
  448. {
  449. Month = static_cast<unsigned short>(Month - 12);
  450. Year++;
  451. }
  452. if (Result > EncodeDate(Year, Month, 1))
  453. {
  454. Result -= 7;
  455. }
  456. }
  457. Result += EncodeTime(Date.wHour, Date.wMinute, Date.wSecond,
  458. Date.wMilliseconds);
  459. }
  460. else
  461. {
  462. Result = EncodeDate(Year, Date.wMonth, Date.wDay) +
  463. EncodeTime(Date.wHour, Date.wMinute, Date.wSecond, Date.wMilliseconds);
  464. }
  465. }
  466. //---------------------------------------------------------------------------
  467. static bool __fastcall IsDateInDST(const TDateTime & DateTime)
  468. {
  469. struct TDSTCache
  470. {
  471. bool Filled;
  472. unsigned short Year;
  473. TDateTime StandardDate;
  474. TDateTime DaylightDate;
  475. };
  476. static TDSTCache DSTCache[10];
  477. static int DSTCacheCount = 0;
  478. static TCriticalSection Section;
  479. TDateTimeParams * Params = GetDateTimeParams();
  480. bool Result;
  481. if (Params->StandardDate.wMonth == 0)
  482. {
  483. Result = false;
  484. }
  485. else
  486. {
  487. unsigned short Year, Month, Day;
  488. DecodeDate(DateTime, Year, Month, Day);
  489. TDSTCache * CurrentCache = &DSTCache[0];
  490. int CacheIndex = 0;
  491. while ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  492. CurrentCache->Filled && (CurrentCache->Year != Year))
  493. {
  494. CacheIndex++;
  495. CurrentCache++;
  496. }
  497. if ((CacheIndex < DSTCacheCount) && (CacheIndex < LENOF(DSTCache)) &&
  498. CurrentCache->Filled)
  499. {
  500. assert(CurrentCache->Year == Year);
  501. Result = (DateTime >= CurrentCache->DaylightDate) &&
  502. (DateTime < CurrentCache->StandardDate);
  503. }
  504. else
  505. {
  506. TDSTCache NewCache;
  507. EncodeDSTMargin(Params->StandardDate, Year, NewCache.StandardDate);
  508. EncodeDSTMargin(Params->DaylightDate, Year, NewCache.DaylightDate);
  509. AnsiString SD = FormatDateTime("dddddd tt", NewCache.StandardDate);
  510. AnsiString DD = FormatDateTime("dddddd tt", NewCache.DaylightDate);
  511. if (DSTCacheCount < LENOF(DSTCache))
  512. {
  513. TGuard Guard(&Section);
  514. if (DSTCacheCount < LENOF(DSTCache))
  515. {
  516. NewCache.Year = Year;
  517. DSTCache[DSTCacheCount] = NewCache;
  518. DSTCache[DSTCacheCount].Filled = true;
  519. DSTCacheCount++;
  520. }
  521. }
  522. Result = (DateTime >= NewCache.DaylightDate) &&
  523. (DateTime < NewCache.StandardDate);
  524. }
  525. }
  526. return Result;
  527. }
  528. //---------------------------------------------------------------------------
  529. TDateTime __fastcall UnixToDateTime(unsigned long TimeStamp, bool ConsiderDST)
  530. {
  531. TDateTimeParams * Params = GetDateTimeParams();
  532. TDateTime Result;
  533. Result = Params->UnixEpoch + (double(TimeStamp) / 86400) - Params->CurrentDifference;
  534. if (ConsiderDST)
  535. {
  536. Result -= (IsDateInDST(Result) ?
  537. Params->DaylightDifference : Params->StandardDifference);
  538. }
  539. return Result;
  540. }
  541. //---------------------------------------------------------------------------
  542. inline __int64 __fastcall Round(double Number)
  543. {
  544. double Floor = floor(Number);
  545. double Ceil = ceil(Number);
  546. return ((Number - Floor) > (Ceil - Number)) ? Ceil : Floor;
  547. }
  548. //---------------------------------------------------------------------------
  549. FILETIME __fastcall DateTimeToFileTime(const TDateTime DateTime,
  550. bool /*ConsiderDST*/)
  551. {
  552. TDateTimeParams * Params = GetDateTimeParams();
  553. __int64 UnixTimeStamp;
  554. FILETIME Result;
  555. UnixTimeStamp = Round(double(DateTime - Params->UnixEpoch) * 86400) +
  556. Params->CurrentDifferenceSec;
  557. TIME_POSIX_TO_WIN(UnixTimeStamp, Result);
  558. return Result;
  559. }
  560. //---------------------------------------------------------------------------
  561. unsigned long __fastcall ConvertTimestampToUnix(const FILETIME & FileTime,
  562. bool ConsiderDST)
  563. {
  564. unsigned long Result;
  565. TIME_WIN_TO_POSIX(FileTime, Result);
  566. if (ConsiderDST)
  567. {
  568. FILETIME LocalFileTime;
  569. SYSTEMTIME SystemTime;
  570. TDateTime DateTime;
  571. FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
  572. FileTimeToSystemTime(&LocalFileTime, &SystemTime);
  573. DateTime = SystemTimeToDateTime(SystemTime);
  574. TDateTimeParams * Params = GetDateTimeParams();
  575. Result += (IsDateInDST(DateTime) ?
  576. Params->DaylightDifferenceSec : Params->StandardDifferenceSec);
  577. }
  578. return Result;
  579. }
  580. //---------------------------------------------------------------------------
  581. TDateTime __fastcall AdjustDateTimeFromUnix(TDateTime DateTime, bool ConsiderDST)
  582. {
  583. TDateTimeParams * Params = GetDateTimeParams();
  584. DateTime = DateTime - Params->CurrentDaylightDifference;
  585. bool IsInDST = IsDateInDST(DateTime);
  586. // shift always, even with ConsiderDST == false
  587. DateTime = DateTime - (!IsInDST ? Params->DaylightDifference :
  588. Params->StandardDifference);
  589. if (ConsiderDST)
  590. {
  591. if (IsInDST)
  592. {
  593. //DateTime = DateTime - Params->DaylightDifference;
  594. }
  595. else
  596. {
  597. DateTime = DateTime + Params->DaylightDifference;
  598. }
  599. }
  600. return DateTime;
  601. }
  602. //---------------------------------------------------------------------------
  603. __inline static bool __fastcall UnifySignificance(unsigned short & V1,
  604. unsigned short & V2)
  605. {
  606. bool Result = (V1 == 0) || (V2 == 0);
  607. if (Result)
  608. {
  609. V1 = 0;
  610. V2 = 0;
  611. }
  612. return Result;
  613. }
  614. //---------------------------------------------------------------------------
  615. void __fastcall UnifyDateTimePrecision(TDateTime & DateTime1, TDateTime & DateTime2)
  616. {
  617. unsigned short Y1, M1, D1, H1, N1, S1, MS1;
  618. unsigned short Y2, M2, D2, H2, N2, S2, MS2;
  619. bool Changed;
  620. if (DateTime1 != DateTime2)
  621. {
  622. DateTime1.DecodeDate(&Y1, &M1, &D1);
  623. DateTime1.DecodeTime(&H1, &N1, &S1, &MS1);
  624. DateTime2.DecodeDate(&Y2, &M2, &D2);
  625. DateTime2.DecodeTime(&H2, &N2, &S2, &MS2);
  626. Changed = UnifySignificance(MS1, MS2);
  627. if (Changed && UnifySignificance(S1, S2) && UnifySignificance(N1, N2) &&
  628. UnifySignificance(H1, H2) && UnifySignificance(D1, D2) &&
  629. UnifySignificance(M1, M2))
  630. {
  631. UnifySignificance(Y1, Y2);
  632. }
  633. if (Changed)
  634. {
  635. DateTime1 = EncodeDate(Y1, M1, D1) + EncodeTime(H1, N1, S1, MS1);
  636. DateTime2 = EncodeDate(Y2, M2, D2) + EncodeTime(H2, N2, S2, MS2);
  637. }
  638. }
  639. }
  640. //---------------------------------------------------------------------------
  641. bool __fastcall RecursiveDeleteFile(const AnsiString FileName, bool ToRecycleBin)
  642. {
  643. SHFILEOPSTRUCT Data;
  644. memset(&Data, 0, sizeof(Data));
  645. Data.hwnd = NULL;
  646. Data.wFunc = FO_DELETE;
  647. AnsiString FileList(FileName);
  648. FileList.SetLength(FileList.Length() + 2);
  649. FileList[FileList.Length() - 1] = '\0';
  650. FileList[FileList.Length()] = '\0';
  651. Data.pFrom = FileList.c_str();
  652. Data.pTo = "";
  653. Data.fFlags = FOF_NOCONFIRMATION | FOF_RENAMEONCOLLISION | FOF_NOCONFIRMMKDIR |
  654. FOF_NOERRORUI | FOF_SILENT;
  655. if (ToRecycleBin)
  656. {
  657. Data.fFlags |= FOF_ALLOWUNDO;
  658. }
  659. int Result = SHFileOperation(&Data);
  660. return (Result == 0);
  661. }
  662. //---------------------------------------------------------------------------
  663. int __fastcall CancelAnswer(int Answers)
  664. {
  665. int Result;
  666. if ((Answers & qaCancel) != 0)
  667. {
  668. Result = qaCancel;
  669. }
  670. else if ((Answers & qaNo) != 0)
  671. {
  672. Result = qaNo;
  673. }
  674. else if ((Answers & qaAbort) != 0)
  675. {
  676. Result = qaAbort;
  677. }
  678. else if ((Answers & qaOK) != 0)
  679. {
  680. Result = qaOK;
  681. }
  682. else
  683. {
  684. assert(false);
  685. Result = qaCancel;
  686. }
  687. return Result;
  688. }