Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

526 lines
14 KiB

  1. /* file: mbftApi.cpp */
  2. #include "mbftpch.h"
  3. #include "messages.hpp"
  4. #include "mbftapi.hpp"
  5. MBFT_SEND_FILE_INFO *AllocateSendFileInfo(LPSTR pszPathName);
  6. void FreeSendFileInfo(MBFT_SEND_FILE_INFO *);
  7. MBFTInterface::MBFTInterface
  8. (
  9. IMbftEvents *pEvents,
  10. HRESULT *pHr
  11. )
  12. :
  13. CRefCount(MAKE_STAMP_ID('I','F','T','I')),
  14. m_pEvents(pEvents),
  15. m_pEngine(NULL),
  16. m_FileHandle(0),
  17. m_InStateMachine(FALSE),
  18. m_bFileOfferOK(TRUE),
  19. m_MBFTUserID(0),
  20. m_SendEventHandle(0),
  21. m_ReceiveEventHandle(0)
  22. {
  23. // register window class first
  24. WNDCLASS wc;
  25. ::ZeroMemory(&wc, sizeof(wc));
  26. // wc.style = 0;
  27. wc.lpfnWndProc = MBFTNotifyWndProc;
  28. // wc.cbClsExtra = 0;
  29. // wc.cbWndExtra = 0;
  30. wc.hInstance = g_hDllInst;
  31. // wc.hIcon = NULL;
  32. // wc.hbrBackground = NULL;
  33. // wc.hCursor = NULL;
  34. // wc.lpszMenuName = NULL;
  35. wc.lpszClassName = g_szMBFTWndClassName;
  36. ::RegisterClass(&wc);
  37. // Create a hidden window for notification
  38. m_hwndNotify = ::CreateWindowA(g_szMBFTWndClassName, NULL, WS_POPUP,
  39. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  40. NULL, NULL, g_hDllInst, NULL);
  41. if (NULL != m_hwndNotify)
  42. {
  43. HANDLE hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  44. if (NULL != hEvent)
  45. {
  46. if (::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_CREATE_ENGINE, (WPARAM) hEvent, (LPARAM) this))
  47. {
  48. DWORD dwRet = ::WaitForSingleObject(hEvent, 1000);
  49. ASSERT(WAIT_OBJECT_0 == dwRet);
  50. }
  51. else
  52. {
  53. WARNING_OUT(("MBFTInterface::MBFTInterface: PostMessage failed, err=%d", ::GetLastError()));
  54. }
  55. *pHr = (NULL != m_pEngine) ? S_OK : E_FAIL;
  56. ::CloseHandle(hEvent);
  57. return;
  58. }
  59. }
  60. *pHr = E_FAIL;
  61. }
  62. MBFTInterface::~MBFTInterface(void)
  63. {
  64. if (NULL != m_pEngine)
  65. {
  66. m_pEngine->ClearInterfacePointer();
  67. m_pEngine = NULL;
  68. }
  69. if (NULL != m_hwndNotify)
  70. {
  71. ::DestroyWindow(m_hwndNotify);
  72. }
  73. }
  74. void MBFTInterface::ReleaseInterface(void)
  75. {
  76. Release();
  77. }
  78. void MBFTInterface::Update(void)
  79. {
  80. // DoStateMachine();
  81. }
  82. HRESULT MBFTInterface::AcceptFileOffer
  83. (
  84. MBFT_FILE_OFFER *pOffer,
  85. LPCSTR pszRecDir,
  86. LPCSTR pszFileName
  87. )
  88. {
  89. BOOL bAcceptFile = (NULL != pszRecDir) && FEnsureDirExists(pszRecDir);
  90. DBG_SAVE_FILE_LINE
  91. return m_pEngine->SafePostMessage(
  92. new FileTransferControlMsg(
  93. pOffer->hEvent,
  94. pOffer->lpFileInfoList->hFile,
  95. pszRecDir,
  96. pszFileName,
  97. bAcceptFile ? FileTransferControlMsg::EnumAcceptFile
  98. : FileTransferControlMsg::EnumRejectFile));
  99. }
  100. void MBFTInterface::RejectFileOffer
  101. (
  102. MBFT_FILE_OFFER *pOffer
  103. )
  104. {
  105. DBG_SAVE_FILE_LINE
  106. m_pEngine->SafePostMessage(
  107. new FileTransferControlMsg(
  108. pOffer->hEvent,
  109. pOffer->lpFileInfoList->hFile,
  110. NULL,
  111. NULL,
  112. FileTransferControlMsg::EnumRejectFile));
  113. }
  114. void MBFTInterface::CancelFt
  115. (
  116. MBFTEVENTHANDLE hEvent,
  117. MBFTFILEHANDLE hFile
  118. )
  119. {
  120. DBG_SAVE_FILE_LINE
  121. m_pEngine->SafePostMessage(
  122. new FileTransferControlMsg(
  123. hEvent,
  124. hFile,
  125. NULL,
  126. NULL,
  127. FileTransferControlMsg::EnumAbortFile));
  128. }
  129. HRESULT MBFTInterface::SendFile
  130. (
  131. LPCSTR lpszFilePath,
  132. T120NodeID nidReceiver,
  133. MBFTEVENTHANDLE *lpEventHandle,
  134. MBFTFILEHANDLE *lpFileHandle
  135. )
  136. {
  137. if (NULL != m_SendEventHandle)
  138. {
  139. // We are waiting for a timeout in a file sent to a 3rd party FT
  140. // that does not support our file end notification
  141. return E_PENDING;
  142. }
  143. #ifdef ENABLE_CONDUCTORSHIP
  144. if( !m_pEngine->ConductedModeOK() )
  145. {
  146. return E_ACCESSDENIED;
  147. }
  148. #endif
  149. ::EnterCriticalSection(&g_csWorkThread);
  150. // set event handle
  151. *lpEventHandle = ::GetNewEventHandle();
  152. ::LeaveCriticalSection(&g_csWorkThread);
  153. DBG_SAVE_FILE_LINE
  154. HRESULT hr = m_pEngine->SafePostMessage(
  155. new CreateSessionMsg(MBFT_PRIVATE_SEND_TYPE, *lpEventHandle));
  156. if (S_OK == hr)
  157. {
  158. *lpFileHandle = ::GetNewFileHandle();
  159. ULONG cbSize = ::lstrlenA(lpszFilePath)+1;
  160. DBG_SAVE_FILE_LINE
  161. LPSTR pszPath = new char[cbSize];
  162. if (NULL != pszPath)
  163. {
  164. ::CopyMemory(pszPath, lpszFilePath, cbSize);
  165. DBG_SAVE_FILE_LINE
  166. hr = m_pEngine->SafePostMessage(
  167. new SubmitFileSendMsg(
  168. 0, // SDK only knows node ID
  169. nidReceiver,
  170. pszPath,
  171. *lpFileHandle,
  172. *lpEventHandle,
  173. FALSE));
  174. if (S_OK == hr)
  175. {
  176. m_SendEventHandle = *lpEventHandle;
  177. }
  178. else
  179. {
  180. delete [] pszPath;
  181. }
  182. }
  183. }
  184. return hr;
  185. }
  186. void MBFTInterface::DoStateMachine(MBFTMsg *pMsg)
  187. {
  188. if(!m_InStateMachine)
  189. {
  190. BOOL fHeartBeat = FALSE;
  191. m_InStateMachine = TRUE;
  192. switch(pMsg->GetMsgType())
  193. {
  194. case EnumFileOfferNotifyMsg:
  195. HandleFileOfferNotify((FileOfferNotifyMsg *) pMsg);
  196. break;
  197. case EnumFileTransmitMsg:
  198. HandleProgressNotify((FileTransmitMsg *) pMsg);
  199. fHeartBeat = TRUE;
  200. break;
  201. case EnumFileErrorMsg:
  202. HandleErrorNotify((FileErrorMsg *) pMsg);
  203. break;
  204. case EnumPeerMsg:
  205. HandlePeerNotification((PeerMsg *) pMsg);
  206. break;
  207. case EnumInitUnInitNotifyMsg:
  208. HandleInitUninitNotification((InitUnInitNotifyMsg *) pMsg);
  209. break;
  210. case EnumFileEventEndNotifyMsg:
  211. HandleGenericNotification((FileEventEndNotifyMsg *) pMsg);
  212. break;
  213. default:
  214. ASSERT(0);
  215. break;
  216. } // switch
  217. m_InStateMachine = FALSE;
  218. if (fHeartBeat)
  219. {
  220. ::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_HEART_BEAT, 0, (LPARAM) m_pEngine);
  221. }
  222. }
  223. }
  224. void MBFTInterface::HandleFileOfferNotify(FileOfferNotifyMsg * lpNotifyMessage)
  225. {
  226. if((m_ReceiveEventHandle == 0) || (m_ReceiveEventHandle != lpNotifyMessage->m_EventHandle))
  227. {
  228. TRACEAPI(" File Offer Notification for [%s], Event: [%ld], Size: [%ld], Handle [%Fp]\n",
  229. lpNotifyMessage->m_szFileName,lpNotifyMessage->m_EventHandle,
  230. lpNotifyMessage->m_FileSize,lpNotifyMessage->m_hFile);
  231. MBFT_FILE_OFFER NewFileOffer;
  232. MBFT_RECEIVE_FILE_INFO FileData;
  233. NewFileOffer.hEvent = lpNotifyMessage->m_EventHandle;
  234. NewFileOffer.SenderID = lpNotifyMessage->m_SenderID;
  235. NewFileOffer.NodeID = lpNotifyMessage->m_NodeID;
  236. NewFileOffer.uNumFiles = 1;
  237. NewFileOffer.lpFileInfoList = &FileData;
  238. NewFileOffer.bIsBroadcastEvent = !lpNotifyMessage->m_bAckNeeded;
  239. ::lstrcpynA(FileData.szFileName, lpNotifyMessage->m_szFileName, sizeof(FileData.szFileName));
  240. FileData.hFile = lpNotifyMessage->m_hFile;
  241. FileData.lFileSize = lpNotifyMessage->m_FileSize;
  242. FileData.FileDateTime = lpNotifyMessage->m_FileDateTime;
  243. m_pEvents->OnFileOffer(&NewFileOffer);
  244. }
  245. }
  246. void MBFTInterface::HandleProgressNotify(FileTransmitMsg * lpProgressMessage)
  247. {
  248. MBFT_NOTIFICATION wMBFTCode = (MBFT_NOTIFICATION)lpProgressMessage->m_TransmitStatus;
  249. TRACEAPI(" Notification [%x] from Event [%ld], Handle: [%ld] FileSize: [%ld], Bytes Xfered[%ld]\n",
  250. wMBFTCode,lpProgressMessage->m_EventHandle,
  251. lpProgressMessage->m_hFile,
  252. lpProgressMessage->m_FileSize,
  253. lpProgressMessage->m_BytesTransmitted);
  254. switch (wMBFTCode)
  255. {
  256. case iMBFT_FILE_RECEIVE_BEGIN:
  257. if(!m_ReceiveEventHandle)
  258. {
  259. m_ReceiveEventHandle = lpProgressMessage->m_EventHandle;
  260. }
  261. //m_bFileOfferOK = FALSE;
  262. break;
  263. case iMBFT_FILE_RECEIVE_PROGRESS:
  264. case iMBFT_FILE_SEND_PROGRESS:
  265. {
  266. MBFT_FILE_PROGRESS Progress;
  267. Progress.hEvent = lpProgressMessage->m_EventHandle;
  268. Progress.hFile = lpProgressMessage->m_hFile;
  269. Progress.lFileSize = lpProgressMessage->m_FileSize;
  270. Progress.lBytesTransmitted = lpProgressMessage->m_BytesTransmitted;
  271. Progress.bIsBroadcastEvent = lpProgressMessage->m_bIsBroadcastEvent;
  272. m_pEvents->OnFileProgress(&Progress);
  273. }
  274. break;
  275. case iMBFT_FILE_RECEIVE_END:
  276. //m_bFileOfferOK = TRUE;
  277. if(m_ReceiveEventHandle == lpProgressMessage->m_EventHandle)
  278. {
  279. m_ReceiveEventHandle = 0;
  280. }
  281. // fall through
  282. case iMBFT_FILE_SEND_END:
  283. m_pEvents->OnFileEnd(lpProgressMessage->m_hFile);
  284. break;
  285. default:
  286. ASSERT(iMBFT_FILE_SEND_BEGIN == wMBFTCode);
  287. break;
  288. }
  289. }
  290. void MBFTInterface::HandleErrorNotify(FileErrorMsg * lpErrorMessage)
  291. {
  292. TRACEAPI(" Error Notification, Event: [%ld], Handle [%ld], IsLocal = [%d]\n",
  293. lpErrorMessage->m_EventHandle,lpErrorMessage->m_hFile,
  294. lpErrorMessage->m_bIsLocalError);
  295. MBFT_EVENT_ERROR Error;
  296. Error.hEvent = lpErrorMessage->m_EventHandle;
  297. Error.bIsLocalError = lpErrorMessage->m_bIsLocalError;
  298. Error.UserID = lpErrorMessage->m_UserID;
  299. Error.hFile = lpErrorMessage->m_hFile;
  300. Error.bIsBroadcastEvent = lpErrorMessage->m_bIsBroadcastEvent;
  301. if(LOWORD(Error.hFile) == LOWORD(_iMBFT_PROSHARE_ALL_FILES))
  302. {
  303. Error.hFile = _iMBFT_PROSHARE_ALL_FILES;
  304. }
  305. Error.eErrorType = (MBFT_ERROR_TYPES)lpErrorMessage->m_ErrorType;
  306. Error.eErrorCode = (MBFT_ERROR_CODE)lpErrorMessage->m_ErrorCode;
  307. m_pEvents->OnFileError(&Error);
  308. }
  309. void MBFTInterface::HandlePeerNotification(PeerMsg * lpNewMessage)
  310. {
  311. TRACEAPI(" Peer Notification, Node [%u], UserID [%u], IsProshare = [%u], Added = [%u]\n",
  312. lpNewMessage->m_NodeID,
  313. lpNewMessage->m_MBFTPeerID,lpNewMessage->m_bIsProsharePeer,
  314. lpNewMessage->m_bPeerAdded);
  315. MBFT_PEER_INFO PeerInfo;
  316. PeerInfo.NodeID = lpNewMessage->m_NodeID;
  317. PeerInfo.MBFTPeerID = lpNewMessage->m_MBFTPeerID;
  318. PeerInfo.bIsProShareApp = lpNewMessage->m_bIsProsharePeer;
  319. PeerInfo.MBFTSessionID = lpNewMessage->m_MBFTSessionID;
  320. //PeerInfo.bIsLocalPeer = lpNewMessage->m_bIsLocalPeer;
  321. ::lstrcpynA(PeerInfo.szAppKey,lpNewMessage->m_szAppKey, sizeof(PeerInfo.szAppKey));
  322. //lstrcpyn(PeerInfo.szProtocolKey,lpNewMessage->m_szProtocolKey, sizeof(PeerInfo.szProtocolKey));
  323. if(!lpNewMessage->m_bIsLocalPeer)
  324. {
  325. TRACEAPI("Delivering PEER Notification\n");
  326. if (lpNewMessage->m_bPeerAdded)
  327. {
  328. m_pEvents->OnPeerAdded(&PeerInfo);
  329. }
  330. else
  331. {
  332. m_pEvents->OnPeerRemoved(&PeerInfo);
  333. }
  334. }
  335. if(lpNewMessage->m_bIsLocalPeer)
  336. {
  337. if(lpNewMessage->m_bPeerAdded)
  338. {
  339. m_MBFTUserID = PeerInfo.MBFTPeerID;
  340. m_pEvents->OnInitializeComplete();
  341. }
  342. }
  343. }
  344. void MBFTInterface::HandleInitUninitNotification(InitUnInitNotifyMsg * lpNewMessage)
  345. {
  346. if (lpNewMessage->m_iNotifyMessage == EnumInvoluntaryUnInit)
  347. {
  348. if (NULL != m_pEvents)
  349. {
  350. m_pEvents->OnSessionEnd();
  351. }
  352. }
  353. }
  354. void MBFTInterface::HandleGenericNotification(FileEventEndNotifyMsg * lpNewMessage)
  355. {
  356. if (m_SendEventHandle == lpNewMessage->m_EventHandle)
  357. {
  358. m_SendEventHandle = 0;
  359. }
  360. m_pEvents->OnFileEventEnd(lpNewMessage->m_EventHandle);
  361. }
  362. MBFT_SEND_FILE_INFO *AllocateSendFileInfo(LPSTR pszPathName)
  363. {
  364. MBFT_SEND_FILE_INFO *p = new MBFT_SEND_FILE_INFO;
  365. if (NULL != p)
  366. {
  367. ::ZeroMemory(p, sizeof(*p));
  368. ULONG cb = ::lstrlenA(pszPathName) + 1;
  369. p->lpszFilePath = new char[cb];
  370. if (NULL != p->lpszFilePath)
  371. {
  372. ::CopyMemory(p->lpszFilePath, pszPathName, cb);
  373. #ifdef BUG_INTL
  374. ::AnsiToOem(p->lpszFilePath, p->lpszFilePath);
  375. #endif /* BUG_INTL */
  376. }
  377. else
  378. {
  379. delete p;
  380. p = NULL;
  381. }
  382. }
  383. return p;
  384. }
  385. void FreeSendFileInfo(MBFT_SEND_FILE_INFO *p)
  386. {
  387. if (NULL != p)
  388. {
  389. delete p->lpszFilePath;
  390. delete p;
  391. }
  392. }
  393. HRESULT MBFTInterface::SafePostNotifyMessage(MBFTMsg *pMsg)
  394. {
  395. if (NULL != pMsg)
  396. {
  397. AddRef();
  398. ::PostMessage(m_hwndNotify, MBFTNOTIFY_BASIC, (WPARAM) pMsg, (LPARAM) this);
  399. return S_OK;
  400. }
  401. ERROR_OUT(("MBFTInterface::SafePostNotifyMessage: null msg ptr"));
  402. return E_OUTOFMEMORY;
  403. }
  404. LRESULT CALLBACK
  405. MBFTNotifyWndProc
  406. (
  407. HWND hwnd,
  408. UINT uMsg,
  409. WPARAM wParam,
  410. LPARAM lParam
  411. )
  412. {
  413. switch (uMsg)
  414. {
  415. case MBFTNOTIFY_BASIC:
  416. {
  417. MBFTInterface *pIntf = (MBFTInterface *) lParam;
  418. MBFTMsg *pMsg = (MBFTMsg *) wParam;
  419. ASSERT(NULL != pIntf);
  420. ASSERT(NULL != pMsg);
  421. pIntf->DoStateMachine(pMsg);
  422. delete pMsg;
  423. pIntf->Release();
  424. }
  425. break;
  426. case WM_CLOSE:
  427. ::DestroyWindow(hwnd);
  428. break;
  429. default:
  430. return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
  431. }
  432. return 0;
  433. }