MainThread.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. //---------------------------------------------------------------------------
  2. #include "stdafx.h"
  3. #include "MainThread.h"
  4. #define ECS m_CriticalSection.Lock()
  5. #define LCS m_CriticalSection.Unlock()
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CMainThread
  8. CMainThread::CMainThread()
  9. {
  10. m_pTools = NULL;
  11. m_nInternalMessageID = 0;
  12. m_pPostKeepAliveCommand = 0;
  13. m_nTimerID = 0;
  14. m_pControlSocket = NULL;
  15. m_bBusy = FALSE;
  16. m_bConnected = FALSE;
  17. m_pWorkingDir = 0;
  18. m_nAsyncRequestID = 0;
  19. m_bQuit = FALSE;
  20. m_hThread = 0;
  21. m_dwThreadId = 0;
  22. }
  23. CMainThread::~CMainThread()
  24. {
  25. delete m_pWorkingDir;
  26. CloseHandle(m_hThread);
  27. }
  28. BOOL CMainThread::InitInstance()
  29. {
  30. m_nTimerID=SetTimer(0,1,1000,0);
  31. m_pPostKeepAliveCommand=0;
  32. // initialize Winsock library
  33. BOOL res=TRUE;
  34. WSADATA wsaData;
  35. WORD wVersionRequested = MAKEWORD(1, 1);
  36. int nResult = WSAStartup(wVersionRequested, &wsaData);
  37. if (nResult != 0)
  38. res=FALSE;
  39. else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
  40. {
  41. WSACleanup();
  42. res=FALSE;
  43. }
  44. m_pControlSocket=new CFtpControlSocket(this, m_pTools);
  45. m_pControlSocket->InitIntern(GetIntern());
  46. return TRUE;
  47. }
  48. DWORD CMainThread::ExitInstance()
  49. {
  50. KillTimer(0,m_nTimerID);
  51. if (m_pControlSocket)
  52. delete m_pControlSocket;
  53. return 1;
  54. }
  55. BOOL CMainThread::IsConnected()
  56. {
  57. BOOL bConnected;
  58. ECS;
  59. bConnected=m_bConnected;
  60. LCS;
  61. return bConnected;
  62. }
  63. void CMainThread::OnTimer(WPARAM wParam, LPARAM lParam)
  64. {
  65. if (!m_pControlSocket)
  66. return;
  67. if (wParam==m_nTimerID)
  68. m_pControlSocket->OnTimer();
  69. return;
  70. }
  71. void CMainThread::ShowStatus(CString status, int type)
  72. {
  73. ECS;
  74. if (m_bQuit)
  75. {
  76. LCS;
  77. return;
  78. }
  79. LCS;
  80. //Displays a message in the message log
  81. t_ffam_statusmessage *pStatus = new t_ffam_statusmessage;
  82. pStatus->post = TRUE;
  83. pStatus->status = status;
  84. pStatus->type = type;
  85. if (!GetIntern()->PostMessage(FZ_MSG_MAKEMSG(FZ_MSG_STATUS, 0), (LPARAM)pStatus))
  86. delete pStatus;
  87. }
  88. void CMainThread::ShowStatus(UINT nID, int type)
  89. {
  90. ECS;
  91. if (m_bQuit)
  92. {
  93. LCS;
  94. return;
  95. }
  96. LCS;
  97. CString str;
  98. str.LoadString(nID);
  99. ShowStatus(str,type);
  100. }
  101. BOOL CMainThread::OnThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
  102. {
  103. if (Msg==m_nInternalMessageID)
  104. {
  105. if (wParam==FZAPI_THREADMSG_COMMAND)
  106. {
  107. if (m_pControlSocket && !m_pControlSocket->IsReady())
  108. m_pPostKeepAliveCommand=(t_command *)lParam;
  109. else
  110. {
  111. t_command *pCommand=(t_command *)lParam;
  112. switch(pCommand->id)
  113. {
  114. case FZ_COMMAND_CONNECT:
  115. DebugAssert(!IsConnected());
  116. SetCurrentPath(CServerPath());
  117. m_pControlSocket->Connect(pCommand->server);
  118. break;
  119. case FZ_COMMAND_LIST:
  120. DebugAssert(m_pControlSocket);
  121. m_pControlSocket->List(FALSE, 0, pCommand->path, pCommand->param1);
  122. break;
  123. case FZ_COMMAND_LISTFILE:
  124. DebugAssert(m_pControlSocket);
  125. m_pControlSocket->ListFile(pCommand->param1, pCommand->path);
  126. break;
  127. case FZ_COMMAND_FILETRANSFER:
  128. DebugAssert(m_pControlSocket);
  129. m_pControlSocket->FileTransfer(&pCommand->transferfile);
  130. break;
  131. case FZ_COMMAND_CUSTOMCOMMAND:
  132. DebugAssert(m_pControlSocket);
  133. m_pControlSocket->FtpCommand(pCommand->param1);
  134. break;
  135. case FZ_COMMAND_DELETE:
  136. DebugAssert(m_pControlSocket);
  137. m_pControlSocket->Delete(pCommand->param1, pCommand->path);
  138. break;
  139. case FZ_COMMAND_REMOVEDIR:
  140. DebugAssert(m_pControlSocket);
  141. m_pControlSocket->RemoveDir(pCommand->param1, pCommand->path);
  142. break;
  143. case FZ_COMMAND_MAKEDIR:
  144. DebugAssert(m_pControlSocket);
  145. m_pControlSocket->MakeDir(pCommand->path);
  146. break;
  147. case FZ_COMMAND_RENAME:
  148. DebugAssert(m_pControlSocket);
  149. m_pControlSocket->Rename(pCommand->param1, pCommand->param2, pCommand->path, pCommand->newPath);
  150. break;
  151. case FZ_COMMAND_CHMOD:
  152. DebugAssert(m_pControlSocket);
  153. m_pControlSocket->Chmod(pCommand->param1, pCommand->path, pCommand->param4);
  154. break;
  155. }
  156. delete pCommand;
  157. }
  158. }
  159. else if (wParam==FZAPI_THREADMSG_PROCESSREPLY)
  160. m_pControlSocket->ProcessReply();
  161. else if (wParam==FZAPI_THREADMSG_TRANSFEREND)
  162. m_pControlSocket->TransferEnd(lParam);
  163. else if (wParam==FZAPI_THREADMSG_CANCEL)
  164. m_pControlSocket->Cancel(lParam);
  165. else if (wParam==FZAPI_THREADMSG_DISCONNECT)
  166. m_pControlSocket->Disconnect();
  167. else if (wParam==FZAPI_THREADMSG_POSTKEEPALIVE)
  168. {
  169. if (m_pPostKeepAliveCommand)
  170. {
  171. PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_COMMAND,(LPARAM)m_pPostKeepAliveCommand);
  172. m_pPostKeepAliveCommand=0;
  173. }
  174. }
  175. else if (wParam==FZAPI_THREADMSG_ASYNCREQUESTREPLY)
  176. {
  177. CAsyncRequestData *pData=(CAsyncRequestData *)lParam;
  178. if (pData)
  179. {
  180. if (pData->nRequestID!=GetAsyncRequestID())
  181. LogMessage(FZ_LOG_INFO, L"Ignoring old request ID");
  182. else
  183. m_pControlSocket->SetAsyncRequestResult(pData->nRequestResult, pData);
  184. delete pData;
  185. }
  186. else
  187. LogMessage(FZ_LOG_WARNING, L"Request reply without data");
  188. }
  189. return TRUE;
  190. }
  191. else if (Msg==WM_TIMER)
  192. {
  193. OnTimer(wParam, lParam);
  194. }
  195. return TRUE;
  196. }
  197. BOOL CMainThread::IsBusy()
  198. {
  199. BOOL bBusy;
  200. ECS;
  201. bBusy=m_bBusy;
  202. LCS;
  203. return bBusy;
  204. }
  205. void CMainThread::Command(const t_command &command)
  206. {
  207. DebugAssert(!IsBusy());
  208. ECS;
  209. if (m_bQuit)
  210. {
  211. LCS;
  212. return;
  213. }
  214. m_bBusy=TRUE;
  215. t_command *pCommand=new t_command;
  216. *pCommand=command;
  217. VERIFY(PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_COMMAND,(LPARAM)pCommand));
  218. m_LastCommand=command;
  219. LCS;
  220. }
  221. BOOL CMainThread::LastOperationSuccessful()
  222. {
  223. return TRUE;
  224. }
  225. void CMainThread::SetBusy(BOOL bBusy)
  226. {
  227. ECS;
  228. m_bBusy=bBusy;
  229. LCS;
  230. }
  231. void CMainThread::SetConnected(BOOL bConnected /*=TRUE*/)
  232. {
  233. ECS;
  234. m_bConnected=bConnected;
  235. if (!bConnected)
  236. {
  237. // when we loose connection
  238. // reset pending commands as we cannot fulfill them anyway
  239. m_pPostKeepAliveCommand = 0;
  240. }
  241. LCS;
  242. }
  243. bool CMainThread::GetCurrentPath(CServerPath &dir)
  244. {
  245. if (!IsConnected())
  246. return false;
  247. ECS;
  248. dir=m_CurrentPath;
  249. LCS;
  250. return true;
  251. }
  252. CServerPath CMainThread::GetCurrentPath()
  253. {
  254. CServerPath path;
  255. bool res = GetCurrentPath(path);
  256. if (!res)
  257. return CServerPath();
  258. return path;
  259. }
  260. BOOL CMainThread::GetCurrentServer(t_server &server)
  261. {
  262. if (!IsConnected())
  263. return FALSE;
  264. ECS;
  265. server=m_pControlSocket->GetCurrentServer();
  266. LCS;
  267. return TRUE;
  268. }
  269. void CMainThread::Quit()
  270. {
  271. ECS;
  272. m_bQuit=TRUE;
  273. LCS;
  274. if (IsBusy())
  275. PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_CANCEL, 1);
  276. PostThreadMessage(WM_QUIT, 0, 0);
  277. }
  278. void CMainThread::SetCurrentPath(CServerPath path)
  279. {
  280. ECS;
  281. m_CurrentPath=path;
  282. LCS;
  283. return;
  284. }
  285. bool CMainThread::UsingMlsd()
  286. {
  287. if (!IsConnected())
  288. return false;
  289. return m_pControlSocket->UsingMlsd();
  290. }
  291. bool CMainThread::UsingUtf8()
  292. {
  293. if (!IsConnected())
  294. return false;
  295. return m_pControlSocket->UsingUtf8();
  296. }
  297. std::string CMainThread::GetTlsVersionStr()
  298. {
  299. if (!IsConnected())
  300. return std::string();
  301. return m_pControlSocket->GetTlsVersionStr();
  302. }
  303. std::string CMainThread::GetCipherName()
  304. {
  305. if (!IsConnected())
  306. return std::string();
  307. return m_pControlSocket->GetCipherName();
  308. }
  309. BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)
  310. {
  311. ECS;
  312. if (m_pWorkingDir)
  313. {
  314. *pWorkingDir=*m_pWorkingDir;
  315. LCS;
  316. return TRUE;
  317. }
  318. LCS;
  319. return FALSE;
  320. }
  321. void CMainThread::SetWorkingDir(t_directory *pWorkingDir)
  322. {
  323. if (!pWorkingDir)
  324. {
  325. ECS;
  326. delete m_pWorkingDir;
  327. m_pWorkingDir=0;
  328. LCS;
  329. }
  330. else
  331. {
  332. ECS;
  333. if (!m_pWorkingDir)
  334. m_pWorkingDir=new t_directory;
  335. *m_pWorkingDir=*pWorkingDir;
  336. LCS;
  337. }
  338. if (pWorkingDir)
  339. {
  340. t_directory *pDirectoryToSend=new t_directory;
  341. *pDirectoryToSend=*pWorkingDir;
  342. SendDirectoryListing(pDirectoryToSend);
  343. }
  344. return;
  345. }
  346. void CMainThread::SendDirectoryListing(t_directory * pDirectoryToSend)
  347. {
  348. if (!GetIntern()->PostMessage(FZ_MSG_MAKEMSG(FZ_MSG_LISTDATA, 0), (LPARAM)pDirectoryToSend))
  349. {
  350. delete pDirectoryToSend;
  351. }
  352. }
  353. bool CMainThread::GetWorkingDirPath(CServerPath &path)
  354. {
  355. ECS;
  356. if (m_pWorkingDir)
  357. {
  358. path = m_pWorkingDir->path;
  359. LCS;
  360. return true;
  361. }
  362. LCS;
  363. return false;
  364. }
  365. __int64 CMainThread::GetAsyncRequestID() const
  366. {
  367. return m_nAsyncRequestID;
  368. }
  369. __int64 CMainThread::GetNextAsyncRequestID()
  370. {
  371. return ++m_nAsyncRequestID;
  372. }
  373. CMainThread* CMainThread::Create(int nPriority /*=THREAD_PRIORITY_NORMAL*/, DWORD dwCreateFlags /*=0*/)
  374. {
  375. CMainThread *pMainThread=new CMainThread();
  376. pMainThread->m_hThread=CreateThread(0, 0, ThreadProc, pMainThread, dwCreateFlags, &pMainThread->m_dwThreadId);
  377. if (!pMainThread->m_hThread)
  378. {
  379. delete pMainThread;
  380. return NULL;
  381. }
  382. ::SetThreadPriority(pMainThread->m_hThread, nPriority);
  383. return pMainThread;
  384. }
  385. BOOL CMainThread::PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam)
  386. {
  387. return ::PostThreadMessage(m_dwThreadId, message, wParam, lParam);
  388. }
  389. DWORD CMainThread::ResumeThread()
  390. {
  391. BOOL res=::ResumeThread(m_hThread);
  392. if (res)
  393. {
  394. m_EventStarted.Lock();
  395. m_EventStarted.Unlock();
  396. }
  397. return res;
  398. }
  399. DWORD WINAPI CMainThread::ThreadProc(LPVOID lpParameter)
  400. {
  401. return ((CMainThread *)lpParameter)->Run();
  402. }
  403. DWORD CMainThread::Run()
  404. {
  405. ECS;
  406. InitInstance();
  407. m_EventStarted.SetEvent();
  408. LCS;
  409. MSG msg;
  410. while (GetMessage(&msg, 0, 0, 0))
  411. {
  412. TranslateMessage(&msg);
  413. if (!msg.hwnd)
  414. {
  415. OnThreadMessage(msg.message, msg.wParam, msg.lParam);
  416. }
  417. DispatchMessage(&msg);
  418. }
  419. DWORD res = ExitInstance();
  420. delete this;
  421. return res;
  422. }
  423. BOOL CMainThread::IsValid() const
  424. {
  425. if (!this)
  426. return FALSE;
  427. if (IsBadWritePtr((VOID *)this, sizeof(CMainThread)) )
  428. return FALSE;
  429. return TRUE;
  430. }