MainThread.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. LCS;
  299. }
  300. bool CMainThread::GetCurrentPath(CServerPath &dir)
  301. {
  302. if (!IsConnected())
  303. return false;
  304. ECS;
  305. dir=m_CurrentPath;
  306. LCS;
  307. return true;
  308. }
  309. CServerPath CMainThread::GetCurrentPath()
  310. {
  311. CServerPath path;
  312. bool res = GetCurrentPath(path);
  313. if (!res)
  314. return CServerPath();
  315. return path;
  316. }
  317. BOOL CMainThread::GetCurrentServer(t_server &server)
  318. {
  319. if (!IsConnected())
  320. return FALSE;
  321. ECS;
  322. server=m_pControlSocket->GetCurrentServer();
  323. LCS;
  324. return TRUE;
  325. }
  326. void CMainThread::Quit()
  327. {
  328. ECS;
  329. m_bQuit=TRUE;
  330. LCS;
  331. if (IsBusy())
  332. PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_CANCEL, 1);
  333. PostThreadMessage(WM_QUIT, 0, 0);
  334. }
  335. void CMainThread::SetCurrentPath(CServerPath path)
  336. {
  337. ECS;
  338. m_CurrentPath=path;
  339. LCS;
  340. return;
  341. }
  342. #ifndef MPEXT
  343. int CMainThread::GetOption(int nOption)
  344. {
  345. int nValue=0;
  346. ECS;
  347. std::map<int, int>::iterator iter=m_Options.find(nOption);
  348. if (iter!=m_Options.end())
  349. nValue=iter->second;
  350. LCS;
  351. return nValue;
  352. }
  353. void CMainThread::SetOption(int nOption, int nValue)
  354. {
  355. ECS;
  356. m_Options[nOption]=nValue;
  357. LCS;
  358. }
  359. #endif
  360. BOOL CMainThread::GetWorkingDir(t_directory *pWorkingDir)
  361. {
  362. ECS;
  363. if (m_pWorkingDir)
  364. {
  365. *pWorkingDir=*m_pWorkingDir;
  366. LCS;
  367. return TRUE;
  368. }
  369. LCS;
  370. return FALSE;
  371. }
  372. void CMainThread::SetWorkingDir(t_directory *pWorkingDir)
  373. {
  374. if (!pWorkingDir)
  375. {
  376. ECS;
  377. delete m_pWorkingDir;
  378. m_pWorkingDir=0;
  379. LCS;
  380. }
  381. else
  382. {
  383. ECS;
  384. if (!m_pWorkingDir)
  385. m_pWorkingDir=new t_directory;
  386. *m_pWorkingDir=*pWorkingDir;
  387. LCS;
  388. }
  389. if (pWorkingDir)
  390. {
  391. t_directory *pDirectoryToSend=new t_directory;
  392. *pDirectoryToSend=*pWorkingDir;
  393. PostMessage(m_hOwnerWnd, m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_LISTDATA, 0), (LPARAM)pDirectoryToSend);
  394. }
  395. return;
  396. }
  397. bool CMainThread::GetWorkingDirPath(CServerPath &path)
  398. {
  399. ECS;
  400. if (m_pWorkingDir)
  401. {
  402. path = m_pWorkingDir->path;
  403. LCS;
  404. return true;
  405. }
  406. LCS;
  407. return false;
  408. }
  409. __int64 CMainThread::GetAsyncRequestID() const
  410. {
  411. return m_nAsyncRequestID;
  412. }
  413. __int64 CMainThread::GetNextAsyncRequestID()
  414. {
  415. return ++m_nAsyncRequestID;
  416. }
  417. CMainThread* CMainThread::Create(int nPriority /*=THREAD_PRIORITY_NORMAL*/, DWORD dwCreateFlags /*=0*/)
  418. {
  419. CMainThread *pMainThread=new CMainThread();
  420. pMainThread->m_hThread=CreateThread(0, 0, ThreadProc, pMainThread, dwCreateFlags, &pMainThread->m_dwThreadId);
  421. if (!pMainThread->m_hThread)
  422. {
  423. delete pMainThread;
  424. return NULL;
  425. }
  426. ::SetThreadPriority(pMainThread->m_hThread, nPriority);
  427. return pMainThread;
  428. }
  429. BOOL CMainThread::PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam)
  430. {
  431. return ::PostThreadMessage(m_dwThreadId, message, wParam, lParam);
  432. }
  433. DWORD CMainThread::ResumeThread()
  434. {
  435. BOOL res=::ResumeThread(m_hThread);
  436. if (res)
  437. {
  438. m_EventStarted.Lock();
  439. m_EventStarted.Unlock();
  440. }
  441. return res;
  442. }
  443. DWORD WINAPI CMainThread::ThreadProc(LPVOID lpParameter)
  444. {
  445. return ((CMainThread *)lpParameter)->Run();
  446. }
  447. DWORD CMainThread::Run()
  448. {
  449. ECS;
  450. InitInstance();
  451. m_EventStarted.SetEvent();
  452. LCS;
  453. MSG msg;
  454. while (GetMessage(&msg, 0, 0, 0))
  455. {
  456. TranslateMessage(&msg);
  457. if (!msg.hwnd)
  458. OnThreadMessage(msg.message, msg.wParam, msg.lParam);
  459. DispatchMessage(&msg);
  460. }
  461. DWORD res = ExitInstance();
  462. delete this;
  463. return res;
  464. }
  465. BOOL CMainThread::IsValid() const
  466. {
  467. if (!this)
  468. return FALSE;
  469. if (IsBadWritePtr((VOID *)this, sizeof(CMainThread)) )
  470. return FALSE;
  471. if (m_pControlSocket &&
  472. m_pControlSocket != m_pFtpControlSocket
  473. #ifndef MPEXT_NO_SFTP
  474. &&
  475. m_pControlSocket != m_pSFtpControlSocket
  476. #endif
  477. )
  478. return FALSE;
  479. return TRUE;
  480. }