MainThread.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. // FileZilla - a Windows ftp client
  2. // Copyright (C) 2002-2004 - Tim Kosse <[email protected]>
  3. // This program is free software; you can redistribute it and/or
  4. // modify it under the terms of the GNU General Public License
  5. // as published by the Free Software Foundation; either version 2
  6. // of the License, or (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program; if not, write to the Free Software
  13. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. // MainThread.cpp: Implementierungsdatei
  15. //
  16. #include "stdafx.h"
  17. #include "MainThread.h"
  18. #ifndef MPEXT
  19. #include "fileexistsdlg.h"
  20. #include "resource.h"
  21. #include "entersomething.h"
  22. #endif
  23. #ifndef MPEXT_NO_CACHE
  24. #include "directorycache.h"
  25. #endif
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. #define ECS m_CriticalSection.Lock()
  32. #define LCS m_CriticalSection.Unlock()
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CMainThread
  35. CMainThread::CMainThread()
  36. {
  37. m_hOwnerWnd = 0;
  38. m_pControlSocket = NULL;
  39. m_pFtpControlSocket = NULL;
  40. #ifndef MPEXT_NO_SFTP
  41. m_pSFtpControlSocket = NULL;
  42. #endif
  43. m_bBusy = FALSE;
  44. m_bConnected = FALSE;
  45. #ifndef MPEXT_NO_CACHE
  46. m_pDirectoryCache = 0;
  47. #endif
  48. m_pWorkingDir = 0;
  49. m_nAsyncRequestID = 0;
  50. m_bQuit = FALSE;
  51. #ifndef MPEXT_NO_IDENT
  52. m_pIdentServer = 0;
  53. #endif
  54. m_hThread = 0;
  55. m_dwThreadId = 0;
  56. }
  57. CMainThread::~CMainThread()
  58. {
  59. delete m_pWorkingDir;
  60. CloseHandle(m_hThread);
  61. }
  62. BOOL CMainThread::InitInstance()
  63. {
  64. m_nTimerID=SetTimer(0,1,1000,0);
  65. #ifndef MPEXT_NO_CACHE
  66. m_pDirectoryCache=new CDirectoryCache;
  67. #endif
  68. m_pPostKeepAliveCommand=0;
  69. // initialize Winsock library
  70. BOOL res=TRUE;
  71. WSADATA wsaData;
  72. WORD wVersionRequested = MAKEWORD(1, 1);
  73. int nResult = WSAStartup(wVersionRequested, &wsaData);
  74. if (nResult != 0)
  75. res=FALSE;
  76. else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
  77. {
  78. WSACleanup();
  79. res=FALSE;
  80. }
  81. m_pFtpControlSocket=new CFtpControlSocket(this);
  82. #ifndef MPEXT_NO_SFTP
  83. m_pSFtpControlSocket=new CSFtpControlSocket(this);
  84. #endif
  85. m_pControlSocket=m_pFtpControlSocket;
  86. m_pFtpControlSocket->InitLog(this);
  87. #ifndef MPEXT_NO_SFTP
  88. m_pSFtpControlSocket->InitLog(this);
  89. #endif
  90. #ifndef MPEXT_NO_IDENT
  91. if (COptions::GetOptionVal(OPTION_IDENT) && !COptions::GetOptionVal(OPTION_IDENTCONNECT))
  92. m_pIdentServer=new CIdentServerControl(this);
  93. #endif
  94. return TRUE;
  95. }
  96. DWORD CMainThread::ExitInstance()
  97. {
  98. KillTimer(0,m_nTimerID);
  99. if (m_pFtpControlSocket)
  100. delete m_pFtpControlSocket;
  101. #ifndef MPEXT_NO_SFTP
  102. if (m_pSFtpControlSocket)
  103. delete m_pSFtpControlSocket;
  104. #endif
  105. #ifndef MPEXT_NO_CACHE
  106. if (m_pDirectoryCache)
  107. delete m_pDirectoryCache;
  108. #endif
  109. #ifndef MPEXT_NO_IDENT
  110. if (m_pIdentServer)
  111. delete m_pIdentServer;
  112. #endif
  113. return 1;
  114. }
  115. BOOL CMainThread::IsConnected()
  116. {
  117. BOOL bConnected;
  118. ECS;
  119. bConnected=m_bConnected;
  120. LCS;
  121. return bConnected;
  122. }
  123. void CMainThread::OnTimer(WPARAM wParam, LPARAM lParam)
  124. {
  125. if (!m_pControlSocket)
  126. return;
  127. if (wParam==m_nTimerID)
  128. m_pControlSocket->OnTimer();
  129. return;
  130. }
  131. void CMainThread::ShowStatus(CString status, int type)
  132. {
  133. ECS;
  134. if (m_bQuit)
  135. {
  136. LCS;
  137. return;
  138. }
  139. LCS;
  140. //Displays a message in the message log
  141. t_ffam_statusmessage *pStatus = new t_ffam_statusmessage;
  142. pStatus->post = TRUE;
  143. pStatus->status = status;
  144. pStatus->type = type;
  145. if (!PostMessage(m_hOwnerWnd, m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_STATUS, 0), (LPARAM)pStatus))
  146. delete pStatus;
  147. }
  148. void CMainThread::ShowStatus(UINT nID, int type)
  149. {
  150. ECS;
  151. if (m_bQuit)
  152. {
  153. LCS;
  154. return;
  155. }
  156. LCS;
  157. CString str;
  158. str.LoadString(nID);
  159. ShowStatus(str,type);
  160. }
  161. BOOL CMainThread::OnThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
  162. {
  163. if (Msg==m_nInternalMessageID)
  164. {
  165. if (wParam==FZAPI_THREADMSG_COMMAND)
  166. {
  167. if (m_pControlSocket && !m_pControlSocket->IsReady())
  168. m_pPostKeepAliveCommand=(t_command *)lParam;
  169. else
  170. {
  171. t_command *pCommand=(t_command *)lParam;
  172. switch(pCommand->id)
  173. {
  174. case FZ_COMMAND_CONNECT:
  175. ASSERT(!IsConnected());
  176. SetCurrentPath(CServerPath());
  177. #ifndef MPEXT_NO_SFTP
  178. if (pCommand->server.nServerType&FZ_SERVERTYPE_SUB_FTP_SFTP)
  179. m_pControlSocket=m_pSFtpControlSocket;
  180. else
  181. #endif
  182. m_pControlSocket=m_pFtpControlSocket;
  183. ASSERT(m_pControlSocket);
  184. m_pControlSocket->Connect(pCommand->server);
  185. break;
  186. case FZ_COMMAND_LIST:
  187. ASSERT(m_pControlSocket);
  188. m_pControlSocket->List(FALSE, 0, pCommand->path, pCommand->param1, pCommand->param4);
  189. break;
  190. case FZ_COMMAND_FILETRANSFER:
  191. ASSERT(m_pControlSocket);
  192. m_pControlSocket->FileTransfer(&pCommand->transferfile);
  193. break;
  194. case FZ_COMMAND_CUSTOMCOMMAND:
  195. ASSERT(m_pControlSocket);
  196. m_pControlSocket->FtpCommand(pCommand->param1);
  197. break;
  198. case FZ_COMMAND_DELETE:
  199. ASSERT(m_pControlSocket);
  200. m_pControlSocket->Delete(pCommand->param1, pCommand->path);
  201. break;
  202. case FZ_COMMAND_REMOVEDIR:
  203. ASSERT(m_pControlSocket);
  204. m_pControlSocket->RemoveDir(pCommand->param1, pCommand->path);
  205. break;
  206. case FZ_COMMAND_MAKEDIR:
  207. ASSERT(m_pControlSocket);
  208. m_pControlSocket->MakeDir(pCommand->path);
  209. break;
  210. case FZ_COMMAND_RENAME:
  211. ASSERT(m_pControlSocket);
  212. m_pControlSocket->Rename(pCommand->param1, pCommand->param2, pCommand->path, pCommand->newPath);
  213. break;
  214. case FZ_COMMAND_CHMOD:
  215. ASSERT(m_pControlSocket);
  216. m_pControlSocket->Chmod(pCommand->param1, pCommand->path, pCommand->param4);
  217. break;
  218. }
  219. delete pCommand;
  220. }
  221. }
  222. else if (wParam==FZAPI_THREADMSG_PROCESSREPLY)
  223. m_pControlSocket->ProcessReply();
  224. else if (wParam==FZAPI_THREADMSG_TRANSFEREND)
  225. m_pControlSocket->TransferEnd(lParam);
  226. else if (wParam==FZAPI_THREADMSG_CANCEL)
  227. m_pControlSocket->Cancel(lParam);
  228. else if (wParam==FZAPI_THREADMSG_DISCONNECT)
  229. m_pControlSocket->Disconnect();
  230. else if (wParam==FZAPI_THREADMSG_POSTKEEPALIVE)
  231. {
  232. if (m_pPostKeepAliveCommand)
  233. {
  234. PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_COMMAND,(LPARAM)m_pPostKeepAliveCommand);
  235. m_pPostKeepAliveCommand=0;
  236. }
  237. }
  238. else if (wParam==FZAPI_THREADMSG_ASYNCREQUESTREPLY)
  239. {
  240. CAsyncRequestData *pData=(CAsyncRequestData *)lParam;
  241. if (pData)
  242. {
  243. if (pData->nRequestID!=GetAsyncRequestID())
  244. LogMessage(__FILE__, __LINE__, this,FZ_LOG_INFO, _T("Ignoring old request ID"));
  245. else
  246. m_pControlSocket->SetAsyncRequestResult(pData->nRequestResult, pData);
  247. delete pData;
  248. }
  249. else
  250. LogMessage(__FILE__, __LINE__, this,FZ_LOG_WARNING, _T("Request reply without data"));
  251. }
  252. return TRUE;
  253. }
  254. else if (Msg==WM_TIMER)
  255. {
  256. OnTimer(wParam, lParam);
  257. }
  258. return TRUE;
  259. }
  260. BOOL CMainThread::IsBusy()
  261. {
  262. BOOL bBusy;
  263. ECS;
  264. bBusy=m_bBusy;
  265. LCS;
  266. return bBusy;
  267. }
  268. void CMainThread::Command(const t_command &command)
  269. {
  270. ASSERT(!IsBusy());
  271. ECS;
  272. if (m_bQuit)
  273. {
  274. LCS;
  275. return;
  276. }
  277. m_bBusy=TRUE;
  278. t_command *pCommand=new t_command;
  279. *pCommand=command;
  280. VERIFY(PostThreadMessage(m_nInternalMessageID,FZAPI_THREADMSG_COMMAND,(LPARAM)pCommand));
  281. m_LastCommand=command;
  282. LCS;
  283. }
  284. BOOL CMainThread::LastOperationSuccessful()
  285. {
  286. return TRUE;
  287. }
  288. void CMainThread::SetBusy(BOOL bBusy)
  289. {
  290. ECS;
  291. m_bBusy=bBusy;
  292. LCS;
  293. }
  294. void CMainThread::SetConnected(BOOL bConnected /*=TRUE*/)
  295. {
  296. ECS;
  297. m_bConnected=bConnected;
  298. #ifdef MPEXT
  299. if (!bConnected)
  300. {
  301. // when we loose connection
  302. // reset pending commands as we cannot fulfill them anyway
  303. m_pPostKeepAliveCommand = 0;
  304. }
  305. #endif
  306. LCS;
  307. }
  308. bool CMainThread::GetCurrentPath(CServerPath &dir)
  309. {
  310. if (!IsConnected())
  311. return false;
  312. ECS;
  313. dir=m_CurrentPath;
  314. LCS;
  315. return true;
  316. }
  317. CServerPath CMainThread::GetCurrentPath()
  318. {
  319. CServerPath path;
  320. bool res = GetCurrentPath(path);
  321. if (!res)
  322. return CServerPath();
  323. return path;
  324. }
  325. BOOL CMainThread::GetCurrentServer(t_server &server)
  326. {
  327. if (!IsConnected())
  328. return FALSE;
  329. ECS;
  330. server=m_pControlSocket->GetCurrentServer();
  331. LCS;
  332. return TRUE;
  333. }
  334. void CMainThread::Quit()
  335. {
  336. ECS;
  337. m_bQuit=TRUE;
  338. LCS;
  339. if (IsBusy())
  340. PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_CANCEL, 1);
  341. PostThreadMessage(WM_QUIT, 0, 0);
  342. }
  343. void CMainThread::SetCurrentPath(CServerPath path)
  344. {
  345. ECS;
  346. m_CurrentPath=path;
  347. LCS;
  348. return;
  349. }
  350. #ifndef MPEXT
  351. int CMainThread::GetOption(int nOption)
  352. {
  353. int nValue=0;
  354. ECS;
  355. std::map<int, int>::iterator iter=m_Options.find(nOption);
  356. if (iter!=m_Options.end())
  357. nValue=iter->second;
  358. LCS;
  359. return nValue;
  360. }
  361. void CMainThread::SetOption(int nOption, int nValue)
  362. {
  363. ECS;
  364. m_Options[nOption]=nValue;
  365. LCS;
  366. }
  367. #endif
  368. BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)
  369. {
  370. ECS;
  371. if (m_pWorkingDir)
  372. {
  373. *pWorkingDir=*m_pWorkingDir;
  374. LCS;
  375. return TRUE;
  376. }
  377. LCS;
  378. return FALSE;
  379. }
  380. void CMainThread::SetWorkingDir(t_directory *pWorkingDir)
  381. {
  382. if (!pWorkingDir)
  383. {
  384. ECS;
  385. delete m_pWorkingDir;
  386. m_pWorkingDir=0;
  387. LCS;
  388. }
  389. else
  390. {
  391. ECS;
  392. if (!m_pWorkingDir)
  393. m_pWorkingDir=new t_directory;
  394. *m_pWorkingDir=*pWorkingDir;
  395. LCS;
  396. }
  397. if (pWorkingDir)
  398. {
  399. t_directory *pDirectoryToSend=new t_directory;
  400. *pDirectoryToSend=*pWorkingDir;
  401. PostMessage(m_hOwnerWnd, m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_LISTDATA, 0), (LPARAM)pDirectoryToSend);
  402. }
  403. return;
  404. }
  405. bool CMainThread::GetWorkingDirPath(CServerPath &path)
  406. {
  407. ECS;
  408. if (m_pWorkingDir)
  409. {
  410. path = m_pWorkingDir->path;
  411. LCS;
  412. return true;
  413. }
  414. LCS;
  415. return false;
  416. }
  417. __int64 CMainThread::GetAsyncRequestID() const
  418. {
  419. return m_nAsyncRequestID;
  420. }
  421. __int64 CMainThread::GetNextAsyncRequestID()
  422. {
  423. return ++m_nAsyncRequestID;
  424. }
  425. CMainThread* CMainThread::Create(int nPriority /*=THREAD_PRIORITY_NORMAL*/, DWORD dwCreateFlags /*=0*/)
  426. {
  427. CMainThread *pMainThread=new CMainThread();
  428. pMainThread->m_hThread=CreateThread(0, 0, ThreadProc, pMainThread, dwCreateFlags, &pMainThread->m_dwThreadId);
  429. if (!pMainThread->m_hThread)
  430. {
  431. delete pMainThread;
  432. return NULL;
  433. }
  434. ::SetThreadPriority(pMainThread->m_hThread, nPriority);
  435. return pMainThread;
  436. }
  437. BOOL CMainThread::PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam)
  438. {
  439. return ::PostThreadMessage(m_dwThreadId, message, wParam, lParam);
  440. }
  441. DWORD CMainThread::ResumeThread()
  442. {
  443. BOOL res=::ResumeThread(m_hThread);
  444. if (res)
  445. {
  446. m_EventStarted.Lock();
  447. m_EventStarted.Unlock();
  448. }
  449. return res;
  450. }
  451. DWORD WINAPI CMainThread::ThreadProc(LPVOID lpParameter)
  452. {
  453. return ((CMainThread *)lpParameter)->Run();
  454. }
  455. DWORD CMainThread::Run()
  456. {
  457. ECS;
  458. InitInstance();
  459. m_EventStarted.SetEvent();
  460. LCS;
  461. MSG msg;
  462. while (GetMessage(&msg, 0, 0, 0))
  463. {
  464. TranslateMessage(&msg);
  465. if (!msg.hwnd)
  466. OnThreadMessage(msg.message, msg.wParam, msg.lParam);
  467. DispatchMessage(&msg);
  468. }
  469. DWORD res = ExitInstance();
  470. delete this;
  471. return res;
  472. }
  473. BOOL CMainThread::IsValid() const
  474. {
  475. if (!this)
  476. return FALSE;
  477. if (IsBadWritePtr((VOID *)this, sizeof(CMainThread)) )
  478. return FALSE;
  479. if (m_pControlSocket &&
  480. m_pControlSocket != m_pFtpControlSocket
  481. #ifndef MPEXT_NO_SFTP
  482. &&
  483. m_pControlSocket != m_pSFtpControlSocket
  484. #endif
  485. )
  486. return FALSE;
  487. return TRUE;
  488. }