Queue.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "Common.h"
  5. #include "Terminal.h"
  6. #include "Queue.h"
  7. //---------------------------------------------------------------------------
  8. #pragma package(smart_init)
  9. //---------------------------------------------------------------------------
  10. class TTerminalItem : public TSignalThread
  11. {
  12. friend class TQueueItem;
  13. public:
  14. __fastcall TTerminalItem(TTerminalQueue * Queue);
  15. __fastcall ~TTerminalItem();
  16. void __fastcall Process(TQueueItem * Item);
  17. void __fastcall ProcessUserAction();
  18. void __fastcall Cancel();
  19. protected:
  20. struct TQueryUserRec
  21. {
  22. TObject * Sender;
  23. AnsiString Query;
  24. TStrings * MoreMessages;
  25. int Answers;
  26. int Params;
  27. int Answer;
  28. TQueryType Type;
  29. };
  30. struct TPromptUserRec
  31. {
  32. TSecureShell * SecureShell;
  33. AnsiString Prompt;
  34. TPromptKind Kind;
  35. AnsiString Response;
  36. bool Result;
  37. };
  38. struct TShowExtendedExceptionRec
  39. {
  40. TSecureShell * SecureShell;
  41. Exception * E;
  42. };
  43. bool FMasterPasswordTried;
  44. TTerminalQueue * FQueue;
  45. TTerminal * FTerminal;
  46. TQueueItem * FItem;
  47. TCriticalSection * FCriticalSection;
  48. void * FUserActionParams;
  49. bool FCancel;
  50. virtual void __fastcall ProcessEvent();
  51. virtual void __fastcall Finished();
  52. bool __fastcall WaitForUserAction(TQueueItem::TStatus ItemStatus, void * Params);
  53. void __fastcall TerminalClose(TObject * Sender);
  54. void __fastcall TerminalQueryUser(TObject * Sender,
  55. const AnsiString Query, TStrings * MoreMessages, int Answers,
  56. int Params, int & Answer, TQueryType Type);
  57. void __fastcall TerminalPromptUser(TSecureShell * SecureShell,
  58. AnsiString Prompt, TPromptKind Kind, AnsiString & Response, bool & Result);
  59. void __fastcall TerminalShowExtendedException(TSecureShell * SecureShell,
  60. Exception * E);
  61. void __fastcall OperationFinished(TFileOperation Operation, TOperationSide Side,
  62. bool DragDrop, const AnsiString FileName, bool Success,
  63. bool & DisconnectWhenFinished);
  64. void __fastcall OperationProgress(TFileOperationProgressType & ProgressData,
  65. TCancelStatus & Cancel);
  66. };
  67. //---------------------------------------------------------------------------
  68. typedef int __fastcall (__closure *TDirectoryAffected)
  69. (TTerminal * Terminal, const AnsiString Directory);
  70. //---------------------------------------------------------------------------
  71. class TSecondaryTerminal : public TTerminal
  72. {
  73. public:
  74. __fastcall TSecondaryTerminal(TTerminal * MainTerminal);
  75. __property TDirectoryAffected OnDirectoryAffected = { read = FOnDirectoryAffected,
  76. write = FOnDirectoryAffected };
  77. protected:
  78. virtual void __fastcall DirectoryLoaded(TRemoteFileList * FileList);
  79. virtual void __fastcall DirectoryModified(const AnsiString Path,
  80. bool SubDirs);
  81. private:
  82. TTerminal * FMainTerminal;
  83. TDirectoryAffected FOnDirectoryAffected;
  84. void __fastcall DoDirectoryAffected(const AnsiString Path);
  85. };
  86. //---------------------------------------------------------------------------
  87. // TSignalThread
  88. //---------------------------------------------------------------------------
  89. int __fastcall ThreadProc(void * Thread)
  90. {
  91. TSignalThread * SimpleThread = reinterpret_cast<TSignalThread*>(Thread);
  92. assert(SimpleThread != NULL);
  93. try
  94. {
  95. SimpleThread->Execute();
  96. }
  97. __finally
  98. {
  99. SimpleThread->FFinished = true;
  100. SimpleThread->Finished();
  101. EndThread(0);
  102. }
  103. return 0;
  104. }
  105. //---------------------------------------------------------------------------
  106. __fastcall TSignalThread::TSignalThread() :
  107. FTerminated(true), FFinished(true), FThread(NULL), FEvent(NULL)
  108. {
  109. FEvent = CreateEvent(NULL, false, false, NULL);
  110. assert(FEvent != NULL);
  111. unsigned ThreadID;
  112. FThread = reinterpret_cast<HANDLE>(
  113. BeginThread(NULL, 0, ThreadProc, this, CREATE_SUSPENDED, ThreadID));
  114. ::SetThreadPriority(FThread, THREAD_PRIORITY_BELOW_NORMAL);
  115. }
  116. //---------------------------------------------------------------------------
  117. __fastcall TSignalThread::~TSignalThread()
  118. {
  119. Close();
  120. if (FThread != NULL)
  121. {
  122. CloseHandle(FThread);
  123. }
  124. if (FEvent)
  125. {
  126. CloseHandle(FEvent);
  127. }
  128. }
  129. //---------------------------------------------------------------------------
  130. void __fastcall TSignalThread::Start()
  131. {
  132. FTerminated = false;
  133. if (ResumeThread(FThread) == 1)
  134. {
  135. FFinished = false;
  136. }
  137. }
  138. //---------------------------------------------------------------------------
  139. void __fastcall TSignalThread::Finished()
  140. {
  141. }
  142. //---------------------------------------------------------------------------
  143. void __fastcall TSignalThread::TriggerEvent()
  144. {
  145. SetEvent(FEvent);
  146. }
  147. //---------------------------------------------------------------------------
  148. bool __fastcall TSignalThread::WaitForEvent()
  149. {
  150. return (WaitForSingleObject(FEvent, INFINITE) == WAIT_OBJECT_0) &&
  151. !FTerminated;
  152. }
  153. //---------------------------------------------------------------------------
  154. void __fastcall TSignalThread::Execute()
  155. {
  156. while (!FTerminated)
  157. {
  158. if (WaitForEvent())
  159. {
  160. ProcessEvent();
  161. }
  162. }
  163. }
  164. //---------------------------------------------------------------------------
  165. void __fastcall TSignalThread::Close()
  166. {
  167. if (!FFinished)
  168. {
  169. Terminate();
  170. WaitFor();
  171. }
  172. }
  173. //---------------------------------------------------------------------------
  174. void __fastcall TSignalThread::Terminate()
  175. {
  176. FTerminated = true;
  177. TriggerEvent();
  178. }
  179. //---------------------------------------------------------------------------
  180. void __fastcall TSignalThread::WaitFor()
  181. {
  182. WaitForSingleObject(FThread, INFINITE);
  183. }
  184. //---------------------------------------------------------------------------
  185. // TTerminalQueue
  186. //---------------------------------------------------------------------------
  187. __fastcall TTerminalQueue::TTerminalQueue(TTerminal * Terminal,
  188. TConfiguration * Configuration) :
  189. FTerminal(Terminal), FTransfersLimit(2),
  190. FConfiguration(Configuration), FSessionData(NULL), FItems(NULL),
  191. FTerminals(NULL), FItemsSection(NULL), FFreeTerminals(0),
  192. FItemsInProcess(0), FTemporaryTerminals(0)
  193. {
  194. FOnQueryUser = NULL;
  195. FOnPromptUser = NULL;
  196. FOnShowExtendedException = NULL;
  197. FOnQueueItemUpdate = NULL;
  198. FOnListUpdate = NULL;
  199. assert(Terminal != NULL);
  200. FSessionData = new TSessionData("");
  201. FSessionData->Assign(Terminal->SessionData);
  202. FSessionData->NonPersistant();
  203. FItems = new TList();
  204. FTerminals = new TList();
  205. FItemsSection = new TCriticalSection();
  206. Start();
  207. }
  208. //---------------------------------------------------------------------------
  209. __fastcall TTerminalQueue::~TTerminalQueue()
  210. {
  211. Close();
  212. {
  213. TGuard Guard(FItemsSection);
  214. TTerminalItem * TerminalItem;
  215. while (FTerminals->Count > 0)
  216. {
  217. TerminalItem = reinterpret_cast<TTerminalItem*>(FTerminals->Items[0]);
  218. FTerminals->Delete(0);
  219. TerminalItem->Terminate();
  220. TerminalItem->WaitFor();
  221. delete TerminalItem;
  222. }
  223. delete FTerminals;
  224. for (int Index = 0; Index < FItems->Count; Index++)
  225. {
  226. delete GetItem(Index);
  227. }
  228. }
  229. delete FItemsSection;
  230. }
  231. //---------------------------------------------------------------------------
  232. void __fastcall TTerminalQueue::TerminalFinished(TTerminalItem * TerminalItem)
  233. {
  234. if (!FTerminated)
  235. {
  236. {
  237. TGuard Guard(FItemsSection);
  238. int Index = FTerminals->IndexOf(TerminalItem);
  239. assert(Index >= 0);
  240. if (Index < FFreeTerminals)
  241. {
  242. FFreeTerminals--;
  243. }
  244. if (Index >= FTransfersLimit)
  245. {
  246. assert(FTemporaryTerminals > 0);
  247. FTemporaryTerminals--;
  248. }
  249. FTerminals->Extract(TerminalItem);
  250. delete TerminalItem;
  251. }
  252. TriggerEvent();
  253. }
  254. }
  255. //---------------------------------------------------------------------------
  256. bool __fastcall TTerminalQueue::TerminalFree(TTerminalItem * TerminalItem)
  257. {
  258. bool Result = true;
  259. if (!FTerminated)
  260. {
  261. {
  262. TGuard Guard(FItemsSection);
  263. int Index = FTerminals->IndexOf(TerminalItem);
  264. assert(Index >= 0);
  265. assert(Index >= FFreeTerminals);
  266. Result = (Index < FTransfersLimit);
  267. if (Result)
  268. {
  269. FTerminals->Move(Index, 0);
  270. FFreeTerminals++;
  271. }
  272. }
  273. TriggerEvent();
  274. }
  275. return Result;
  276. }
  277. //---------------------------------------------------------------------------
  278. void __fastcall TTerminalQueue::AddItem(TQueueItem * Item)
  279. {
  280. assert(!FTerminated);
  281. Item->SetStatus(TQueueItem::qsPending);
  282. {
  283. TGuard Guard(FItemsSection);
  284. FItems->Add(Item);
  285. Item->FQueue = this;
  286. }
  287. DoListUpdate();
  288. TriggerEvent();
  289. }
  290. //---------------------------------------------------------------------------
  291. void __fastcall TTerminalQueue::RetryItem(TQueueItem * Item)
  292. {
  293. if (!FTerminated)
  294. {
  295. {
  296. TGuard Guard(FItemsSection);
  297. int Index = FItems->Remove(Item);
  298. assert(Index < FItemsInProcess);
  299. USEDPARAM(Index);
  300. FItemsInProcess--;
  301. FItems->Add(Item);
  302. }
  303. DoListUpdate();
  304. TriggerEvent();
  305. }
  306. }
  307. //---------------------------------------------------------------------------
  308. void __fastcall TTerminalQueue::DeleteItem(TQueueItem * Item)
  309. {
  310. if (!FTerminated)
  311. {
  312. {
  313. TGuard Guard(FItemsSection);
  314. int Index = FItems->Remove(Item);
  315. assert(Index < FItemsInProcess);
  316. USEDPARAM(Index);
  317. FItemsInProcess--;
  318. delete Item;
  319. }
  320. DoListUpdate();
  321. }
  322. }
  323. //---------------------------------------------------------------------------
  324. TQueueItem * __fastcall TTerminalQueue::GetItem(int Index)
  325. {
  326. return reinterpret_cast<TQueueItem*>(FItems->Items[Index]);
  327. }
  328. //---------------------------------------------------------------------------
  329. TTerminalQueueStatus * __fastcall TTerminalQueue::CreateStatus(TTerminalQueueStatus * Current)
  330. {
  331. TTerminalQueueStatus * Status = new TTerminalQueueStatus();
  332. try
  333. {
  334. try
  335. {
  336. TGuard Guard(FItemsSection);
  337. TQueueItem * Item;
  338. TQueueItemProxy * ItemProxy;
  339. for (int Index = 0; Index < FItems->Count; Index++)
  340. {
  341. Item = GetItem(Index);
  342. if (Current != NULL)
  343. {
  344. ItemProxy = Current->FindByQueueItem(Item);
  345. }
  346. else
  347. {
  348. ItemProxy = NULL;
  349. }
  350. if (ItemProxy != NULL)
  351. {
  352. Current->Delete(ItemProxy);
  353. Status->Add(ItemProxy);
  354. ItemProxy->Update();
  355. }
  356. else
  357. {
  358. Status->Add(new TQueueItemProxy(this, Item));
  359. }
  360. }
  361. }
  362. __finally
  363. {
  364. if (Current != NULL)
  365. {
  366. delete Current;
  367. }
  368. }
  369. }
  370. catch(...)
  371. {
  372. delete Status;
  373. throw;
  374. }
  375. return Status;
  376. }
  377. //---------------------------------------------------------------------------
  378. bool __fastcall TTerminalQueue::ItemGetData(TQueueItem * Item,
  379. TQueueItemProxy * Proxy)
  380. {
  381. TGuard Guard(FItemsSection);
  382. bool Result = (FItems->IndexOf(Item) >= 0);
  383. if (Result)
  384. {
  385. Item->GetData(Proxy);
  386. }
  387. return Result;
  388. }
  389. //---------------------------------------------------------------------------
  390. bool __fastcall TTerminalQueue::ItemProcessUserAction(TQueueItem * Item)
  391. {
  392. bool Result;
  393. TTerminalItem * TerminalItem;
  394. {
  395. TGuard Guard(FItemsSection);
  396. Result = (FItems->IndexOf(Item) >= 0) &&
  397. TQueueItem::IsUserActionStatus(Item->Status);
  398. if (Result)
  399. {
  400. TerminalItem = Item->FTerminalItem;
  401. }
  402. }
  403. if (Result)
  404. {
  405. TerminalItem->ProcessUserAction();
  406. }
  407. return Result;
  408. }
  409. //---------------------------------------------------------------------------
  410. bool __fastcall TTerminalQueue::ItemMove(TQueueItem * Item, TQueueItem * BeforeItem)
  411. {
  412. bool Result;
  413. {
  414. TGuard Guard(FItemsSection);
  415. int Index = FItems->IndexOf(Item);
  416. int IndexDest = FItems->IndexOf(BeforeItem);
  417. Result = (Index >= 0) && (IndexDest >= 0) &&
  418. (Item->GetStatus() == TQueueItem::qsPending) &&
  419. (BeforeItem->GetStatus() == TQueueItem::qsPending);
  420. if (Result)
  421. {
  422. FItems->Move(Index, IndexDest);
  423. }
  424. }
  425. if (Result)
  426. {
  427. DoListUpdate();
  428. TriggerEvent();
  429. }
  430. return Result;
  431. }
  432. //---------------------------------------------------------------------------
  433. bool __fastcall TTerminalQueue::ItemExecuteNow(TQueueItem * Item)
  434. {
  435. bool Result;
  436. {
  437. TGuard Guard(FItemsSection);
  438. int Index = FItems->IndexOf(Item);
  439. Result = (Index >= 0) && (Item->GetStatus() == TQueueItem::qsPending);
  440. if (Result)
  441. {
  442. if (Index != FItemsInProcess)
  443. {
  444. assert(Index > FItemsInProcess);
  445. FItems->Move(Index, FItemsInProcess);
  446. }
  447. if (FTerminals->Count >= FTransfersLimit)
  448. {
  449. FTemporaryTerminals++;
  450. }
  451. }
  452. }
  453. if (Result)
  454. {
  455. DoListUpdate();
  456. TriggerEvent();
  457. }
  458. return Result;
  459. }
  460. //---------------------------------------------------------------------------
  461. bool __fastcall TTerminalQueue::ItemDelete(TQueueItem * Item)
  462. {
  463. bool Result;
  464. bool UpdateList = false;
  465. {
  466. TGuard Guard(FItemsSection);
  467. int Index = FItems->IndexOf(Item);
  468. Result = (Index >= 0);
  469. if (Result)
  470. {
  471. if (Item->Status == TQueueItem::qsPending)
  472. {
  473. FItems->Delete(Index);
  474. UpdateList = true;
  475. }
  476. else
  477. {
  478. Item->FTerminalItem->Cancel();
  479. }
  480. }
  481. }
  482. if (UpdateList)
  483. {
  484. DoListUpdate();
  485. TriggerEvent();
  486. }
  487. return Result;
  488. }
  489. //---------------------------------------------------------------------------
  490. void __fastcall TTerminalQueue::ProcessEvent()
  491. {
  492. TTerminalItem * TerminalItem;
  493. TQueueItem * Item;
  494. do
  495. {
  496. TerminalItem = NULL;
  497. Item = NULL;
  498. if (FItems->Count > FItemsInProcess)
  499. {
  500. TGuard Guard(FItemsSection);
  501. if ((FFreeTerminals == 0) &&
  502. (FTerminals->Count < FTransfersLimit + FTemporaryTerminals))
  503. {
  504. TerminalItem = new TTerminalItem(this);
  505. FTerminals->Add(TerminalItem);
  506. }
  507. else if (FFreeTerminals > 0)
  508. {
  509. TerminalItem = reinterpret_cast<TTerminalItem*>(FTerminals->Items[0]);
  510. FTerminals->Move(0, FTerminals->Count - 1);
  511. FFreeTerminals--;
  512. }
  513. if (TerminalItem != NULL)
  514. {
  515. Item = GetItem(FItemsInProcess);
  516. FItemsInProcess++;
  517. }
  518. }
  519. if (TerminalItem != NULL)
  520. {
  521. TerminalItem->Process(Item);
  522. }
  523. }
  524. while (!FTerminated && (TerminalItem != NULL));
  525. }
  526. //---------------------------------------------------------------------------
  527. void __fastcall TTerminalQueue::DoQueueItemUpdate(TQueueItem * Item)
  528. {
  529. if (OnQueueItemUpdate != NULL)
  530. {
  531. OnQueueItemUpdate(this, Item);
  532. }
  533. }
  534. //---------------------------------------------------------------------------
  535. void __fastcall TTerminalQueue::DoListUpdate()
  536. {
  537. if (OnListUpdate != NULL)
  538. {
  539. OnListUpdate(this);
  540. }
  541. }
  542. //---------------------------------------------------------------------------
  543. void __fastcall TTerminalQueue::DoQueryUser(TObject * Sender,
  544. const AnsiString Query, TStrings * MoreMessages, int Answers, int Params,
  545. int & Answer, TQueryType Type)
  546. {
  547. if (OnQueryUser != NULL)
  548. {
  549. OnQueryUser(Sender, Query, MoreMessages, Answers, Params, Answer, Type);
  550. }
  551. }
  552. //---------------------------------------------------------------------------
  553. void __fastcall TTerminalQueue::DoPromptUser(TSecureShell * SecureShell,
  554. AnsiString Prompt, TPromptKind Kind, AnsiString & Response, bool & Result)
  555. {
  556. if (OnPromptUser != NULL)
  557. {
  558. OnPromptUser(SecureShell, Prompt, Kind, Response, Result);
  559. }
  560. }
  561. //---------------------------------------------------------------------------
  562. void __fastcall TTerminalQueue::DoShowExtendedException(
  563. TSecureShell * SecureShell, Exception * E)
  564. {
  565. if (OnShowExtendedException != NULL)
  566. {
  567. OnShowExtendedException(SecureShell, E);
  568. }
  569. }
  570. //---------------------------------------------------------------------------
  571. void __fastcall TTerminalQueue::SetTransfersLimit(int value)
  572. {
  573. if (FTransfersLimit != value)
  574. {
  575. {
  576. TGuard Guard(FItemsSection);
  577. if (value < FItemsInProcess)
  578. {
  579. FTemporaryTerminals = (FItemsInProcess - value);
  580. }
  581. else
  582. {
  583. FTemporaryTerminals = 0;
  584. }
  585. FTransfersLimit = value;
  586. }
  587. TriggerEvent();
  588. }
  589. }
  590. //---------------------------------------------------------------------------
  591. bool __fastcall TTerminalQueue::GetIsEmpty()
  592. {
  593. TGuard Guard(FItemsSection);
  594. return (FItems->Count == 0);
  595. }
  596. //---------------------------------------------------------------------------
  597. // TSecondaryTerminal
  598. //---------------------------------------------------------------------------
  599. __fastcall TSecondaryTerminal::TSecondaryTerminal(TTerminal * MainTerminal) :
  600. TTerminal(), FMainTerminal(MainTerminal)
  601. {
  602. assert(FMainTerminal != NULL);
  603. OnDirectoryAffected = NULL;
  604. UseBusyCursor = false;
  605. }
  606. //---------------------------------------------------------------------------
  607. void __fastcall TSecondaryTerminal::DirectoryLoaded(TRemoteFileList * FileList)
  608. {
  609. FMainTerminal->DirectoryLoaded(FileList);
  610. assert(FileList != NULL);
  611. }
  612. //---------------------------------------------------------------------------
  613. void __fastcall TSecondaryTerminal::DirectoryModified(const AnsiString Path,
  614. bool SubDirs)
  615. {
  616. // clear cache of main terminal
  617. FMainTerminal->DirectoryModified(Path, SubDirs);
  618. }
  619. //---------------------------------------------------------------------------
  620. // TTerminalItem
  621. //---------------------------------------------------------------------------
  622. __fastcall TTerminalItem::TTerminalItem(TTerminalQueue * Queue) :
  623. TSignalThread(), FQueue(Queue), FTerminal(NULL), FItem(NULL),
  624. FCriticalSection(NULL), FUserActionParams(NULL)
  625. {
  626. FCriticalSection = new TCriticalSection();
  627. FTerminal = new TSecondaryTerminal(FQueue->FTerminal);
  628. try
  629. {
  630. FTerminal->Configuration = Queue->FConfiguration;
  631. FTerminal->SessionData = Queue->FSessionData;
  632. FTerminal->OnClose = TerminalClose;
  633. FTerminal->OnQueryUser = TerminalQueryUser;
  634. FTerminal->OnPromptUser = TerminalPromptUser;
  635. FTerminal->OnShowExtendedException = TerminalShowExtendedException;
  636. FTerminal->OnProgress = OperationProgress;
  637. FTerminal->OnFinished = OperationFinished;
  638. }
  639. catch(...)
  640. {
  641. delete FTerminal;
  642. throw;
  643. }
  644. Start();
  645. }
  646. //---------------------------------------------------------------------------
  647. __fastcall TTerminalItem::~TTerminalItem()
  648. {
  649. Close();
  650. assert(FItem == NULL);
  651. delete FTerminal;
  652. delete FCriticalSection;
  653. }
  654. //---------------------------------------------------------------------------
  655. void __fastcall TTerminalItem::Process(TQueueItem * Item)
  656. {
  657. {
  658. TGuard Guard(FCriticalSection);
  659. assert(FItem == NULL);
  660. FItem = Item;
  661. }
  662. TriggerEvent();
  663. }
  664. //---------------------------------------------------------------------------
  665. void __fastcall TTerminalItem::ProcessEvent()
  666. {
  667. TGuard Guard(FCriticalSection);
  668. bool Retry = true;
  669. FCancel = false;
  670. FItem->FTerminalItem = this;
  671. try
  672. {
  673. assert(FItem != NULL);
  674. if (!FTerminal->Active)
  675. {
  676. FItem->SetStatus(TQueueItem::qsConnecting);
  677. FMasterPasswordTried = false;
  678. FTerminal->SessionData->RemoteDirectory = FItem->StartupDirectory();
  679. FTerminal->Open();
  680. FTerminal->DoStartup();
  681. }
  682. Retry = false;
  683. if (!FCancel)
  684. {
  685. FItem->SetStatus(TQueueItem::qsProcessing);
  686. FItem->Execute(this);
  687. }
  688. }
  689. catch(Exception & E)
  690. {
  691. FTerminal->DoShowExtendedException(&E);
  692. }
  693. FItem->SetStatus(TQueueItem::qsDone);
  694. FItem->FTerminalItem = NULL;
  695. TQueueItem * Item = FItem;
  696. FItem = NULL;
  697. if (Retry && !FCancel)
  698. {
  699. FQueue->RetryItem(Item);
  700. }
  701. else
  702. {
  703. FQueue->DeleteItem(Item);
  704. }
  705. if (!FTerminal->Active ||
  706. !FQueue->TerminalFree(this))
  707. {
  708. Terminate();
  709. }
  710. }
  711. //---------------------------------------------------------------------------
  712. void __fastcall TTerminalItem::Cancel()
  713. {
  714. FCancel = true;
  715. }
  716. //---------------------------------------------------------------------------
  717. void __fastcall TTerminalItem::ProcessUserAction()
  718. {
  719. assert(FItem != NULL);
  720. assert(FUserActionParams != NULL);
  721. if (FItem->GetStatus() == TQueueItem::qsQuery)
  722. {
  723. TQueryUserRec * Params;
  724. Params = reinterpret_cast<TQueryUserRec *>(FUserActionParams);
  725. FQueue->DoQueryUser(Params->Sender, Params->Query, Params->MoreMessages,
  726. Params->Answers, Params->Params, Params->Answer, Params->Type);
  727. }
  728. else if (FItem->GetStatus() == TQueueItem::qsPrompt)
  729. {
  730. TPromptUserRec * Params;
  731. Params = reinterpret_cast<TPromptUserRec *>(FUserActionParams);
  732. FQueue->DoPromptUser(Params->SecureShell, Params->Prompt,
  733. Params->Kind, Params->Response, Params->Result);
  734. }
  735. else if (FItem->GetStatus() == TQueueItem::qsError)
  736. {
  737. TShowExtendedExceptionRec * Params;
  738. Params = reinterpret_cast<TShowExtendedExceptionRec *>(FUserActionParams);
  739. FQueue->DoShowExtendedException(Params->SecureShell, Params->E);
  740. }
  741. else
  742. {
  743. assert(false);
  744. }
  745. TriggerEvent();
  746. }
  747. //---------------------------------------------------------------------------
  748. bool __fastcall TTerminalItem::WaitForUserAction(
  749. TQueueItem::TStatus ItemStatus, void * Params)
  750. {
  751. assert(FItem != NULL);
  752. assert((FItem->GetStatus() == TQueueItem::qsProcessing) ||
  753. (FItem->GetStatus() == TQueueItem::qsConnecting));
  754. bool Result;
  755. TQueueItem::TStatus PrevStatus = FItem->GetStatus();
  756. try
  757. {
  758. FUserActionParams = Params;
  759. FItem->SetStatus(ItemStatus);
  760. Result = !FTerminated && WaitForEvent() && !FCancel;
  761. }
  762. __finally
  763. {
  764. FUserActionParams = NULL;
  765. FItem->SetStatus(PrevStatus);
  766. }
  767. return Result;
  768. }
  769. //---------------------------------------------------------------------------
  770. void __fastcall TTerminalItem::Finished()
  771. {
  772. TSignalThread::Finished();
  773. FQueue->TerminalFinished(this);
  774. }
  775. //---------------------------------------------------------------------------
  776. void __fastcall TTerminalItem::TerminalClose(TObject * /*Sender*/)
  777. {
  778. // nothing
  779. }
  780. //---------------------------------------------------------------------------
  781. void __fastcall TTerminalItem::TerminalQueryUser(TObject * Sender,
  782. const AnsiString Query, TStrings * MoreMessages, int Answers,
  783. int Params, int & Answer, TQueryType Type)
  784. {
  785. TQueryUserRec QueryUserRec;
  786. QueryUserRec.Sender = Sender;
  787. QueryUserRec.Query = Query;
  788. QueryUserRec.MoreMessages = MoreMessages;
  789. QueryUserRec.Answers = Answers;
  790. QueryUserRec.Params = Params;
  791. QueryUserRec.Answer = Answer;
  792. QueryUserRec.Type = Type;
  793. if (WaitForUserAction(TQueueItem::qsQuery, &QueryUserRec))
  794. {
  795. Answer = QueryUserRec.Answer;
  796. }
  797. }
  798. //---------------------------------------------------------------------------
  799. void __fastcall TTerminalItem::TerminalPromptUser(TSecureShell * SecureShell,
  800. AnsiString Prompt, TPromptKind Kind, AnsiString & Response, bool & Result)
  801. {
  802. Result = false;
  803. if (!FMasterPasswordTried)
  804. {
  805. // let's expect that the main session is already authenticated and its password
  806. // is not written after, so no locking is necessary
  807. Response = FQueue->FTerminal->Password;
  808. if (!Response.IsEmpty())
  809. {
  810. Result = true;
  811. }
  812. FMasterPasswordTried = true;
  813. }
  814. if (!Result)
  815. {
  816. TPromptUserRec PromptUserRec;
  817. PromptUserRec.SecureShell = SecureShell;
  818. PromptUserRec.Prompt = Prompt;
  819. PromptUserRec.Kind = Kind;
  820. PromptUserRec.Response = Response;
  821. PromptUserRec.Result = Result;
  822. if (WaitForUserAction(TQueueItem::qsPrompt, &PromptUserRec))
  823. {
  824. Response = PromptUserRec.Response;
  825. Result = PromptUserRec.Result;
  826. }
  827. }
  828. }
  829. //---------------------------------------------------------------------------
  830. void __fastcall TTerminalItem::TerminalShowExtendedException(
  831. TSecureShell * SecureShell, Exception * E)
  832. {
  833. if (!E->Message.IsEmpty() &&
  834. (dynamic_cast<EAbort*>(E) == NULL))
  835. {
  836. TShowExtendedExceptionRec ShowExtendedExceptionRec;
  837. ShowExtendedExceptionRec.SecureShell = SecureShell;
  838. ShowExtendedExceptionRec.E = E;
  839. WaitForUserAction(TQueueItem::qsError, &ShowExtendedExceptionRec);
  840. }
  841. }
  842. //---------------------------------------------------------------------------
  843. void __fastcall TTerminalItem::OperationFinished(TFileOperation /*Operation*/,
  844. TOperationSide /*Side*/, bool /*DragDrop*/, const AnsiString /*FileName*/,
  845. bool /*Success*/, bool & /*DisconnectWhenFinished*/)
  846. {
  847. // nothing
  848. }
  849. //---------------------------------------------------------------------------
  850. void __fastcall TTerminalItem::OperationProgress(
  851. TFileOperationProgressType & ProgressData, TCancelStatus & Cancel)
  852. {
  853. if (FTerminated || FCancel)
  854. {
  855. if (ProgressData.TransferingFile)
  856. {
  857. Cancel = csCancelTransfer;
  858. }
  859. else
  860. {
  861. Cancel = csCancel;
  862. }
  863. }
  864. assert(FItem != NULL);
  865. FItem->SetProgress(ProgressData);
  866. }
  867. //---------------------------------------------------------------------------
  868. // TQueueItem
  869. //---------------------------------------------------------------------------
  870. __fastcall TQueueItem::TQueueItem() :
  871. FStatus(qsPending), FTerminalItem(NULL), FSection(NULL), FProgressData(NULL),
  872. FQueue(NULL), FInfo(NULL)
  873. {
  874. FSection = new TCriticalSection();
  875. FInfo = new TInfo();
  876. }
  877. //---------------------------------------------------------------------------
  878. __fastcall TQueueItem::~TQueueItem()
  879. {
  880. delete FSection;
  881. delete FInfo;
  882. }
  883. //---------------------------------------------------------------------------
  884. bool __fastcall TQueueItem::IsUserActionStatus(TStatus Status)
  885. {
  886. return (Status == qsQuery) || (Status == qsError) || (Status == qsPrompt);
  887. }
  888. //---------------------------------------------------------------------------
  889. TQueueItem::TStatus __fastcall TQueueItem::GetStatus()
  890. {
  891. TGuard Guard(FSection);
  892. return FStatus;
  893. }
  894. //---------------------------------------------------------------------------
  895. void __fastcall TQueueItem::SetStatus(TStatus Status)
  896. {
  897. {
  898. TGuard Guard(FSection);
  899. FStatus = Status;
  900. }
  901. assert((FQueue != NULL) || (Status == qsPending));
  902. if (FQueue != NULL)
  903. {
  904. FQueue->DoQueueItemUpdate(this);
  905. }
  906. }
  907. //---------------------------------------------------------------------------
  908. void __fastcall TQueueItem::SetProgress(
  909. const TFileOperationProgressType & ProgressData)
  910. {
  911. {
  912. TGuard Guard(FSection);
  913. assert(FProgressData != NULL);
  914. *FProgressData = ProgressData;
  915. FProgressData->Reset();
  916. }
  917. FQueue->DoQueueItemUpdate(this);
  918. }
  919. //---------------------------------------------------------------------------
  920. void __fastcall TQueueItem::GetData(TQueueItemProxy * Proxy)
  921. {
  922. TGuard Guard(FSection);
  923. assert(Proxy->FProgressData != NULL);
  924. if (FProgressData != NULL)
  925. {
  926. *Proxy->FProgressData = *FProgressData;
  927. }
  928. else
  929. {
  930. Proxy->FProgressData->Clear();
  931. }
  932. *Proxy->FInfo = *FInfo;
  933. Proxy->FStatus = FStatus;
  934. }
  935. //---------------------------------------------------------------------------
  936. void __fastcall TQueueItem::Execute(TTerminalItem * TerminalItem)
  937. {
  938. try
  939. {
  940. {
  941. assert(FProgressData == NULL);
  942. TGuard Guard(FSection);
  943. FProgressData = new TFileOperationProgressType();
  944. }
  945. DoExecute(TerminalItem->FTerminal);
  946. }
  947. __finally
  948. {
  949. {
  950. TGuard Guard(FSection);
  951. delete FProgressData;
  952. FProgressData = NULL;
  953. }
  954. }
  955. }
  956. //---------------------------------------------------------------------------
  957. // TQueueItemProxy
  958. //---------------------------------------------------------------------------
  959. __fastcall TQueueItemProxy::TQueueItemProxy(TTerminalQueue * Queue,
  960. TQueueItem * QueueItem) :
  961. FQueue(Queue), FQueueItem(QueueItem), FProgressData(NULL),
  962. FQueueStatus(NULL), FInfo(NULL), FFlag(false),
  963. FProcessingUserAction(false)
  964. {
  965. FProgressData = new TFileOperationProgressType();
  966. FInfo = new TQueueItem::TInfo();
  967. Update();
  968. }
  969. //---------------------------------------------------------------------------
  970. __fastcall TQueueItemProxy::~TQueueItemProxy()
  971. {
  972. delete FProgressData;
  973. delete FInfo;
  974. }
  975. //---------------------------------------------------------------------------
  976. TFileOperationProgressType * __fastcall TQueueItemProxy::GetProgressData()
  977. {
  978. return (FProgressData->Operation == foNone) ? NULL : FProgressData;
  979. }
  980. //---------------------------------------------------------------------------
  981. bool __fastcall TQueueItemProxy::Update()
  982. {
  983. assert(FQueueItem != NULL);
  984. TQueueItem::TStatus PrevStatus = Status;
  985. bool Result = FQueue->ItemGetData(FQueueItem, this);
  986. if ((FQueueStatus != NULL) && (PrevStatus != Status))
  987. {
  988. FQueueStatus->ResetStats();
  989. }
  990. return Result;
  991. }
  992. //---------------------------------------------------------------------------
  993. bool __fastcall TQueueItemProxy::ExecuteNow()
  994. {
  995. return FQueue->ItemExecuteNow(FQueueItem);
  996. }
  997. //---------------------------------------------------------------------------
  998. bool __fastcall TQueueItemProxy::Move(bool Sooner)
  999. {
  1000. bool Result = false;
  1001. int I = Index;
  1002. if (Sooner)
  1003. {
  1004. if (I > 0)
  1005. {
  1006. Result = Move(FQueueStatus->Items[I - 1]);
  1007. }
  1008. }
  1009. else
  1010. {
  1011. if (I < FQueueStatus->Count - 1)
  1012. {
  1013. Result = FQueueStatus->Items[I + 1]->Move(this);
  1014. }
  1015. }
  1016. return Result;
  1017. }
  1018. //---------------------------------------------------------------------------
  1019. bool __fastcall TQueueItemProxy::Move(TQueueItemProxy * BeforeItem)
  1020. {
  1021. return FQueue->ItemMove(FQueueItem, BeforeItem->FQueueItem);
  1022. }
  1023. //---------------------------------------------------------------------------
  1024. bool __fastcall TQueueItemProxy::Delete()
  1025. {
  1026. return FQueue->ItemDelete(FQueueItem);
  1027. }
  1028. //---------------------------------------------------------------------------
  1029. bool __fastcall TQueueItemProxy::ProcessUserAction()
  1030. {
  1031. assert(FQueueItem != NULL);
  1032. bool Result;
  1033. FProcessingUserAction = true;
  1034. try
  1035. {
  1036. Result = FQueue->ItemProcessUserAction(FQueueItem);
  1037. }
  1038. __finally
  1039. {
  1040. FProcessingUserAction = false;
  1041. }
  1042. return Result;
  1043. }
  1044. //---------------------------------------------------------------------------
  1045. int __fastcall TQueueItemProxy::GetIndex()
  1046. {
  1047. assert(FQueueStatus != NULL);
  1048. int Index = FQueueStatus->FList->IndexOf(this);
  1049. assert(Index >= 0);
  1050. return Index;
  1051. }
  1052. //---------------------------------------------------------------------------
  1053. // TTerminalQueueStatus
  1054. //---------------------------------------------------------------------------
  1055. __fastcall TTerminalQueueStatus::TTerminalQueueStatus() :
  1056. FList(NULL)
  1057. {
  1058. FList = new TList();
  1059. ResetStats();
  1060. }
  1061. //---------------------------------------------------------------------------
  1062. __fastcall TTerminalQueueStatus::~TTerminalQueueStatus()
  1063. {
  1064. for (int Index = 0; Index < FList->Count; Index++)
  1065. {
  1066. delete GetItem(Index);
  1067. }
  1068. delete FList;
  1069. FList = NULL;
  1070. }
  1071. //---------------------------------------------------------------------------
  1072. void __fastcall TTerminalQueueStatus::ResetStats()
  1073. {
  1074. FActiveCount = -1;
  1075. }
  1076. //---------------------------------------------------------------------------
  1077. int __fastcall TTerminalQueueStatus::GetActiveCount()
  1078. {
  1079. if (FActiveCount < 0)
  1080. {
  1081. FActiveCount = 0;
  1082. while ((FActiveCount < FList->Count) &&
  1083. (GetItem(FActiveCount)->Status != TQueueItem::qsPending))
  1084. {
  1085. FActiveCount++;
  1086. }
  1087. }
  1088. return FActiveCount;
  1089. }
  1090. //---------------------------------------------------------------------------
  1091. void __fastcall TTerminalQueueStatus::Add(TQueueItemProxy * ItemProxy)
  1092. {
  1093. ItemProxy->FQueueStatus = this;
  1094. FList->Add(ItemProxy);
  1095. ResetStats();
  1096. }
  1097. //---------------------------------------------------------------------------
  1098. void __fastcall TTerminalQueueStatus::Delete(TQueueItemProxy * ItemProxy)
  1099. {
  1100. FList->Extract(ItemProxy);
  1101. ItemProxy->FQueueStatus = NULL;
  1102. ResetStats();
  1103. }
  1104. //---------------------------------------------------------------------------
  1105. int __fastcall TTerminalQueueStatus::GetCount()
  1106. {
  1107. return FList->Count;
  1108. }
  1109. //---------------------------------------------------------------------------
  1110. TQueueItemProxy * __fastcall TTerminalQueueStatus::GetItem(int Index)
  1111. {
  1112. return reinterpret_cast<TQueueItemProxy *>(FList->Items[Index]);
  1113. }
  1114. //---------------------------------------------------------------------------
  1115. TQueueItemProxy * __fastcall TTerminalQueueStatus::FindByQueueItem(
  1116. TQueueItem * QueueItem)
  1117. {
  1118. TQueueItemProxy * Item;
  1119. for (int Index = 0; Index < FList->Count; Index++)
  1120. {
  1121. Item = GetItem(Index);
  1122. if (Item->FQueueItem == QueueItem)
  1123. {
  1124. return Item;
  1125. }
  1126. }
  1127. return NULL;
  1128. }
  1129. //---------------------------------------------------------------------------
  1130. // TLocatedQueueItem
  1131. //---------------------------------------------------------------------------
  1132. __fastcall TLocatedQueueItem::TLocatedQueueItem(TTerminal * Terminal) :
  1133. TQueueItem()
  1134. {
  1135. assert(Terminal != NULL);
  1136. FCurrentDir = Terminal->CurrentDirectory;
  1137. }
  1138. //---------------------------------------------------------------------------
  1139. AnsiString __fastcall TLocatedQueueItem::StartupDirectory()
  1140. {
  1141. return FCurrentDir;
  1142. }
  1143. //---------------------------------------------------------------------------
  1144. void __fastcall TLocatedQueueItem::DoExecute(TTerminal * Terminal)
  1145. {
  1146. assert(Terminal != NULL);
  1147. Terminal->CurrentDirectory = FCurrentDir;
  1148. }
  1149. //---------------------------------------------------------------------------
  1150. // TTransferQueueItem
  1151. //---------------------------------------------------------------------------
  1152. __fastcall TTransferQueueItem::TTransferQueueItem(TTerminal * Terminal,
  1153. TStrings * FilesToCopy, const AnsiString & TargetDir,
  1154. const TCopyParamType * CopyParam, int Params, TOperationSide Side) :
  1155. TLocatedQueueItem(Terminal), FFilesToCopy(NULL), FCopyParam(NULL)
  1156. {
  1157. FInfo->Operation = (Params & cpDelete ? foMove : foCopy);
  1158. FInfo->Side = Side;
  1159. assert(FilesToCopy != NULL);
  1160. FFilesToCopy = new TStringList();
  1161. for (int Index = 0; Index < FilesToCopy->Count; Index++)
  1162. {
  1163. FFilesToCopy->AddObject(FilesToCopy->Strings[Index],
  1164. ((FilesToCopy->Objects[Index] == NULL) || (Side == osLocal)) ? NULL :
  1165. dynamic_cast<TRemoteFile*>(FilesToCopy->Objects[Index])->Duplicate());
  1166. }
  1167. FTargetDir = TargetDir;
  1168. assert(CopyParam != NULL);
  1169. FCopyParam = new TCopyParamType(*CopyParam);
  1170. FParams = Params;
  1171. }
  1172. //---------------------------------------------------------------------------
  1173. __fastcall TTransferQueueItem::~TTransferQueueItem()
  1174. {
  1175. delete FFilesToCopy;
  1176. delete FCopyParam;
  1177. }
  1178. //---------------------------------------------------------------------------
  1179. // TUploadQueueItem
  1180. //---------------------------------------------------------------------------
  1181. __fastcall TUploadQueueItem::TUploadQueueItem(TTerminal * Terminal,
  1182. TStrings * FilesToCopy, const AnsiString & TargetDir,
  1183. const TCopyParamType * CopyParam, int Params) :
  1184. TTransferQueueItem(Terminal, FilesToCopy, TargetDir, CopyParam, Params, osLocal)
  1185. {
  1186. if (FilesToCopy->Count > 1)
  1187. {
  1188. ExtractCommonPath(FilesToCopy, FInfo->Source);
  1189. FInfo->Source = ExcludeTrailingBackslash(FInfo->Source);
  1190. }
  1191. else
  1192. {
  1193. assert(FilesToCopy->Count > 0);
  1194. FInfo->Source = FilesToCopy->Strings[0];
  1195. }
  1196. FInfo->Destination =
  1197. UnixIncludeTrailingBackslash(TargetDir) + CopyParam->FileMask;
  1198. FInfo->ModifiesLocal = ((Params & cpDelete) != 0);
  1199. FInfo->ModifiesRemote = true;
  1200. }
  1201. //---------------------------------------------------------------------------
  1202. void __fastcall TUploadQueueItem::DoExecute(TTerminal * Terminal)
  1203. {
  1204. TTransferQueueItem::DoExecute(Terminal);
  1205. assert(Terminal != NULL);
  1206. Terminal->CopyToRemote(FFilesToCopy, FTargetDir, FCopyParam, FParams);
  1207. }
  1208. //---------------------------------------------------------------------------
  1209. // TDownloadQueueItem
  1210. //---------------------------------------------------------------------------
  1211. __fastcall TDownloadQueueItem::TDownloadQueueItem(TTerminal * Terminal,
  1212. TStrings * FilesToCopy, const AnsiString & TargetDir,
  1213. const TCopyParamType * CopyParam, int Params) :
  1214. TTransferQueueItem(Terminal, FilesToCopy, TargetDir, CopyParam, Params, osRemote)
  1215. {
  1216. if (FilesToCopy->Count > 1)
  1217. {
  1218. if (!UnixExtractCommonPath(FilesToCopy, FInfo->Source))
  1219. {
  1220. FInfo->Source = Terminal->CurrentDirectory;
  1221. }
  1222. FInfo->Source = UnixExcludeTrailingBackslash(FInfo->Source);
  1223. }
  1224. else
  1225. {
  1226. assert(FilesToCopy->Count > 0);
  1227. FInfo->Source = FilesToCopy->Strings[0];
  1228. if (UnixExtractFilePath(FInfo->Source).IsEmpty())
  1229. {
  1230. FInfo->Source = UnixIncludeTrailingBackslash(Terminal->CurrentDirectory) +
  1231. FInfo->Source;
  1232. }
  1233. }
  1234. FInfo->Destination =
  1235. IncludeTrailingBackslash(TargetDir) + CopyParam->FileMask;
  1236. FInfo->ModifiesLocal = true;
  1237. FInfo->ModifiesRemote = ((Params & cpDelete) != 0);
  1238. }
  1239. //---------------------------------------------------------------------------
  1240. void __fastcall TDownloadQueueItem::DoExecute(TTerminal * Terminal)
  1241. {
  1242. TTransferQueueItem::DoExecute(Terminal);
  1243. assert(Terminal != NULL);
  1244. Terminal->CopyToLocal(FFilesToCopy, FTargetDir, FCopyParam, FParams);
  1245. }