Leaked source code of windows server 2003
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.

3865 lines
105 KiB

  1. // File: ftui.h
  2. #include "mbftpch.h"
  3. #include <commctrl.h>
  4. #include <regentry.h>
  5. #include "ftui.h"
  6. #include "version.h"
  7. #include <iappldr.h>
  8. #include <nmhelp.h>
  9. static ULONG s_cMsgBox2Dlg = 0; // for alignment
  10. static ULONG s_cRecvDlg = 0; // for alignment
  11. static ULONG s_sort = -1;
  12. ULONG _GetPercent(ULONG cbTotalRecvSize , ULONG cbFileSize);
  13. TCHAR s_szMSFT[64];
  14. static TCHAR s_szScratchText[MAX_PATH*2];
  15. static const TCHAR s_cszHtmlHelpFile[] = TEXT("conf.chm");
  16. #define MAX_FILE_NAME_LENGTH 30
  17. LRESULT CALLBACK FtMainWndProc(HWND, UINT, WPARAM, LPARAM);
  18. INT_PTR CALLBACK RecvDlgProc(HWND, UINT, WPARAM, LPARAM);
  19. LPTSTR PathNameToFileName(LPTSTR pszPathName);
  20. HRESULT GetRecvFolder(LPTSTR pszInFldr, LPTSTR pszOutFldr);
  21. BOOL MsgBox2(CAppletWindow *pWindow, LPTSTR pszText);
  22. void ShiftFocus(HWND hwndTop, BOOL bForward);
  23. void EnsureTrailingSlash(LPTSTR);
  24. int MyLoadString(UINT idStr);
  25. int MyLoadString(UINT idStr, LPTSTR pszDstStr);
  26. int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement);
  27. int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, LPTSTR pszElement2);
  28. __inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement)
  29. { return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement); }
  30. __inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement1, UINT_PTR nElement2)
  31. { return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement1, (LPTSTR) nElement2); }
  32. int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, UINT_PTR nElement2)
  33. { return MyLoadString(idStr, pszDstStr, pszElement1, (LPTSTR) nElement2); }
  34. __inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement1, LPTSTR pszElement2)
  35. { return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement1, pszElement2); }
  36. #define count_of(array) (sizeof(array) / sizeof(array[0]))
  37. void OnChangeFolder(void);
  38. BOOL FBrowseForFolder(LPTSTR pszFolder, UINT cchMax, LPCTSTR pszTitle);
  39. extern BOOL g_fShutdownByT120;
  40. void OPT_GetFTWndPosition(RECT *pRect)
  41. {
  42. int iLeft, iTop, iRight, iBottom;
  43. RegEntry reWnd( FILEXFER_KEY, HKEY_CURRENT_USER);
  44. iLeft = reWnd.GetNumber(REGVAL_WINDOW_XPOS, 0);
  45. iTop = reWnd.GetNumber(REGVAL_WINDOW_YPOS, 0);
  46. iRight = reWnd.GetNumber(REGVAL_WINDOW_WIDTH, 0) + iLeft;
  47. iBottom = reWnd.GetNumber(REGVAL_WINDOW_HEIGHT, 0) + iTop;
  48. // If it was empty, use the new rect
  49. if (!(iBottom || iTop || iLeft || iRight))
  50. {
  51. return;
  52. }
  53. // Make sure that the window rectangle is (at least partially) on
  54. // screen, and not too large. First get the screen size
  55. int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
  56. int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
  57. // Check the window size
  58. if ((iRight - iLeft) > screenWidth)
  59. {
  60. iRight = iLeft + screenWidth;
  61. }
  62. if ((iBottom - iTop) > screenHeight)
  63. {
  64. iTop = screenHeight;
  65. }
  66. // Check the window position
  67. if (iLeft >= screenWidth)
  68. {
  69. // Off screen to the right - keep the width the same
  70. iLeft = screenWidth - (iRight - iLeft);
  71. iRight = screenWidth;
  72. }
  73. if (iRight < 0)
  74. {
  75. // Off screen to the left - keep the width the same
  76. iRight = iRight - iLeft;
  77. iLeft = 0;
  78. }
  79. if (iTop >= screenHeight)
  80. {
  81. // Off screen to the bottom - keep the height the same
  82. iTop = screenHeight - (iBottom - iTop);
  83. iBottom = screenHeight;
  84. }
  85. if (iBottom < 0)
  86. {
  87. // Off screen to the top - keep the height the same
  88. iBottom = (iBottom - iTop);
  89. iTop = 0;
  90. }
  91. pRect->left = iLeft;
  92. pRect->top = iTop;
  93. pRect->right = iRight - iLeft;
  94. pRect->bottom = iBottom - iTop;
  95. }
  96. CAppletWindow::CAppletWindow(BOOL fNoUI, HRESULT *pHr)
  97. :
  98. CRefCount(MAKE_STAMP_ID('F','T','U','I')),
  99. m_hwndMainUI(NULL),
  100. m_pToolbar(NULL),
  101. m_hwndListView(NULL),
  102. m_hwndStatusBar(NULL),
  103. m_pEngine(NULL),
  104. m_fInFileOpenDialog(FALSE),
  105. m_pCurrSendFileInfo(NULL),
  106. m_nCurrSendEventHandle(0),
  107. m_hIconInCall(NULL),
  108. m_hIconNotInCall(NULL)
  109. {
  110. m_UIMode = fNoUI ? FTUIMODE_NOUI : FTUIMODE_UIHIDDEN;
  111. ::GetCurrentDirectory(MAX_PATH, m_szDefaultDir);
  112. *pHr = E_FAIL; // failure, at default
  113. // create window class name
  114. ::wsprintf(&m_szFtMainWndClassName[0], TEXT("FTMainWnd%0X_%0X"), ::GetCurrentProcessId(), ::GetTickCount());
  115. ASSERT(::lstrlenA(&m_szFtMainWndClassName[0]) < sizeof(m_szFtMainWndClassName));
  116. // register window class first
  117. WNDCLASS wc;
  118. ::ZeroMemory(&wc, sizeof(wc));
  119. //wc.style = 0;
  120. wc.lpfnWndProc = FtMainWndProc;
  121. // wc.cbClsExtra = 0;
  122. // wc.cbWndExtra = 0;
  123. wc.hInstance = g_hDllInst;
  124. wc.hIcon = ::LoadIcon(g_hDllInst, MAKEINTRESOURCE(IDI_FILE_TRANSFER));
  125. // wc.hbrBackground = NULL;
  126. // wc.hCursor = NULL;
  127. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_FT);
  128. wc.lpszClassName = m_szFtMainWndClassName;
  129. if (::RegisterClass(&wc))
  130. {
  131. ::MyLoadString(IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION);
  132. m_hwndMainUI = ::CreateWindow(
  133. m_szFtMainWndClassName,
  134. s_szScratchText,
  135. WS_OVERLAPPEDWINDOW | WS_TABSTOP,
  136. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  137. NULL, // no parent window
  138. NULL, // use class' menu
  139. g_hDllInst,
  140. (LPVOID) this); // this window is for this object
  141. if (NULL != m_hwndMainUI)
  142. {
  143. // success
  144. *pHr = S_OK;
  145. }
  146. }
  147. m_hAccel = ::LoadAccelerators(g_hDllInst, MAKEINTRESOURCE(RECVDLGACCELTABLE));
  148. m_hLVAccel = ::LoadAccelerators(g_hDllInst, MAKEINTRESOURCE(LISTVIEWACCELTABLE));
  149. }
  150. CAppletWindow::~CAppletWindow(void)
  151. {
  152. ASSERT(NULL == m_hwndMainUI);
  153. ::UnregisterClass(m_szFtMainWndClassName, g_hDllInst);
  154. ClearSendInfo(FALSE);
  155. ClearRecvInfo();
  156. if (m_hIconInCall)
  157. ::DestroyIcon(m_hIconInCall);
  158. if (m_hIconNotInCall)
  159. ::DestroyIcon(m_hIconNotInCall);
  160. ASSERT(NULL == m_pEngine);
  161. }
  162. BOOL CAppletWindow::FilterMessage(MSG *pMsg)
  163. {
  164. CRecvDlg *pRecvDlg;
  165. HWND hwndError;
  166. HWND hwndForeground = ::GetForegroundWindow();
  167. m_RecvDlgList.Reset();
  168. while (NULL != (pRecvDlg = m_RecvDlgList.Iterate()))
  169. {
  170. if (::IsDialogMessage(pRecvDlg->GetHwnd(), pMsg))
  171. {
  172. return TRUE;
  173. }
  174. }
  175. if (hwndForeground == m_hwndMainUI)
  176. {
  177. BOOL fRet = ::TranslateAccelerator(m_hwndMainUI, m_hLVAccel, pMsg);
  178. return fRet;
  179. }
  180. m_ErrorDlgList.Reset();
  181. while (NULL != (hwndError = m_ErrorDlgList.Iterate()))
  182. {
  183. if (::IsDialogMessage(hwndError, pMsg))
  184. {
  185. return TRUE;
  186. }
  187. }
  188. return FALSE;
  189. }
  190. BOOL CAppletWindow::QueryShutdown(BOOL fShutdown)
  191. {
  192. if (m_UIMode != FTUIMODE_NOUI)
  193. {
  194. int id = 0;
  195. if (m_nCurrSendEventHandle)
  196. {
  197. id = (fShutdown)?IDS_QUERY_SEND_SHUTDOWN:IDS_QUERY_SEND_HANGUP;
  198. }
  199. else if (IsReceiving())
  200. {
  201. id = (fShutdown)?IDS_QUERY_RECVING_SHUTDOWN:IDS_QUERY_RECVING_HANGUP;
  202. }
  203. if (id)
  204. {
  205. // could be in any thread
  206. TCHAR szText[MAX_PATH];
  207. if (::MyLoadString(id, szText))
  208. {
  209. if (IDNO == ::MessageBox(NULL, szText, s_szMSFT, MB_TASKMODAL | MB_YESNO | MB_ICONQUESTION))
  210. {
  211. return FALSE;
  212. }
  213. }
  214. }
  215. }
  216. if (m_nCurrSendEventHandle)
  217. {
  218. OnStopSending();
  219. }
  220. if (IsReceiving())
  221. {
  222. CRecvDlg *pRecvDlg = NULL;
  223. m_RecvDlgList.Reset();
  224. while (NULL != (pRecvDlg = m_RecvDlgList.Iterate()))
  225. {
  226. DBG_SAVE_FILE_LINE
  227. GetEngine()->SafePostMessage(
  228. new FileTransferControlMsg(
  229. pRecvDlg->GetEventHandle(),
  230. pRecvDlg->GetFileHandle(),
  231. NULL,
  232. NULL,
  233. FileTransferControlMsg::EnumAbortFile));
  234. }
  235. }
  236. return TRUE;
  237. }
  238. void CAppletWindow::RegisterEngine(MBFTEngine *pEngine)
  239. {
  240. ASSERT(NULL == m_pEngine);
  241. pEngine->AddRef();
  242. m_pEngine = pEngine;
  243. UpdateUI();
  244. }
  245. void CAppletWindow::UnregisterEngine(void)
  246. {
  247. if (NULL != m_pEngine)
  248. {
  249. m_pEngine->Release();
  250. m_pEngine = NULL;
  251. ClearSendInfo(TRUE);
  252. ClearRecvInfo();
  253. }
  254. if (UIHidden())
  255. { // exit
  256. ::PostMessage(m_hwndMainUI, WM_CLOSE, 0, 0);
  257. }
  258. else
  259. {
  260. UpdateUI(); // don't quit
  261. }
  262. }
  263. void CAppletWindow::RegisterRecvDlg(CRecvDlg *pDlg)
  264. {
  265. m_RecvDlgList.Prepend(pDlg);
  266. }
  267. void CAppletWindow::UnregisterRecvDlg(CRecvDlg *pDlg)
  268. {
  269. m_RecvDlgList.Remove(pDlg);
  270. FocusNextRecvDlg();
  271. }
  272. BOOL CAppletWindow::IsReceiving(void)
  273. {
  274. BOOL fRet = FALSE;
  275. CRecvDlg *pDlg;
  276. CUiRecvFileInfo *pRecvFile;
  277. m_RecvDlgList.Reset();
  278. while (NULL != (pDlg = m_RecvDlgList.Iterate()))
  279. {
  280. pRecvFile = pDlg->GetRecvFileInfo();
  281. if (pRecvFile && (pRecvFile->GetTotalRecvSize() < pRecvFile->GetSize()))
  282. {
  283. fRet = TRUE;
  284. break;
  285. }
  286. }
  287. return fRet;
  288. }
  289. CRecvDlg * CAppletWindow::FindDlgByHandles(MBFTEVENTHANDLE nEventHandle, MBFTFILEHANDLE nFileHandle)
  290. {
  291. CRecvDlg *pDlg;
  292. m_RecvDlgList.Reset();
  293. while (NULL != (pDlg = m_RecvDlgList.Iterate()))
  294. {
  295. if (nEventHandle == pDlg->GetEventHandle() &&
  296. nFileHandle == pDlg->GetFileHandle())
  297. {
  298. break;
  299. }
  300. }
  301. return pDlg;
  302. }
  303. /////////////////////////////////////////////////////////////////
  304. //
  305. // WM_CREATE
  306. //
  307. LRESULT OnCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
  308. {
  309. CREATESTRUCT *p = (CREATESTRUCT *) lParam;
  310. CAppletWindow *pWindow = (CAppletWindow *) p->lpCreateParams;
  311. ASSERT(NULL != pWindow);
  312. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) p->lpCreateParams);
  313. pWindow->SetHwnd(hwnd);
  314. ::InitCommonControls();
  315. pWindow->CreateToolBar();
  316. pWindow->CreateStatusBar();
  317. pWindow->CreateListView();
  318. ::DragAcceptFiles(hwnd, g_fSendAllowed);
  319. // resize the window
  320. MINMAXINFO mmi;
  321. ::ZeroMemory(&mmi, sizeof(mmi));
  322. pWindow->OnGetMinMaxInfo(&mmi);
  323. RECT rcUI;
  324. ::GetWindowRect(pWindow->GetHwnd(), &rcUI);
  325. rcUI.right = mmi.ptMinTrackSize.x;
  326. rcUI.bottom = mmi.ptMinTrackSize.y + 30;
  327. OPT_GetFTWndPosition(&rcUI);
  328. ::MoveWindow(pWindow->GetHwnd(), rcUI.left, rcUI.top,
  329. rcUI.right, rcUI.bottom, TRUE);
  330. pWindow->UpdateUI();
  331. #if defined(TEST_PLUGABLE) && defined(_DEBUG)
  332. ::OnPluggableBegin(hwnd);
  333. #endif
  334. return 0;
  335. }
  336. enum
  337. {
  338. TB_IDX_ADD_FILES = 0,
  339. TB_IDX_REMOVE_FILES,
  340. TB_IDX_BREAK_1,
  341. TB_IDX_IDM_SEND_ALL,
  342. TB_IDX_IDM_SEND_ONE,
  343. TB_IDX_IDM_STOP_SENDING,
  344. TB_IDX_BREAK_2,
  345. TB_IDX_IDM_OPEN_RECV_FOLDER,
  346. TB_IDX_IDM_CHANGE_FOLDER,
  347. TB_IDX_BREAK_3,
  348. TB_IDX_IDM_HELP,
  349. };
  350. static Buttons buttons [] =
  351. {
  352. {IDB_ADDFILES, CBitmapButton::Disabled+1, 1, IDM_ADD_FILES, (LPCSTR)IDS_MENU_ADD_FILES,},
  353. {IDB_REMOVEFILES, CBitmapButton::Disabled+1, 1, IDM_REMOVE_FILES, (LPCSTR)IDS_MENU_REMOVE_FILES,},
  354. {0, 0, 0, 0, 0,},
  355. {IDB_SENDFILE, CBitmapButton::Disabled+1, 1, IDM_SEND_ALL, (LPCSTR)IDS_MENU_SEND_ALL,},
  356. {IDB_STOPSEND, CBitmapButton::Disabled+1, 1, IDM_STOP_SENDING, (LPCSTR)IDS_MENU_STOP_SENDING,},
  357. {0, 0, 0, 0, 0,},
  358. {IDB_FOLDER, CBitmapButton::Disabled+1, 1, IDM_OPEN_RECV_FOLDER, (LPCSTR)IDS_MENU_OPEN_RECV_FOLDER,},
  359. {0, 0, 0, 0, 0},
  360. };
  361. BOOL CAppletWindow::CreateToolBar(void)
  362. {
  363. DBG_SAVE_FILE_LINE
  364. m_pToolbar = new CComboToolbar();
  365. if (m_pToolbar)
  366. {
  367. m_pToolbar->Create(m_hwndMainUI, &buttons[0], count_of(buttons), this);
  368. m_pToolbar->Release();
  369. return TRUE;
  370. }
  371. return FALSE;
  372. }
  373. BOOL CAppletWindow::CreateStatusBar(void)
  374. {
  375. m_hwndStatusBar = ::CreateWindowEx(0,
  376. STATUSCLASSNAME, // status bar class
  377. TEXT(""), // no default text
  378. WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP,
  379. 0, 0, 0, 0,
  380. m_hwndMainUI,
  381. (HMENU) IDC_STATUS_BAR,
  382. g_hDllInst,
  383. NULL);
  384. ASSERT(NULL != m_hwndStatusBar);
  385. if (NULL != m_hwndStatusBar)
  386. {
  387. // Load Call Icons
  388. m_hIconInCall = (HICON) ::LoadImage(g_hDllInst,
  389. MAKEINTRESOURCE(IDI_INCALL),
  390. IMAGE_ICON,
  391. ::GetSystemMetrics(SM_CXSMICON),
  392. ::GetSystemMetrics(SM_CYSMICON),
  393. LR_DEFAULTCOLOR);
  394. m_hIconNotInCall = (HICON) ::LoadImage(g_hDllInst,
  395. MAKEINTRESOURCE(IDI_NOT_INCALL),
  396. IMAGE_ICON,
  397. ::GetSystemMetrics(SM_CXSMICON),
  398. ::GetSystemMetrics(SM_CYSMICON),
  399. LR_DEFAULTCOLOR);
  400. if (CreateProgressBar())
  401. {
  402. return TRUE;
  403. }
  404. }
  405. return FALSE;
  406. }
  407. BOOL CAppletWindow::CreateProgressBar(void)
  408. {
  409. RECT rcl;
  410. GetClientRect(m_hwndStatusBar, &rcl);
  411. m_hwndProgressBar = ::CreateWindowEx(0, PROGRESS_CLASS, TEXT(""),
  412. WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
  413. rcl.right/2 + 2, 2, rcl.right - rcl.right/2 - 40, rcl.bottom - 8,
  414. m_hwndStatusBar, (HMENU)IDC_PROGRESS_BAR,
  415. g_hDllInst, NULL);
  416. if (m_hwndProgressBar)
  417. {
  418. ::SendMessage(m_hwndProgressBar, PBM_SETRANGE, 0L, MAKELONG(0, 100));
  419. return TRUE;
  420. }
  421. return FALSE;
  422. }
  423. BOOL CAppletWindow::CreateListView(void)
  424. {
  425. // get the size and position of the main window
  426. RECT rcWindow, rcToolBar, rcStatusBar;
  427. SIZE szToolBar;
  428. ::GetClientRect(m_hwndMainUI, &rcWindow);
  429. m_pToolbar->GetDesiredSize(&szToolBar);
  430. ::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
  431. ULONG x = 0;
  432. ULONG y = szToolBar.cy - 1;
  433. ULONG cx = rcWindow.right - rcWindow.left;
  434. ULONG cy = rcWindow.bottom - rcWindow.top - y - (rcStatusBar.bottom - rcStatusBar.top) + 1;
  435. // create the list view window
  436. m_hwndListView = ::CreateWindowEx(WS_EX_CLIENTEDGE, // sunken look
  437. WC_LISTVIEW , // list view class
  438. TEXT(""), // no default text
  439. WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT |WS_TABSTOP |
  440. LVS_AUTOARRANGE | WS_CLIPCHILDREN | LVS_SHOWSELALWAYS,
  441. x, y, cx, cy,
  442. m_hwndMainUI,
  443. (HMENU) IDC_LIST_VIEW,
  444. g_hDllInst,
  445. NULL);
  446. ASSERT(NULL != m_hwndListView);
  447. if (NULL != m_hwndListView)
  448. {
  449. // set extended list view styles
  450. DWORD dwExtStyle = ListView_GetExtendedListViewStyle(m_hwndListView);
  451. dwExtStyle |= (LVS_EX_HEADERDRAGDROP | LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT);
  452. ListView_SetExtendedListViewStyle(m_hwndListView, dwExtStyle);
  453. // enable window only if we can send files
  454. ::EnableWindow(m_hwndListView, g_fSendAllowed);
  455. // set up the columns
  456. ULONG i;
  457. LVCOLUMN lvc;
  458. LVITEM lvi;
  459. TCHAR szText[64];
  460. int iColumnSize[NUM_LIST_VIEW_COLUMNS] = {150, 80, 70, 130}; // listview column size
  461. // initialize the common part of the columns
  462. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  463. lvc.fmt = LVCFMT_LEFT; // left-aligned column
  464. lvc.pszText = szText;
  465. // initialize columns one by one
  466. for (i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
  467. {
  468. lvc.iSubItem = i;
  469. ::LoadString(g_hDllInst, IDS_LV_FILE_NAME + i, szText, count_of(szText));
  470. lvc.cx = iColumnSize[i];
  471. int iRet = ListView_InsertColumn(m_hwndListView, lvc.iSubItem, &lvc);
  472. ASSERT(-1 != iRet);
  473. }
  474. return TRUE;
  475. }
  476. return FALSE;
  477. }
  478. BOOL CAppletWindow::DrawItem(LPDRAWITEMSTRUCT pdis)
  479. {
  480. ASSERT(pdis);
  481. if (NULL != (pdis->itemData))
  482. {
  483. int nWidth = pdis->rcItem.right - pdis->rcItem.left;
  484. int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
  485. int nLeft = pdis->rcItem.left;
  486. int nTop = pdis->rcItem.top;
  487. int xSmIcon = ::GetSystemMetrics(SM_CXSMICON);
  488. int ySmIcon = ::GetSystemMetrics(SM_CYSMICON);
  489. if (nWidth > xSmIcon)
  490. {
  491. nLeft += (nWidth - xSmIcon) / 2 - 5;
  492. nWidth = xSmIcon;
  493. }
  494. if (nHeight > ySmIcon)
  495. {
  496. nTop += (nHeight - ySmIcon) / 2;
  497. nHeight = ySmIcon;
  498. }
  499. ::DrawIconEx( pdis->hDC,
  500. nLeft,
  501. nTop,
  502. (HICON) (pdis->itemData),
  503. nWidth,
  504. nHeight,
  505. 0,
  506. NULL,
  507. DI_NORMAL);
  508. }
  509. return TRUE;
  510. }
  511. void CAppletWindow::OnCommand(WORD wId, HWND hwndCtl, WORD codeNotify)
  512. {
  513. switch (wId)
  514. {
  515. case IDM_ADD_FILES:
  516. OnAddFiles();
  517. UpdateUI();
  518. break;
  519. case IDM_REMOVE_FILES:
  520. OnRemoveFiles();
  521. UpdateUI();
  522. break;
  523. case IDM_SEND_ALL:
  524. s_cMsgBox2Dlg = 0;
  525. SetSendMode(TRUE);
  526. OnSendAll();
  527. UpdateUI();
  528. break;
  529. case IDM_SEND_ONE:
  530. s_cMsgBox2Dlg = 0;
  531. SetSendMode(FALSE);
  532. OnSendOne();
  533. UpdateUI();
  534. break;
  535. case IDM_STOP_SENDING:
  536. OnStopSending();
  537. UpdateUI();
  538. break;
  539. case IDM_OPEN_RECV_FOLDER:
  540. OnOpenRecvFolder();
  541. break;
  542. case IDM_CHANGE_FOLDER:
  543. OnChangeFolder();
  544. break;
  545. case IDM_EXIT:
  546. OnExit();
  547. break;
  548. case IDM_HELP:
  549. OnHelp();
  550. break;
  551. case ID_NAV_TAB:
  552. ShiftFocus(m_hwndMainUI, TRUE);
  553. if(GetFocus() == m_hwndListView)
  554. {
  555. SetListViewFocus();
  556. }
  557. break;
  558. case ID_NAV_SHIFT_TAB:
  559. ShiftFocus(m_hwndMainUI, FALSE);
  560. if(GetFocus() == m_hwndListView)
  561. {
  562. SetListViewFocus();
  563. }
  564. break;
  565. case IDM_ABOUT:
  566. OnAbout();
  567. break;
  568. default:
  569. WARNING_OUT(("FT::OnCommand: unknown command ID=%u", (UINT) wId));
  570. break;
  571. }
  572. return;
  573. }
  574. /////////////////////////////////////////////////////////////////
  575. //
  576. // WM_COMMAND
  577. //
  578. LRESULT OnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
  579. {
  580. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  581. if (NULL != pWindow)
  582. {
  583. WORD wNotifyCode = GET_WM_COMMAND_CMD(wParam, lParam); // notification code
  584. WORD wID = GET_WM_COMMAND_ID(wParam, lParam); // item, control, or accelerator identifier
  585. HWND hwndCtl = (HWND) lParam; // handle of control
  586. pWindow->OnCommand(wID, hwndCtl, wNotifyCode);
  587. return 0;
  588. }
  589. else
  590. {
  591. WARNING_OUT((" CAppletWindow::OnCommand--Received unhandled window message.\n"));
  592. }
  593. return (DefWindowProc(hwnd, WM_COMMAND, wParam, lParam));
  594. }
  595. //
  596. // OnAddFiles
  597. //
  598. UINT_PTR APIENTRY SendFileDlgHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  599. {
  600. if (WM_INITDIALOG == uMsg)
  601. {
  602. hdlg = ::GetParent(hdlg); // Real dialog is this window's parent
  603. if (::MyLoadString(IDS_FILEDLG_SEND))
  604. {
  605. ::SetDlgItemText(hdlg, IDOK, s_szScratchText);
  606. }
  607. }
  608. return 0;
  609. }
  610. void CAppletWindow::OnAddFiles(void)
  611. {
  612. TCHAR szTitle[MAX_PATH];
  613. TCHAR szFilter[MAX_PATH];
  614. TCHAR szDirSav[MAX_PATH];
  615. TCHAR szSendDir[MAX_PATH];
  616. // Load dialog title and filter strings
  617. if (::MyLoadString(IDS_FILEDLG_TITLE, szTitle) &&
  618. ::MyLoadString(IDS_FILEDLG_FILTER, szFilter))
  619. {
  620. // replace '|' to '\0'
  621. LPTSTR pszFltr = szFilter;
  622. while (TEXT('\0') != *pszFltr)
  623. {
  624. if (TEXT('|') == *pszFltr)
  625. {
  626. *pszFltr = TEXT('\0');
  627. pszFltr++; // cannot use CharNext
  628. }
  629. else
  630. {
  631. pszFltr = ::CharNext(pszFltr);
  632. }
  633. }
  634. // only allow one "Select a file to send" dialog
  635. if (! m_fInFileOpenDialog)
  636. {
  637. m_fInFileOpenDialog = TRUE;
  638. // Allocate a really large buffer to hold the file list
  639. ULONG cbBufSize = 8192;
  640. DBG_SAVE_FILE_LINE
  641. LPTSTR pszBuffer = new TCHAR[cbBufSize];
  642. if (NULL != pszBuffer)
  643. {
  644. *pszBuffer = TEXT('\0'); // start with null string
  645. OPENFILENAME ofn;
  646. ::ZeroMemory(&ofn, sizeof(ofn));
  647. ofn.lStructSize = sizeof(ofn);
  648. ofn.hwndOwner = m_hwndMainUI;
  649. ofn.hInstance = g_hDllInst;
  650. ofn.lpstrFilter = &szFilter[0];
  651. ofn.nFilterIndex = 1L; // FUTURE: remember filter preference
  652. ofn.lpstrFile = pszBuffer;
  653. ofn.nMaxFile = cbBufSize - 1; // Number of TCHAR in pszFiles (not including NULL)
  654. ofn.lpstrTitle = &szTitle[0];
  655. ofn.lpstrInitialDir = m_szDefaultDir;
  656. ofn.lpfnHook = SendFileDlgHookProc;
  657. ofn.Flags = OFN_ALLOWMULTISELECT | OFN_ENABLEHOOK | // OFN_HIDEREADONLY |
  658. OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
  659. // remember current directory
  660. ::ZeroMemory(szSendDir, sizeof(szSendDir));
  661. ::GetCurrentDirectory(count_of(szDirSav), szDirSav);
  662. ::lstrcpyn(szSendDir, szDirSav, count_of(szSendDir));
  663. if (::GetOpenFileName(&ofn))
  664. {
  665. // if there is only a single file, the first string is the full path.
  666. // if there are more than one file, the first string is the directory path
  667. // and followed by a list of file names. terminated by double null
  668. // remember the working directory for next time
  669. ULONG cchDirPath;
  670. LPTSTR pszFileName;
  671. ULONG cchFile = ::lstrlen(ofn.lpstrFile);
  672. if (TEXT('\0') == ofn.lpstrFile[cchFile] && TEXT('\0') == ofn.lpstrFile[cchFile+1])
  673. {
  674. //
  675. // only a single file
  676. //
  677. pszFileName = ::PathNameToFileName(ofn.lpstrFile);
  678. cchDirPath = (ULONG)(pszFileName - ofn.lpstrFile);
  679. if (cchDirPath)
  680. {
  681. cchDirPath--; // back to '\\'
  682. }
  683. ASSERT(TEXT('\\') == ofn.lpstrFile[cchDirPath]);
  684. ofn.lpstrFile[cchDirPath] = TEXT('\0');
  685. }
  686. else
  687. {
  688. //
  689. // multiple files
  690. //
  691. cchDirPath = ::lstrlen(ofn.lpstrFile);
  692. pszFileName = ofn.lpstrFile + cchDirPath + 1;
  693. }
  694. ::lstrcpy(m_szDefaultDir, ofn.lpstrFile);
  695. EnsureTrailingSlash(m_szDefaultDir);
  696. ::ZeroMemory(szSendDir, sizeof(szSendDir));
  697. ::CopyMemory(szSendDir, ofn.lpstrFile, cchDirPath * sizeof(TCHAR));
  698. EnsureTrailingSlash(szSendDir);
  699. // set up the common portion of list view item
  700. LVITEM lvi;
  701. ::ZeroMemory(&lvi, sizeof(lvi));
  702. // lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
  703. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  704. // iterate the file name
  705. while ('\0' != *pszFileName)
  706. {
  707. BOOL fRet;
  708. DBG_SAVE_FILE_LINE
  709. CUiSendFileInfo *pFileInfo = new CUiSendFileInfo(this, szSendDir, pszFileName, &fRet);
  710. if (NULL != pFileInfo && fRet)
  711. {
  712. // put it to the list view
  713. lvi.iItem = ListView_GetItemCount(m_hwndListView);
  714. lvi.iSubItem = 0;
  715. // we are responsible for storing the text to display
  716. lvi.pszText = LPSTR_TEXTCALLBACK;
  717. lvi.cchTextMax = MAX_PATH;
  718. lvi.lParam = (LPARAM) pFileInfo;
  719. int iRet = ListView_InsertItem(m_hwndListView, &lvi);
  720. ASSERT(-1 != iRet);
  721. // UpdateListView(pFileInfo);
  722. }
  723. else
  724. {
  725. delete pFileInfo;
  726. }
  727. // get to the next file name
  728. pszFileName += ::lstrlen(pszFileName) + 1;
  729. } // while
  730. }
  731. else
  732. {
  733. // err code for cancel is zero, which is ok.
  734. ASSERT(! ::CommDlgExtendedError());
  735. }
  736. // restore old working directory
  737. ::SetCurrentDirectory(szDirSav);
  738. }
  739. delete [] pszBuffer;
  740. m_fInFileOpenDialog = FALSE;
  741. }
  742. else
  743. {
  744. // bring the active dialog to the front
  745. BringToFront();
  746. }
  747. } // if LoadString
  748. }
  749. //
  750. // OnRemoveFiles
  751. //
  752. void CAppletWindow::OnRemoveFiles(void)
  753. {
  754. UINT nState;
  755. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  756. LVITEM lvi;
  757. ::ZeroMemory(&lvi, sizeof(lvi));
  758. lvi.mask = LVIF_PARAM | LVIF_STATE;
  759. lvi.stateMask = LVIS_SELECTED;
  760. ULONG i = 0;
  761. while (i < cItems)
  762. {
  763. lvi.iItem = i;
  764. BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
  765. if (fRet && lvi.state & LVIS_SELECTED)
  766. {
  767. CUiSendFileInfo *pFileInfo = (CUiSendFileInfo *) lvi.lParam;
  768. if (pFileInfo == m_pCurrSendFileInfo)
  769. {
  770. OnStopSending();
  771. ClearSendInfo(FALSE);
  772. }
  773. delete pFileInfo;
  774. fRet = ListView_DeleteItem(m_hwndListView, i);
  775. ASSERT(fRet);
  776. cItems--;
  777. ASSERT((ULONG) ListView_GetItemCount(m_hwndListView) == cItems);
  778. }
  779. else
  780. {
  781. i++;
  782. }
  783. }
  784. if (cItems > 0) // set focus to first remaining item
  785. {
  786. SetListViewFocus();
  787. }
  788. }
  789. void CAppletWindow::OnRemoveAllFiles(void)
  790. {
  791. BOOL fRet;
  792. CUiSendFileInfo *pFileInfo;
  793. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  794. LVITEM lvi;
  795. ::ZeroMemory(&lvi, sizeof(lvi));
  796. lvi.mask = LVIF_PARAM;
  797. for (ULONG i = 0; i < cItems; i++)
  798. {
  799. lvi.iItem = i;
  800. fRet = ListView_GetItem(m_hwndListView, &lvi);
  801. ASSERT(fRet);
  802. pFileInfo = (CUiSendFileInfo *) lvi.lParam;
  803. if (pFileInfo == m_pCurrSendFileInfo)
  804. {
  805. ClearSendInfo(FALSE);
  806. }
  807. delete pFileInfo;
  808. }
  809. fRet = ListView_DeleteAllItems(m_hwndListView);
  810. ASSERT(fRet);
  811. }
  812. void CAppletWindow::OnSendAll(void)
  813. {
  814. if ((NULL == m_pCurrSendFileInfo)&&(NULL != m_pEngine))
  815. {
  816. CUiSendFileInfo *pFileInfo = ChooseFirstUnSentFile();
  817. SendNow(pFileInfo);
  818. }
  819. }
  820. void CAppletWindow::OnSendOne(void)
  821. {
  822. if ((NULL == m_pCurrSendFileInfo)&&(NULL != m_pEngine))
  823. {
  824. CUiSendFileInfo *pFileInfo = ChooseSelectedFile();
  825. if (!pFileInfo)
  826. {
  827. pFileInfo = ChooseFirstUnSentFile();
  828. }
  829. SendNow(pFileInfo);
  830. }
  831. }
  832. //
  833. // SendNow
  834. //
  835. BOOL CAppletWindow::SendNow(CUiSendFileInfo *pFileInfo)
  836. {
  837. BOOL fRet;
  838. if (NULL != pFileInfo)
  839. {
  840. // send this file now...
  841. m_pCurrSendFileInfo = pFileInfo;
  842. m_nCurrSendEventHandle = ::GetNewEventHandle();
  843. pFileInfo->SetFileHandle(::GetNewFileHandle());
  844. // duplicate full file name
  845. ULONG cbSize = ::lstrlen(pFileInfo->GetFullName()) + 1;
  846. DBG_SAVE_FILE_LINE
  847. LPTSTR pszFullName = new TCHAR[cbSize];
  848. if (NULL != pszFullName)
  849. {
  850. ::CopyMemory(pszFullName, pFileInfo->GetFullName(), cbSize);
  851. DBG_SAVE_FILE_LINE
  852. if (S_OK == m_pEngine->SafePostMessage(
  853. new CreateSessionMsg(MBFT_PRIVATE_SEND_TYPE,
  854. m_nCurrSendEventHandle)))
  855. {
  856. int iSelect;
  857. MEMBER_ID nMemberID;
  858. iSelect = m_pToolbar->GetSelectedItem((LPARAM*)&nMemberID);
  859. if (0 == iSelect)
  860. { // Send to All
  861. DBG_SAVE_FILE_LINE
  862. if (S_OK == m_pEngine->SafePostMessage(
  863. new SubmitFileSendMsg(0, 0, pszFullName,
  864. pFileInfo->GetFileHandle(),
  865. m_nCurrSendEventHandle,
  866. FALSE)))
  867. {
  868. return TRUE;
  869. }
  870. else
  871. {
  872. ERROR_OUT(("CAppletWindow::SendNow: cannot create SubmitFileSendMsg"));
  873. }
  874. }
  875. else
  876. { // Send to one
  877. T120UserID uidRecv = GET_PEER_ID_FROM_MEMBER_ID(nMemberID);
  878. DBG_SAVE_FILE_LINE
  879. if (S_OK == m_pEngine->SafePostMessage(
  880. new SubmitFileSendMsg(uidRecv, 0, pszFullName,
  881. pFileInfo->GetFileHandle(),
  882. m_nCurrSendEventHandle,
  883. FALSE)))
  884. {
  885. return TRUE;
  886. }
  887. else
  888. {
  889. ERROR_OUT(("CAppletWindow::SendNow: cannot create SubmitFileSendMsg to 1"));
  890. }
  891. }
  892. }
  893. else
  894. {
  895. ERROR_OUT(("CAppletWindow::SendNow: cannot create CreateSessionMsg"));
  896. }
  897. delete [] pszFullName;
  898. }
  899. ClearSendInfo(TRUE);
  900. }
  901. return FALSE;
  902. }
  903. CUiSendFileInfo *CAppletWindow::ChooseFirstUnSentFile(void)
  904. {
  905. CUiSendFileInfo *pFileInfo = NULL;
  906. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  907. if (cItems > 0)
  908. {
  909. // examine each item one by one
  910. LVITEM lvi;
  911. ::ZeroMemory(&lvi, sizeof(lvi));
  912. lvi.mask = LVIF_PARAM;
  913. for (ULONG i = 0; i < cItems; i++, pFileInfo = NULL)
  914. {
  915. lvi.iItem = i;
  916. BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
  917. ASSERT(fRet);
  918. pFileInfo = (CUiSendFileInfo *) lvi.lParam;
  919. // if file handle is not zero, then it has been sent
  920. if (! pFileInfo->GetFileHandle())
  921. {
  922. break;
  923. }
  924. }
  925. }
  926. return pFileInfo;
  927. }
  928. CUiSendFileInfo *CAppletWindow::ChooseSelectedFile(void)
  929. {
  930. CUiSendFileInfo *pFileInfo = NULL;
  931. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  932. LVITEM lvi;
  933. ::ZeroMemory(&lvi, sizeof(lvi));
  934. lvi.mask = LVIF_PARAM | LVIF_STATE;
  935. lvi.stateMask = LVIS_SELECTED;
  936. ULONG i = 0;
  937. while (i < cItems)
  938. {
  939. lvi.iItem = i;
  940. BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
  941. if (fRet && lvi.state & LVIS_SELECTED)
  942. {
  943. pFileInfo = (CUiSendFileInfo *) lvi.lParam;
  944. pFileInfo->SetErrorCode(iMBFT_OK);
  945. break;
  946. }
  947. else
  948. {
  949. i++;
  950. pFileInfo = NULL;
  951. }
  952. }
  953. return pFileInfo;
  954. }
  955. //
  956. // OnMenuSelect
  957. //
  958. void CAppletWindow::OnMenuSelect(UINT uiItemID, UINT uiFlags, HMENU hSysMenu)
  959. {
  960. UINT firstMenuId;
  961. UINT statusId;
  962. //
  963. // Work out the help ID for the menu item. We have to store this now
  964. // because when the user presses F1 from a menu item, we can't tell
  965. // which item it was.
  966. //
  967. if ((uiFlags & MF_POPUP) && (uiFlags & MF_SYSMENU))
  968. {
  969. // System menu selected
  970. statusId = (m_pCurrSendFileInfo)?IDS_STBAR_SENDING_XYZ:IDS_STBAR_NOT_TRANSFERING;
  971. }
  972. else if (uiFlags & MF_POPUP)
  973. {
  974. // get popup menu handle and first item
  975. HMENU hPopup = ::GetSubMenu( hSysMenu, uiItemID );
  976. firstMenuId = ::GetMenuItemID( hPopup, 0 );
  977. switch(firstMenuId)
  978. {
  979. case IDM_ADD_FILES:
  980. statusId = IDS_MENU_FILE;
  981. break;
  982. case IDM_HELP:
  983. statusId = IDS_MENU_HELP;
  984. break;
  985. default:
  986. statusId = (m_pCurrSendFileInfo)?IDS_STBAR_SENDING_XYZ:IDS_STBAR_NOT_TRANSFERING;
  987. }
  988. }
  989. else
  990. {
  991. // A normal menu item has been selected
  992. statusId = uiItemID;
  993. }
  994. // Set the new help text
  995. TCHAR szStatus[256];
  996. if (::LoadString(g_hDllInst, statusId, szStatus, 256))
  997. {
  998. ::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_TRANSFER_FILE, (LPARAM)szStatus);
  999. }
  1000. }
  1001. //
  1002. // OnStopSending
  1003. //
  1004. void CAppletWindow::OnStopSending(void)
  1005. {
  1006. m_fSendALL = FALSE;
  1007. if (m_nCurrSendEventHandle)
  1008. {
  1009. DBG_SAVE_FILE_LINE
  1010. HRESULT hr = m_pEngine->SafePostMessage(
  1011. new FileTransferControlMsg(
  1012. m_nCurrSendEventHandle,
  1013. m_pCurrSendFileInfo->GetFileHandle(),
  1014. NULL,
  1015. NULL,
  1016. FileTransferControlMsg::EnumAbortFile));
  1017. ASSERT(hr == S_OK);
  1018. }
  1019. }
  1020. //
  1021. // OnOpenRecvFolder
  1022. //
  1023. void CAppletWindow::OnOpenRecvFolder(void)
  1024. {
  1025. TCHAR szRecvFolder[MAX_PATH];
  1026. while (1)
  1027. {
  1028. if (S_OK == ::GetRecvFolder(NULL, szRecvFolder))
  1029. {
  1030. ::ShellExecute(NULL, NULL, szRecvFolder, NULL, NULL, SW_SHOWNORMAL);
  1031. break;
  1032. }
  1033. else if (m_UIMode != FTUIMODE_NOUI)
  1034. {
  1035. ::MyLoadString(IDS_RECVDLG_DIRNOEXIST, s_szScratchText, szRecvFolder);
  1036. if (IDYES == ::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_YESNO))
  1037. {
  1038. OnChangeFolder();
  1039. }
  1040. else
  1041. {
  1042. break;
  1043. }
  1044. }
  1045. }
  1046. }
  1047. //
  1048. // OnChageFolder
  1049. //
  1050. void OnChangeFolder(void)
  1051. {
  1052. BOOL rc;
  1053. TCHAR szPath[MAX_PATH];
  1054. ::GetRecvFolder(NULL, szPath);
  1055. if (::lstrlen(szPath) > MAX_FILE_NAME_LENGTH)
  1056. {
  1057. LPTSTR psz = szPath;
  1058. int i = MAX_FILE_NAME_LENGTH - 1;
  1059. while (i)
  1060. {
  1061. psz = CharNext(psz);
  1062. i--;
  1063. }
  1064. ::lstrcpy(psz, TEXT("..."));
  1065. }
  1066. ::MyLoadString(IDS_BROWSETITLE, s_szScratchText, szPath);
  1067. if (FBrowseForFolder(szPath, CCHMAX(szPath), s_szScratchText))
  1068. {
  1069. ::GetRecvFolder(szPath, szPath);
  1070. }
  1071. }
  1072. //
  1073. // OnExit
  1074. //
  1075. void CAppletWindow::OnExit(BOOL fNoQuery)
  1076. {
  1077. if ((g_pFileXferApplet->InConf() || g_pFileXferApplet->HasSDK())
  1078. && ! g_fShutdownByT120)
  1079. {
  1080. // There 2.x node inside the conference
  1081. // hide the window
  1082. ::ShowWindow(m_hwndMainUI, SW_HIDE);
  1083. m_UIMode = g_fNoUI ? FTUIMODE_NOUI : FTUIMODE_UIHIDDEN;
  1084. }
  1085. else
  1086. if (fNoQuery || QueryShutdown())
  1087. {
  1088. #if defined(TEST_PLUGABLE) && defined(_DEBUG)
  1089. ::OnPluggableEnd();
  1090. #endif
  1091. MBFTEngine *pEngine = m_pEngine;
  1092. ::T120_AppletStatus(APPLET_ID_FT, APPLET_CLOSING);
  1093. if (NULL != m_pEngine)
  1094. {
  1095. GCCAppPermissionToEnrollInd Ind;
  1096. ::ZeroMemory(&Ind, sizeof(Ind));
  1097. Ind.nConfID = m_pEngine->GetConfID();
  1098. Ind.fPermissionGranted = FALSE;
  1099. m_pEngine->OnPermitToEnrollIndication(&Ind);
  1100. UnregisterEngine();
  1101. }
  1102. OnRemoveAllFiles();
  1103. ::SetWindowLongPtr(m_hwndMainUI, GWLP_USERDATA, 0);
  1104. SaveWindowPosition();
  1105. HWND hwnd = m_hwndMainUI;
  1106. m_hwndMainUI = NULL;
  1107. ::DestroyWindow(hwnd);
  1108. if (NULL != g_pFileXferApplet)
  1109. {
  1110. g_pFileXferApplet->UnregisterWindow(this);
  1111. g_pFileXferApplet->UnregisterEngine(pEngine);
  1112. }
  1113. Release();
  1114. }
  1115. }
  1116. //
  1117. // OnHelp
  1118. //
  1119. void CAppletWindow::OnHelp(void)
  1120. {
  1121. DebugEntry(CAppletWindow::OnHelp);
  1122. ShowNmHelp(s_cszHtmlHelpFile);
  1123. DebugExitVOID(CAppletWindow::OnHelp);
  1124. }
  1125. //
  1126. // OnAbout
  1127. //
  1128. INT_PTR AboutDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1129. {
  1130. BOOL fHandled = FALSE;
  1131. switch (uMsg)
  1132. {
  1133. case WM_INITDIALOG:
  1134. {
  1135. TCHAR szFormat[256];
  1136. TCHAR szVersion[512];
  1137. ::GetDlgItemText(hdlg, IDC_ABOUT_VERSION, szFormat, count_of(szFormat));
  1138. ::wsprintf(szVersion, szFormat, VER_PRODUCTRELEASE_STR,
  1139. VER_PRODUCTVERSION_STR);
  1140. ::SetDlgItemText(hdlg, IDC_ABOUT_VERSION, szVersion);
  1141. fHandled = TRUE;
  1142. }
  1143. break;
  1144. case WM_COMMAND:
  1145. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1146. {
  1147. case IDOK:
  1148. case IDCANCEL:
  1149. case IDCLOSE:
  1150. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  1151. {
  1152. case BN_CLICKED:
  1153. ::EndDialog(hdlg, IDCANCEL);
  1154. break;
  1155. }
  1156. break;
  1157. }
  1158. fHandled = TRUE;
  1159. break;
  1160. }
  1161. return(fHandled);
  1162. }
  1163. void CAppletWindow::OnAbout(void)
  1164. {
  1165. ::DialogBoxParam(g_hDllInst, MAKEINTRESOURCE(IDD_ABOUTBOX), m_hwndMainUI,
  1166. AboutDlgProc, 0);
  1167. }
  1168. BOOL FBrowseForFolder(LPTSTR pszFolder, UINT cchMax, LPCTSTR pszTitle)
  1169. {
  1170. LPITEMIDLIST pidlRoot;
  1171. if(FAILED(SHGetSpecialFolderLocation(HWND_DESKTOP, CSIDL_DRIVES, &pidlRoot)))
  1172. {
  1173. return FALSE;
  1174. }
  1175. BROWSEINFO bi;
  1176. ClearStruct(&bi);
  1177. bi.hwndOwner = NULL;
  1178. bi.lpszTitle = pszTitle;
  1179. bi.ulFlags = BIF_RETURNONLYFSDIRS;
  1180. bi.pidlRoot = pidlRoot;
  1181. LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
  1182. BOOL fRet = (pidl != NULL);
  1183. if (fRet)
  1184. {
  1185. ASSERT(cchMax >= MAX_PATH);
  1186. SHGetPathFromIDList(pidl, pszFolder);
  1187. ASSERT(lstrlen(pszFolder) < (int) cchMax);
  1188. }
  1189. // Get the shell's allocator to free PIDLs
  1190. LPMALLOC lpMalloc;
  1191. if (FAILED(SHGetMalloc(&lpMalloc)) && (NULL != lpMalloc))
  1192. {
  1193. if (NULL != pidlRoot)
  1194. {
  1195. lpMalloc->Free(pidlRoot);
  1196. }
  1197. if (pidl)
  1198. {
  1199. lpMalloc->Free(pidl);
  1200. }
  1201. lpMalloc->Release();
  1202. }
  1203. return fRet;
  1204. }
  1205. /////////////////////////////////////////////////////////////////
  1206. //
  1207. // WM_NOTIFY
  1208. //
  1209. LRESULT OnNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1210. {
  1211. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1212. if (NULL != pWindow)
  1213. {
  1214. switch (wParam)
  1215. {
  1216. case IDC_LIST_VIEW:
  1217. pWindow->OnNotifyListView(lParam);
  1218. break;
  1219. default:
  1220. if (TTN_NEEDTEXT == ((NMHDR *) lParam)->code)
  1221. {
  1222. // display the tool tip text
  1223. TOOLTIPTEXT *pToolTipText = (TOOLTIPTEXT *) lParam;
  1224. ULONG_PTR nID;
  1225. // get id and hwnd
  1226. if (pToolTipText->uFlags & TTF_IDISHWND)
  1227. {
  1228. // idFrom is actually the HWND of the tool
  1229. nID = ::GetDlgCtrlID((HWND) pToolTipText->hdr.idFrom);
  1230. }
  1231. else
  1232. {
  1233. nID = pToolTipText->hdr.idFrom;
  1234. }
  1235. // give it to em
  1236. pToolTipText->lpszText = MAKEINTRESOURCE(nID);
  1237. pToolTipText->hinst = g_hDllInst;
  1238. }
  1239. break;
  1240. }
  1241. }
  1242. return 0;
  1243. }
  1244. int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  1245. {
  1246. CUiSendFileInfo *pFileInfo1 = (CUiSendFileInfo *) lParam1;
  1247. CUiSendFileInfo *pFileInfo2 = (CUiSendFileInfo *) lParam2;
  1248. int iResult;
  1249. iResult = 0; // equal, at default
  1250. switch (lParamSort)
  1251. {
  1252. case (IDS_LV_FILE_NAME - IDS_LV_FILE_NAME):
  1253. iResult = lstrcmpi(pFileInfo1->GetName(), pFileInfo2->GetName());
  1254. break;
  1255. case (IDS_LV_FILE_SIZE - IDS_LV_FILE_NAME):
  1256. if (pFileInfo1->GetSize() > pFileInfo2->GetSize())
  1257. {
  1258. iResult = 1;
  1259. }
  1260. else
  1261. if (pFileInfo1->GetSize() < pFileInfo2->GetSize())
  1262. {
  1263. iResult = -1;
  1264. }
  1265. break;
  1266. case (IDS_LV_FILE_STATUS - IDS_LV_FILE_NAME):
  1267. if ((pFileInfo1->GetTotalSend() == pFileInfo1->GetSize()) >( pFileInfo2->GetTotalSend() == pFileInfo2->GetSize()))
  1268. {
  1269. iResult = 1;
  1270. }
  1271. else
  1272. if ((pFileInfo1->GetTotalSend() == pFileInfo1->GetSize()) < (pFileInfo2->GetTotalSend() == pFileInfo2->GetSize()))
  1273. {
  1274. iResult = -1;
  1275. }
  1276. break;
  1277. case (IDS_LV_FILE_MODIFIED - IDS_LV_FILE_NAME):
  1278. FILETIME fTime1 = pFileInfo1->GetLastWrite();
  1279. FILETIME fTime2 = pFileInfo2->GetLastWrite();
  1280. iResult = CompareFileTime(&fTime1,&fTime2);
  1281. break;
  1282. }
  1283. return iResult*s_sort;
  1284. }
  1285. void CAppletWindow::OnNotifyListView(LPARAM lParam)
  1286. {
  1287. LV_DISPINFO *pDispInfo = (LV_DISPINFO *) lParam;
  1288. NM_LISTVIEW *pLVN = (NM_LISTVIEW *) lParam;
  1289. FILETIME ftFileTime;
  1290. SYSTEMTIME stSystemTime;
  1291. CUiSendFileInfo *pFileInfo;
  1292. int iSize;
  1293. TCHAR szBuffer[MAX_PATH];
  1294. switch (pLVN->hdr.code)
  1295. {
  1296. case LVN_GETDISPINFO:
  1297. pFileInfo = (CUiSendFileInfo *) pDispInfo->item.lParam;
  1298. ASSERT(NULL != pFileInfo);
  1299. switch (pDispInfo->item.iSubItem)
  1300. {
  1301. case (IDS_LV_FILE_NAME - IDS_LV_FILE_NAME):
  1302. pDispInfo->item.pszText = pFileInfo->GetName();
  1303. break;
  1304. case (IDS_LV_FILE_SIZE - IDS_LV_FILE_NAME):
  1305. ::wsprintf(szBuffer, TEXT("%u"), pFileInfo->GetSize());
  1306. iSize = GetNumberFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE,
  1307. szBuffer, NULL, s_szScratchText, MAX_PATH);
  1308. s_szScratchText[iSize - 4] = '\0'; // remove the trailing ".00"
  1309. pDispInfo->item.pszText = s_szScratchText;
  1310. break;
  1311. case (IDS_LV_FILE_STATUS - IDS_LV_FILE_NAME):
  1312. {
  1313. ULONG cbTotalSend = pFileInfo->GetTotalSend();
  1314. ULONG cbFileSize = pFileInfo->GetSize();
  1315. s_szScratchText[0] = TEXT('\0');
  1316. switch (pFileInfo->GetErrorCode())
  1317. {
  1318. case iMBFT_OK:
  1319. case iMBFT_MULT_RECEIVER_ABORTED:
  1320. if (!pFileInfo->GetFileHandle())
  1321. break; // handle == NULL, if cbTotalSend == 0, zero length file to be sent.
  1322. if (cbTotalSend >= cbFileSize)
  1323. {
  1324. ::MyLoadString(IDS_LV_FILE_SENT);
  1325. }
  1326. else
  1327. if (cbTotalSend)
  1328. {
  1329. if (m_pEngine)
  1330. {
  1331. ::MyLoadString(IDS_LV_FILE_SENDING);
  1332. }
  1333. else
  1334. {
  1335. ::MyLoadString(IDS_LV_FILE_CANCELED);
  1336. }
  1337. }
  1338. break;
  1339. case iMBFT_SENDER_ABORTED:
  1340. case iMBFT_RECEIVER_ABORTED:
  1341. case iMBFT_NO_MORE_FILES:
  1342. ::MyLoadString(IDS_LV_FILE_CANCELED);
  1343. break;
  1344. default:
  1345. ::MyLoadString(IDS_LV_FILE_FAILED);
  1346. break;
  1347. }
  1348. pDispInfo->item.pszText = s_szScratchText;
  1349. }
  1350. break;
  1351. case (IDS_LV_FILE_MODIFIED - IDS_LV_FILE_NAME):
  1352. ftFileTime = pFileInfo->GetLastWrite();
  1353. FileTimeToSystemTime(&ftFileTime, &stSystemTime);
  1354. iSize = GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &stSystemTime,
  1355. "MM'/'dd'/'yyyy", s_szScratchText, MAX_PATH);
  1356. GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &stSystemTime,
  1357. " hh':'mm tt", &s_szScratchText[iSize - 1], MAX_PATH-iSize-1);
  1358. pDispInfo->item.pszText = s_szScratchText;
  1359. break;
  1360. }
  1361. break;
  1362. case LVN_COLUMNCLICK:
  1363. {
  1364. s_sort = s_sort *(-1);
  1365. BOOL fRet = ListView_SortItems(pLVN->hdr.hwndFrom, ListViewCompareProc, (LPARAM) pLVN->iSubItem);
  1366. ASSERT(fRet);
  1367. }
  1368. break;
  1369. }
  1370. }
  1371. /////////////////////////////////////////////////////////////////
  1372. //
  1373. // WM_DROPFILES
  1374. //
  1375. LRESULT OnDropFiles(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1376. {
  1377. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1378. ASSERT(NULL != pWindow);
  1379. if (g_fSendAllowed)
  1380. {
  1381. return pWindow->OnDropFiles((HANDLE) wParam);
  1382. }
  1383. else
  1384. {
  1385. ::MyLoadString(IDS_MSGBOX_POL_PREVENT);
  1386. ::MessageBox(pWindow->GetHwnd(), s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
  1387. return 1;
  1388. }
  1389. }
  1390. LRESULT CAppletWindow::OnDropFiles(HANDLE hDrop)
  1391. {
  1392. if (NULL != m_pEngine && m_pEngine->GetPeerCount() > 1)
  1393. {
  1394. HRESULT hr;
  1395. // get the number of dropped files
  1396. ULONG cFiles = ::DragQueryFile((HDROP) hDrop, 0xFFFFFFFF, NULL, 0);
  1397. // set up the common portion of list view item
  1398. LVITEM lvi;
  1399. ::ZeroMemory(&lvi, sizeof(lvi));
  1400. // lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
  1401. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  1402. // iterate on these files
  1403. for (ULONG i = 0; i < cFiles; i++)
  1404. {
  1405. BOOL fRet;
  1406. TCHAR szFile[MAX_PATH];
  1407. if (::DragQueryFile((HDROP) hDrop, i, szFile, count_of(szFile)))
  1408. {
  1409. DBG_SAVE_FILE_LINE
  1410. CUiSendFileInfo *pFileInfo = new CUiSendFileInfo(this, NULL, szFile, &fRet);
  1411. if (NULL != pFileInfo && fRet)
  1412. {
  1413. // put it to the list view
  1414. lvi.iItem = ListView_GetItemCount(m_hwndListView);
  1415. lvi.iSubItem = 0;
  1416. // we are responsible for storing the text to display
  1417. lvi.pszText = LPSTR_TEXTCALLBACK;
  1418. lvi.cchTextMax = MAX_PATH;
  1419. lvi.lParam = (LPARAM) pFileInfo;
  1420. int iRet = ListView_InsertItem(m_hwndListView, &lvi);
  1421. ASSERT(-1 != iRet);
  1422. // UpdateListView(pFileInfo);
  1423. }
  1424. else
  1425. {
  1426. // BUGBUG: we should pop up some error message box here!
  1427. ::MyLoadString(IDS_INVALID_FILENAME, s_szScratchText, szFile);
  1428. ::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
  1429. delete pFileInfo;
  1430. }
  1431. }
  1432. }
  1433. ::DragFinish((HDROP) hDrop);
  1434. SetForegroundWindow(m_hwndMainUI);
  1435. UpdateUI();
  1436. return 0;
  1437. }
  1438. ::MyLoadString(IDS_MSGBOX_NO_CONF);
  1439. ::SetForegroundWindow(m_hwndMainUI);
  1440. ::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
  1441. return 1;
  1442. }
  1443. /////////////////////////////////////////////////////////////////
  1444. //
  1445. // WM_CONTEXTMENU
  1446. //
  1447. LRESULT OnContextMenu(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1448. {
  1449. LRESULT rc = 0;
  1450. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1451. ASSERT(NULL != pWindow);
  1452. if ((WPARAM) pWindow->GetHwnd() == wParam)
  1453. {
  1454. // BUGBUG use TrackPopupMenu to show context sensitive menu
  1455. pWindow->OnContextMenuForMainUI(lParam);
  1456. }
  1457. else
  1458. if ((WPARAM) pWindow->GetListView() == wParam)
  1459. {
  1460. // BUGBUG use TrackPopupMenu to show context sensitive menu
  1461. pWindow->OnContextMenuForListView(lParam);
  1462. }
  1463. else
  1464. {
  1465. rc = 1;
  1466. }
  1467. return rc;
  1468. }
  1469. enum
  1470. {
  1471. MENU_IDX_ADD_FILES,
  1472. MENU_IDX_REMOVE_FILES,
  1473. MENU_IDX_BREAK_1,
  1474. MENU_IDX_SEND_ALL,
  1475. MENU_IDX_SEND_ONE,
  1476. MENU_IDX_STOP_SENDING,
  1477. MENU_IDX_BREAK_2,
  1478. MENU_IDX_OPEN_RECV_FOLDER,
  1479. };
  1480. static UI_MENU_INFO s_aMenuInfo[] =
  1481. {
  1482. { IDS_MENU_ADD_FILES, IDM_ADD_FILES, MF_ENABLED | MF_STRING },
  1483. { IDS_MENU_REMOVE_FILES, IDM_REMOVE_FILES, MF_ENABLED | MF_STRING },
  1484. { 0, 0, MF_SEPARATOR}, // menu break
  1485. { IDS_MENU_SEND_ALL, IDM_SEND_ALL, MF_ENABLED | MF_STRING },
  1486. { IDS_MENU_SEND_ONE, IDM_SEND_ONE, MF_ENABLED | MF_STRING },
  1487. { IDS_MENU_STOP_SENDING, IDM_STOP_SENDING, MF_ENABLED | MF_STRING },
  1488. { 0, 0, MF_SEPARATOR}, // menu break
  1489. { IDS_MENU_OPEN_RECV_FOLDER, IDM_OPEN_RECV_FOLDER, MF_ENABLED | MF_STRING },
  1490. { IDS_MENU_CHANGE_FOLDER, IDM_CHANGE_FOLDER, MF_ENABLED | MF_STRING },
  1491. { 0, 0, MF_SEPARATOR }, // menu break
  1492. { IDS_MENU_EXIT, IDM_EXIT, MF_ENABLED | MF_STRING },
  1493. };
  1494. void CAppletWindow::SetContextMenuStates(void)
  1495. {
  1496. if (g_fSendAllowed)
  1497. {
  1498. BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
  1499. s_aMenuInfo[MENU_IDX_ADD_FILES].nFlags = fMoreThanOne ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
  1500. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  1501. s_aMenuInfo[MENU_IDX_REMOVE_FILES].nFlags = cItems ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
  1502. s_aMenuInfo[MENU_IDX_SEND_ALL].nFlags = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
  1503. s_aMenuInfo[MENU_IDX_SEND_ONE].nFlags = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(FALSE)) ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
  1504. s_aMenuInfo[MENU_IDX_STOP_SENDING].nFlags = m_nCurrSendEventHandle ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
  1505. }
  1506. else
  1507. {
  1508. s_aMenuInfo[MENU_IDX_ADD_FILES].nFlags =(MF_GRAYED | MF_STRING);
  1509. s_aMenuInfo[MENU_IDX_REMOVE_FILES].nFlags =(MF_GRAYED | MF_STRING);
  1510. s_aMenuInfo[MENU_IDX_SEND_ALL].nFlags = (MF_GRAYED | MF_STRING);
  1511. s_aMenuInfo[MENU_IDX_SEND_ONE].nFlags = (MF_GRAYED | MF_STRING);
  1512. s_aMenuInfo[MENU_IDX_STOP_SENDING].nFlags = (MF_GRAYED | MF_STRING);
  1513. }
  1514. }
  1515. void CAppletWindow::OnContextMenuForMainUI(LPARAM lParam)
  1516. {
  1517. SetContextMenuStates();
  1518. CreateMenu(lParam, count_of(s_aMenuInfo), &s_aMenuInfo[0]);
  1519. }
  1520. void CAppletWindow::OnContextMenuForListView(LPARAM lParam)
  1521. {
  1522. SetContextMenuStates();
  1523. CreateMenu(lParam, 6, &s_aMenuInfo[0]);
  1524. }
  1525. void CAppletWindow::CreateMenu(LPARAM lParam, ULONG cItems, UI_MENU_INFO aMenuInfo[])
  1526. {
  1527. HMENU hMenu = ::CreatePopupMenu();
  1528. if (NULL != hMenu)
  1529. {
  1530. for (ULONG i = 0; i < cItems; i++)
  1531. {
  1532. if (aMenuInfo[i].idCommand)
  1533. {
  1534. if (::MyLoadString(aMenuInfo[i].idString))
  1535. {
  1536. ::AppendMenu(hMenu, aMenuInfo[i].nFlags, aMenuInfo[i].idCommand, s_szScratchText);
  1537. }
  1538. }
  1539. else
  1540. {
  1541. ::AppendMenu(hMenu, aMenuInfo[i].nFlags, 0, 0);
  1542. }
  1543. }
  1544. ::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON,
  1545. GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
  1546. 0, // reserved, must be zero
  1547. m_hwndMainUI,
  1548. NULL); // ignore
  1549. }
  1550. }
  1551. /////////////////////////////////////////////////////////////////
  1552. //
  1553. // WM_SIZE
  1554. //
  1555. LRESULT OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1556. {
  1557. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1558. ASSERT(NULL != pWindow);
  1559. pWindow->OnSizeToolBar();
  1560. pWindow->OnSizeStatusBar();
  1561. pWindow->OnSizeListView();
  1562. return 0;
  1563. }
  1564. void CAppletWindow::OnSizeToolBar(void)
  1565. {
  1566. RECT rcWindow;
  1567. SIZE szToolBar;
  1568. ::GetClientRect(m_hwndMainUI, &rcWindow);
  1569. m_pToolbar->GetDesiredSize(&szToolBar);
  1570. ULONG cx = rcWindow.right - rcWindow.left;
  1571. ULONG cy = szToolBar.cy;;
  1572. ULONG x = 0;
  1573. ULONG y = 0;
  1574. ::MoveWindow(m_pToolbar->GetWindow(), x, y, cx, cy, TRUE);
  1575. }
  1576. void CAppletWindow::OnSizeStatusBar(void)
  1577. {
  1578. RECT rcWindow, rcStatusBar;
  1579. ::GetClientRect(m_hwndMainUI, &rcWindow);
  1580. ::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
  1581. ULONG cx = rcWindow.right - rcWindow.left;
  1582. ULONG cy = rcStatusBar.bottom - rcStatusBar.top;
  1583. ULONG x = 0;
  1584. ULONG y = rcWindow.bottom - cy;
  1585. ::MoveWindow(m_hwndStatusBar, x, y, cx, cy, TRUE);
  1586. ::MoveWindow(m_hwndProgressBar, x + cx/2, y, cx/2 - 40, cy, TRUE);
  1587. int aWidths[NUM_STATUS_BAR_PARTS];
  1588. aWidths[0] = cx / 2; // conference state
  1589. aWidths[1] = cx - 40; // transfer name
  1590. aWidths[2] = -1; // transfer percentage
  1591. ASSERT(3 == NUM_STATUS_BAR_PARTS);
  1592. ::SendMessage(m_hwndStatusBar, SB_SETPARTS, NUM_STATUS_BAR_PARTS, (LPARAM) &aWidths[0]);
  1593. }
  1594. void CAppletWindow::OnSizeListView(void)
  1595. {
  1596. // get the size and position of the main window
  1597. RECT rcWindow, rcToolBar, rcStatusBar;
  1598. SIZE szToolBar;
  1599. ::GetClientRect(m_hwndMainUI, &rcWindow);
  1600. m_pToolbar->GetDesiredSize(&szToolBar);
  1601. ::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
  1602. ULONG x = 0;
  1603. ULONG y = szToolBar.cy - 1;
  1604. ULONG cx = rcWindow.right - rcWindow.left;
  1605. ULONG cy = rcWindow.bottom - rcWindow.top - y - (rcStatusBar.bottom - rcStatusBar.top) + 1;
  1606. ::MoveWindow(m_hwndListView, x, y, cx, cy, TRUE);
  1607. }
  1608. /////////////////////////////////////////////////////////////////
  1609. //
  1610. // WM_HELP
  1611. //
  1612. LRESULT OnHelp(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1613. {
  1614. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1615. ASSERT(NULL != pWindow);
  1616. pWindow->OnHelp();
  1617. return 0;
  1618. }
  1619. /////////////////////////////////////////////////////////////////
  1620. //
  1621. // WM_CLOSE
  1622. //
  1623. LRESULT OnClose(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1624. {
  1625. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1626. ASSERT(NULL != pWindow);
  1627. if (NULL != pWindow)
  1628. {
  1629. pWindow->OnExit();
  1630. }
  1631. return 0;
  1632. }
  1633. /////////////////////////////////////////////////////////////////
  1634. //
  1635. // WM_INITMENUPOPUP
  1636. //
  1637. /*
  1638. LRESULT OnInitMenuPopup(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1639. {
  1640. if (0 != HIWORD(lParam)) // System menu flag
  1641. {
  1642. HMENU hMenu = (HMENU) wParam; // handle of pop-up menu
  1643. ::EnableMenuItem(hMenu, SC_MAXIMIZE, MF_GRAYED);
  1644. ::EnableMenuItem(hMenu, SC_SIZE, MF_GRAYED);
  1645. return 0;
  1646. }
  1647. return 1;
  1648. }
  1649. */
  1650. /////////////////////////////////////////////////////////////////
  1651. //
  1652. // WM_MENUSELECT
  1653. //
  1654. LRESULT OnMenuSelect(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1655. {
  1656. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1657. ASSERT(NULL != pWindow);
  1658. if (NULL != pWindow)
  1659. {
  1660. pWindow->OnMenuSelect(GET_WM_MENUSELECT_CMD(wParam, lParam),
  1661. GET_WM_MENUSELECT_FLAGS(wParam, lParam),
  1662. GET_WM_MENUSELECT_HMENU(wParam, lParam));
  1663. }
  1664. return 0;
  1665. }
  1666. /////////////////////////////////////////////////////////////////
  1667. //
  1668. // WM_INITMENUPOPUP
  1669. //
  1670. LRESULT OnGetMinMaxInfo(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1671. {
  1672. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1673. if (NULL != pWindow)
  1674. {
  1675. pWindow->OnGetMinMaxInfo((LPMINMAXINFO) lParam);
  1676. return 0;
  1677. }
  1678. return 1;
  1679. }
  1680. void CAppletWindow::OnGetMinMaxInfo(LPMINMAXINFO pMMI)
  1681. {
  1682. static BOOL s_fEnterBefore = FALSE;
  1683. static SIZE s_csFrame;
  1684. static SIZE s_csSeparator;
  1685. static SIZE s_csScrollBars;
  1686. static SIZE s_csToolBar;
  1687. static SIZE s_csStatusBar;
  1688. static SIZE s_csSum;
  1689. if (! s_fEnterBefore)
  1690. {
  1691. s_fEnterBefore = TRUE;
  1692. s_csFrame.cx = ::GetSystemMetrics(SM_CXSIZEFRAME);
  1693. s_csFrame.cy = ::GetSystemMetrics(SM_CYSIZEFRAME);
  1694. s_csSeparator.cx = ::GetSystemMetrics(SM_CXEDGE);
  1695. s_csSeparator.cy = ::GetSystemMetrics(SM_CYEDGE);
  1696. s_csScrollBars.cx = ::GetSystemMetrics(SM_CXVSCROLL);
  1697. s_csScrollBars.cy = ::GetSystemMetrics(SM_CYHSCROLL);
  1698. m_pToolbar->GetDesiredSize(&s_csToolBar);
  1699. RECT rcStatusBar;
  1700. ::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
  1701. s_csStatusBar.cx = rcStatusBar.right - rcStatusBar.left;
  1702. s_csStatusBar.cy = rcStatusBar.bottom - rcStatusBar.top;
  1703. s_csSum.cx = (s_csFrame.cx << 1);
  1704. s_csSum.cy = (s_csFrame.cy << 1) + (s_csSeparator.cy << 3) +
  1705. s_csToolBar.cy + (rcStatusBar.bottom - rcStatusBar.top) +
  1706. ::GetSystemMetrics( SM_CYCAPTION ) + ::GetSystemMetrics( SM_CYMENU );
  1707. }
  1708. RECT rcListViewItem;
  1709. SIZE csListView;
  1710. csListView.cx = 0;
  1711. for (ULONG i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
  1712. {
  1713. csListView.cx += ListView_GetColumnWidth(m_hwndListView, i);
  1714. }
  1715. if (ListView_GetItemRect(m_hwndListView, 0, &rcListViewItem, LVIR_BOUNDS))
  1716. {
  1717. csListView.cy = 20 + 3 * (rcListViewItem.bottom - rcListViewItem.top);
  1718. }
  1719. else
  1720. {
  1721. csListView.cy = 20 + 30;
  1722. }
  1723. // Set the minimum width and height of the window
  1724. pMMI->ptMinTrackSize.x = s_csSum.cx + max(s_csToolBar.cx, csListView.cx);
  1725. pMMI->ptMinTrackSize.y = s_csSum.cy + csListView.cy;
  1726. //
  1727. // Retrieves the size of the work area on the primary display monitor. The work
  1728. // area is the portion of the screen not obscured by the system taskbar or by
  1729. // application desktop toolbars
  1730. //
  1731. RECT rcWorkArea;
  1732. ::SystemParametersInfo( SPI_GETWORKAREA, 0, (&rcWorkArea), NULL );
  1733. SIZE csMaxSize;
  1734. csMaxSize.cx = rcWorkArea.right - rcWorkArea.left;
  1735. csMaxSize.cy = rcWorkArea.bottom - rcWorkArea.top;
  1736. pMMI->ptMaxPosition.x = 0;
  1737. pMMI->ptMaxPosition.y = 0;
  1738. pMMI->ptMaxSize.x = csMaxSize.cx;
  1739. pMMI->ptMaxSize.y = csMaxSize.cy;
  1740. pMMI->ptMaxTrackSize.x = csMaxSize.cx;
  1741. pMMI->ptMaxTrackSize.y = csMaxSize.cy;
  1742. }
  1743. /////////////////////////////////////////////////////////////////
  1744. //
  1745. // WM_QUERYENDSESSION
  1746. //
  1747. LRESULT OnQueryEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1748. {
  1749. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1750. ASSERT(NULL != pWindow);
  1751. if (NULL != pWindow)
  1752. {
  1753. return pWindow->QueryShutdown(); // TRUE: ok to send session; FALSE, no.
  1754. }
  1755. return TRUE; // ok to end session
  1756. }
  1757. /////////////////////////////////////////////////////////////////
  1758. //
  1759. // WM_ENDSESSION
  1760. //
  1761. LRESULT OnEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1762. {
  1763. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1764. if (wParam && NULL != pWindow)
  1765. {
  1766. pWindow->OnExit(TRUE);
  1767. }
  1768. return 0;
  1769. }
  1770. /////////////////////////////////////////////////////////////////
  1771. //
  1772. // WM_DRAWITEM
  1773. //
  1774. LRESULT OnDrawItem(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1775. {
  1776. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1777. if (wParam && NULL != pWindow)
  1778. {
  1779. pWindow->DrawItem((DRAWITEMSTRUCT *)lParam);
  1780. }
  1781. return 0;
  1782. }
  1783. /////////////////////////////////////////////////////////////////
  1784. //
  1785. // WM_SEND_NEXT
  1786. //
  1787. LRESULT OnSendNext(HWND hwnd, WPARAM wParam, LPARAM lParam)
  1788. {
  1789. CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1790. if (NULL != pWindow)
  1791. {
  1792. pWindow->OnSendAll();
  1793. pWindow->UpdateUI();
  1794. }
  1795. return 0;
  1796. }
  1797. /////////////////////////////////////////////////////////////////
  1798. //
  1799. // Main windows procedure
  1800. //
  1801. LRESULT CALLBACK FtMainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1802. {
  1803. LRESULT rc = 0;
  1804. switch (uMsg)
  1805. {
  1806. case WM_CREATE:
  1807. rc = ::OnCreate(hwnd, wParam, lParam);
  1808. break;
  1809. case WM_COMMAND:
  1810. rc = ::OnCommand(hwnd, wParam, lParam);
  1811. break;
  1812. case WM_NOTIFY:
  1813. rc = ::OnNotify(hwnd, wParam, lParam);
  1814. break;
  1815. case WM_DROPFILES:
  1816. rc = ::OnDropFiles(hwnd, wParam, lParam);
  1817. break;
  1818. case WM_CONTEXTMENU:
  1819. rc = ::OnContextMenu(hwnd, wParam, lParam);
  1820. break;
  1821. case WM_SIZE:
  1822. rc = ::OnSize(hwnd, wParam, lParam);
  1823. break;
  1824. case WM_HELP:
  1825. rc = ::OnHelp(hwnd, wParam, lParam);
  1826. break;
  1827. case WM_DRAWITEM:
  1828. rc = ::OnDrawItem(hwnd, wParam, lParam);
  1829. break;
  1830. case WM_CLOSE:
  1831. rc = ::OnClose(hwnd, wParam, lParam);
  1832. break;
  1833. case WM_INITMENUPOPUP:
  1834. // rc = ::OnInitMenuPopup(hwnd, wParam, lParam);
  1835. break;
  1836. case WM_MENUSELECT:
  1837. rc = ::OnMenuSelect(hwnd, wParam, lParam);
  1838. break;
  1839. case WM_GETMINMAXINFO:
  1840. rc = ::OnGetMinMaxInfo(hwnd, wParam, lParam);
  1841. break;
  1842. case WM_QUERYENDSESSION:
  1843. rc = OnQueryEndSession(hwnd, wParam, lParam);
  1844. break;
  1845. case WM_ENDSESSION:
  1846. rc = ::OnEndSession(hwnd, wParam, lParam);
  1847. break;
  1848. case WM_SEND_NEXT:
  1849. rc = ::OnSendNext(hwnd, wParam, lParam);
  1850. break;
  1851. #if defined(TEST_PLUGABLE) && defined(_DEBUG)
  1852. case WM_PLUGABLE_SOCKET:
  1853. rc = ::OnPluggableSocket(hwnd, wParam, lParam);
  1854. break;
  1855. #endif
  1856. default:
  1857. rc = ::DefWindowProc(hwnd, uMsg, wParam, lParam);
  1858. break;
  1859. }
  1860. return rc;
  1861. }
  1862. /////////////////////////////////////////////////////////////////
  1863. //
  1864. // OnEngineNotify
  1865. //
  1866. void CAppletWindow::OnEngineNotify(MBFTMsg *pMsg)
  1867. {
  1868. BOOL fHeartBeat = FALSE;
  1869. switch (pMsg->GetMsgType())
  1870. {
  1871. case EnumFileOfferNotifyMsg:
  1872. if (m_UIMode != FTUIMODE_NOUI)
  1873. {
  1874. HandleFileOfferNotify((FileOfferNotifyMsg *) pMsg);
  1875. }
  1876. break;
  1877. case EnumFileTransmitMsg:
  1878. if (m_UIMode != FTUIMODE_NOUI)
  1879. {
  1880. HandleProgressNotify((FileTransmitMsg *) pMsg);
  1881. }
  1882. fHeartBeat = TRUE;
  1883. break;
  1884. case EnumFileErrorMsg:
  1885. if (m_UIMode != FTUIMODE_NOUI)
  1886. {
  1887. HandleErrorNotify((FileErrorMsg *) pMsg);
  1888. }
  1889. break;
  1890. case EnumPeerMsg:
  1891. HandlePeerNotification((PeerMsg *) pMsg);
  1892. break;
  1893. case EnumInitUnInitNotifyMsg:
  1894. HandleInitUninitNotification((InitUnInitNotifyMsg *) pMsg);
  1895. break;
  1896. case EnumFileEventEndNotifyMsg:
  1897. if (m_UIMode != FTUIMODE_NOUI)
  1898. {
  1899. HandleFileEventEndNotification((FileEventEndNotifyMsg *) pMsg);
  1900. }
  1901. break;
  1902. default:
  1903. ASSERT(0);
  1904. break;
  1905. } // switch
  1906. }
  1907. void CAppletWindow::HandleFileOfferNotify(FileOfferNotifyMsg *pMsg)
  1908. {
  1909. HRESULT hr = S_OK;
  1910. if (g_fRecvAllowed)
  1911. {
  1912. DBG_SAVE_FILE_LINE
  1913. CUiRecvFileInfo *pRecvFileInfo = new CUiRecvFileInfo(pMsg, &hr);
  1914. if (NULL != pRecvFileInfo && S_OK == hr)
  1915. {
  1916. if (NULL != m_pEngine)
  1917. {
  1918. DBG_SAVE_FILE_LINE
  1919. CRecvDlg *pDlg = new CRecvDlg(this,
  1920. m_pEngine->GetConfID(),
  1921. pMsg->m_NodeID,
  1922. pMsg->m_EventHandle,
  1923. pRecvFileInfo,
  1924. &hr);
  1925. if (NULL != pDlg && S_OK == hr)
  1926. {
  1927. DBG_SAVE_FILE_LINE
  1928. if (S_OK == m_pEngine->SafePostMessage(
  1929. new FileTransferControlMsg(
  1930. pMsg->m_EventHandle,
  1931. pMsg->m_hFile,
  1932. pRecvFileInfo->GetRecvFolder(),
  1933. pMsg->m_szFileName,
  1934. FileTransferControlMsg::EnumAcceptFile)))
  1935. {
  1936. return;
  1937. }
  1938. else
  1939. {
  1940. ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot confirm file offer"));
  1941. }
  1942. }
  1943. else
  1944. {
  1945. ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot allocate CRecvDlg, hr=0x%x", hr));
  1946. }
  1947. delete pDlg;
  1948. }
  1949. else
  1950. {
  1951. ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: no file transfer engine"));
  1952. }
  1953. }
  1954. else
  1955. {
  1956. ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot allocate CUiRecvFileInfo, hr=0x%x", hr));
  1957. }
  1958. delete pRecvFileInfo;
  1959. }
  1960. else
  1961. {
  1962. DBG_SAVE_FILE_LINE
  1963. if (S_OK != m_pEngine->SafePostMessage(
  1964. new FileTransferControlMsg(
  1965. pMsg->m_EventHandle,
  1966. pMsg->m_hFile,
  1967. NULL,
  1968. pMsg->m_szFileName,
  1969. FileTransferControlMsg::EnumRejectFile)))
  1970. {
  1971. ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot confirm file offer"));
  1972. }
  1973. }
  1974. }
  1975. void CAppletWindow::HandleProgressNotify(FileTransmitMsg *pMsg)
  1976. {
  1977. CRecvDlg *pDlg = NULL;
  1978. MBFT_NOTIFICATION wMBFTCode = (MBFT_NOTIFICATION) pMsg->m_TransmitStatus;
  1979. ULONG totalSent = 0;
  1980. ULONG fileSize = 0;
  1981. ULONG percentSent = 0;
  1982. switch (wMBFTCode)
  1983. {
  1984. case iMBFT_FILE_SEND_BEGIN:
  1985. // fall through... because the file start PDU can have data.
  1986. case iMBFT_FILE_SEND_PROGRESS:
  1987. if (NULL != m_pCurrSendFileInfo)
  1988. {
  1989. ASSERT(m_nCurrSendEventHandle == pMsg->m_EventHandle);
  1990. ASSERT(m_pCurrSendFileInfo->GetFileHandle() == pMsg->m_hFile);
  1991. ASSERT(m_pCurrSendFileInfo->GetSize() == pMsg->m_FileSize);
  1992. fileSize = m_pCurrSendFileInfo->GetSize();
  1993. totalSent = m_pCurrSendFileInfo->GetTotalSend();
  1994. m_pCurrSendFileInfo->SetTotalSend(pMsg->m_BytesTransmitted);
  1995. percentSent = _GetPercent(totalSent, fileSize)*10;
  1996. if(m_pCurrSendFileInfo->GetPercentSent()!= percentSent || fileSize == totalSent)
  1997. {
  1998. UpdateListView(m_pCurrSendFileInfo);
  1999. UpdateStatusBar();
  2000. m_pCurrSendFileInfo->SetPercentSent(percentSent);
  2001. }
  2002. }
  2003. break;
  2004. break;
  2005. case iMBFT_FILE_SEND_END:
  2006. if (NULL != m_pCurrSendFileInfo)
  2007. {
  2008. UpdateListView(m_pCurrSendFileInfo);
  2009. UpdateStatusBar();
  2010. }
  2011. break;
  2012. case iMBFT_FILE_RECEIVE_BEGIN:
  2013. // fall through... because the file start PDU can have data.
  2014. case iMBFT_FILE_RECEIVE_PROGRESS:
  2015. pDlg = FindDlgByHandles(pMsg->m_EventHandle, pMsg->m_hFile);
  2016. if (NULL != pDlg)
  2017. {
  2018. pDlg->OnProgressUpdate(pMsg);
  2019. }
  2020. break;
  2021. case iMBFT_FILE_RECEIVE_END:
  2022. // doing nothing...
  2023. break;
  2024. default:
  2025. ASSERT(0);
  2026. break;
  2027. }
  2028. }
  2029. void CAppletWindow::HandleErrorNotify(FileErrorMsg *pMsg)
  2030. {
  2031. MBFTFILEHANDLE nFileHandle = pMsg->m_hFile;
  2032. if(LOWORD(nFileHandle) == LOWORD(_iMBFT_PROSHARE_ALL_FILES))
  2033. {
  2034. nFileHandle = _iMBFT_PROSHARE_ALL_FILES;
  2035. }
  2036. if (m_nCurrSendEventHandle == pMsg->m_EventHandle &&
  2037. m_pCurrSendFileInfo->GetFileHandle() == nFileHandle)
  2038. {
  2039. m_pCurrSendFileInfo->SetErrorCode((MBFT_ERROR_CODE) pMsg->m_ErrorCode);
  2040. UINT idString;
  2041. switch ((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
  2042. {
  2043. case iMBFT_OK:
  2044. idString = 0;
  2045. break;
  2046. case iMBFT_SENDER_ABORTED:
  2047. case iMBFT_RECEIVER_ABORTED:
  2048. case iMBFT_NO_MORE_FILES:
  2049. idString = IDS_MSGBOX2_CANCELED;
  2050. break;
  2051. case iMBFT_MULT_RECEIVER_ABORTED:
  2052. idString = IDS_MSGBOX2_MULT_CANCEL;
  2053. break;
  2054. // case iMBFT_RECEIVER_REJECTED:
  2055. default:
  2056. idString = IDS_MSGBOX2_SEND_FAILED;
  2057. break;
  2058. }
  2059. if (idString)
  2060. {
  2061. if (! m_pCurrSendFileInfo->HasShownUI())
  2062. {
  2063. if (::MyLoadString(idString, s_szScratchText, m_pCurrSendFileInfo->GetName()))
  2064. {
  2065. m_pCurrSendFileInfo->SetShowUI();
  2066. ::MsgBox2(this, s_szScratchText);
  2067. }
  2068. else
  2069. {
  2070. ASSERT(0);
  2071. }
  2072. }
  2073. }
  2074. UpdateListView(m_pCurrSendFileInfo);
  2075. UpdateStatusBar();
  2076. ClearSendInfo(TRUE);
  2077. if (! idString)
  2078. {
  2079. // send the next one now
  2080. if (m_fSendALL)
  2081. {
  2082. ::PostMessage(m_hwndMainUI, WM_SEND_NEXT, 0, 0);
  2083. }
  2084. }
  2085. }
  2086. else
  2087. {
  2088. CRecvDlg *pDlg = FindDlgByHandles(pMsg->m_EventHandle, nFileHandle);
  2089. if (NULL != pDlg)
  2090. {
  2091. switch ((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
  2092. {
  2093. case iMBFT_RECEIVER_ABORTED:
  2094. case iMBFT_MULT_RECEIVER_ABORTED:
  2095. pDlg->OnCanceled();
  2096. break;
  2097. default:
  2098. pDlg->OnRejectedFile();
  2099. break;
  2100. }
  2101. }
  2102. else
  2103. {
  2104. switch((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
  2105. {
  2106. case iMBFT_INVALID_PATH:
  2107. ::MyLoadString(IDS_MSGBOX2_INVALID_DIRECTORY,
  2108. s_szScratchText, pMsg->m_stFileInfo.szFileName);
  2109. break;
  2110. case iMBFT_DIRECTORY_FULL_ERROR:
  2111. ::MyLoadString(IDS_MSGBOX2_DIRECTORY_FULL,
  2112. s_szScratchText, pMsg->m_stFileInfo.lFileSize,
  2113. pMsg->m_stFileInfo.szFileName);
  2114. break;
  2115. case iMBFT_FILE_ACCESS_DENIED:
  2116. ::MyLoadString(IDS_MSGBOX2_FILE_CREATE_FAILED,
  2117. s_szScratchText, pMsg->m_stFileInfo.szFileName);
  2118. break;
  2119. default:
  2120. return;
  2121. }
  2122. ::MsgBox2(this, s_szScratchText);
  2123. }
  2124. }
  2125. }
  2126. void CAppletWindow::HandlePeerNotification(PeerMsg *pMsg)
  2127. {
  2128. m_pToolbar->HandlePeerNotification(m_pEngine->GetConfID(),
  2129. m_pEngine->GetNodeID(), pMsg);
  2130. }
  2131. void CAppletWindow::HandleInitUninitNotification(InitUnInitNotifyMsg *pMsg)
  2132. {
  2133. if (pMsg->m_iNotifyMessage == EnumInvoluntaryUnInit)
  2134. {
  2135. UnregisterEngine();
  2136. }
  2137. }
  2138. void CAppletWindow::HandleFileEventEndNotification(FileEventEndNotifyMsg *pMsg)
  2139. {
  2140. if (m_nCurrSendEventHandle == pMsg->m_EventHandle)
  2141. {
  2142. ClearSendInfo(TRUE);
  2143. // send the next one now
  2144. if (m_fSendALL)
  2145. {
  2146. ::PostMessage(m_hwndMainUI, WM_SEND_NEXT, 0, 0);
  2147. }
  2148. }
  2149. }
  2150. /////////////////////////////////////////////////////////////////
  2151. //
  2152. // Main UI methods
  2153. //
  2154. void CAppletWindow::BringToFront(void)
  2155. {
  2156. if (NULL != m_hwndMainUI)
  2157. {
  2158. int nCmdShow = SW_SHOW;
  2159. WINDOWPLACEMENT wp;
  2160. ::ZeroMemory(&wp, sizeof(wp));
  2161. wp.length = sizeof(wp);
  2162. if (::GetWindowPlacement(m_hwndMainUI, &wp))
  2163. {
  2164. if (SW_MINIMIZE == wp.showCmd || SW_SHOWMINIMIZED == wp.showCmd)
  2165. {
  2166. // The window is minimized - restore it:
  2167. nCmdShow = SW_RESTORE;
  2168. }
  2169. }
  2170. // show the window now
  2171. ::ShowWindow(m_hwndMainUI, nCmdShow);
  2172. m_UIMode = FTUIMODE_SHOWUI;
  2173. // bring it to the foreground
  2174. ::SetForegroundWindow(m_hwndMainUI);
  2175. }
  2176. }
  2177. void CAppletWindow::ClearSendInfo(BOOL fUpdateUI)
  2178. {
  2179. m_pCurrSendFileInfo = NULL;
  2180. m_nCurrSendEventHandle = NULL;
  2181. if (fUpdateUI)
  2182. {
  2183. UpdateUI();
  2184. }
  2185. }
  2186. void CAppletWindow::ClearRecvInfo(void)
  2187. {
  2188. CRecvDlg *pDlg;
  2189. while (NULL != (pDlg = m_RecvDlgList.Get()))
  2190. {
  2191. ::EndDialog(pDlg->GetHwnd(), IDCLOSE);
  2192. pDlg->Release();
  2193. }
  2194. }
  2195. BOOL CAppletWindow::HasUnSentFiles(BOOL fUnSentOnly)
  2196. {
  2197. BOOL fRc = FALSE;
  2198. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  2199. CUiSendFileInfo *pFileInfo;
  2200. LVITEM lvi;
  2201. if (!fUnSentOnly && cItems) {
  2202. return TRUE;
  2203. }
  2204. ::ZeroMemory(&lvi, sizeof(lvi));
  2205. lvi.mask = LVIF_PARAM; // examine each item one by one
  2206. for (ULONG i = 0; i < cItems; i++, pFileInfo = NULL)
  2207. {
  2208. lvi.iItem = i;
  2209. BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
  2210. ASSERT(fRet);
  2211. pFileInfo = (CUiSendFileInfo *) lvi.lParam;
  2212. if (!pFileInfo->GetFileHandle()) // if file handle is not zero, then it has been sent or cancelled
  2213. {
  2214. fRc = TRUE;
  2215. break;
  2216. }
  2217. }
  2218. return fRc;
  2219. }
  2220. void CAppletWindow::UpdateUI(void)
  2221. {
  2222. UpdateTitle();
  2223. UpdateMenu();
  2224. UpdateToolBar();
  2225. UpdateStatusBar();
  2226. }
  2227. void CAppletWindow::UpdateTitle(void)
  2228. {
  2229. UINT captionID;
  2230. if ((! m_pEngine) || (m_pEngine->GetPeerCount() <= 1))
  2231. {
  2232. captionID = IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION;
  2233. }
  2234. else
  2235. {
  2236. captionID = IDS_MSFT_IN_CALL_WINDOW_CAPTION;
  2237. }
  2238. ::LoadString(g_hDllInst, captionID, s_szMSFT, sizeof(s_szMSFT));
  2239. SetWindowText(m_hwndMainUI, s_szMSFT);
  2240. }
  2241. void CAppletWindow::UpdateMenu(void)
  2242. {
  2243. HMENU hMenu = ::GetMenu(m_hwndMainUI);
  2244. if (NULL != hMenu)
  2245. {
  2246. if (g_fSendAllowed)
  2247. {
  2248. BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
  2249. ::EnableMenuItem(hMenu, IDM_ADD_FILES, fMoreThanOne ? MF_ENABLED : MF_GRAYED);
  2250. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  2251. ::EnableMenuItem(hMenu, IDM_REMOVE_FILES, cItems ? MF_ENABLED : MF_GRAYED);
  2252. ::EnableMenuItem(hMenu, IDM_SEND_ALL, (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? MF_ENABLED : MF_GRAYED);
  2253. ::EnableMenuItem(hMenu, IDM_SEND_ONE, (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(FALSE)) ? MF_ENABLED : MF_GRAYED);
  2254. ::EnableMenuItem(hMenu, IDM_STOP_SENDING, m_nCurrSendEventHandle ? MF_ENABLED : MF_GRAYED);
  2255. }
  2256. else
  2257. {
  2258. ::EnableMenuItem(hMenu, IDM_ADD_FILES, MF_GRAYED);
  2259. ::EnableMenuItem(hMenu, IDM_REMOVE_FILES, MF_GRAYED);
  2260. ::EnableMenuItem(hMenu, IDM_SEND_ALL, MF_GRAYED);
  2261. ::EnableMenuItem(hMenu, IDM_SEND_ONE, MF_GRAYED);
  2262. ::EnableMenuItem(hMenu, IDM_STOP_SENDING, MF_GRAYED);
  2263. }
  2264. }
  2265. }
  2266. void CAppletWindow::UpdateToolBar(void)
  2267. {
  2268. int iFlags[count_of(buttons)];
  2269. ::ZeroMemory(iFlags, sizeof(iFlags));
  2270. iFlags[2] = iFlags[5] = iFlags[6] = 1; // separators
  2271. iFlags[7] = 1; // open recv folders
  2272. if (g_fSendAllowed)
  2273. {
  2274. BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
  2275. ULONG cItems = ListView_GetItemCount(m_hwndListView);
  2276. iFlags[0] = fMoreThanOne ? TRUE : FALSE; // Add files
  2277. iFlags[1] = cItems ? TRUE : FALSE; // Delete files
  2278. iFlags[3] = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? TRUE : FALSE; // Send file(s)
  2279. iFlags[4] = m_nCurrSendEventHandle ? TRUE : FALSE; // Stop sending
  2280. m_pToolbar->UpdateButton(iFlags);
  2281. }
  2282. else
  2283. {
  2284. m_pToolbar->UpdateButton(iFlags);
  2285. }
  2286. }
  2287. void CAppletWindow::UpdateStatusBar(void)
  2288. {
  2289. int idString, iPos = 0;
  2290. HICON hIcon;
  2291. RECT rc;
  2292. // set the text in part 0
  2293. s_szScratchText[0] = TEXT('\0');
  2294. if ((NULL != m_pEngine) && (NULL != m_pCurrSendFileInfo))
  2295. {
  2296. idString = IDS_STBAR_SENDING_XYZ;
  2297. ::MyLoadString(idString, s_szScratchText, m_pCurrSendFileInfo->GetName());
  2298. }
  2299. else if (NULL == m_pEngine)
  2300. {
  2301. ::MyLoadString(IDS_STBAR_NOT_IN_CALL);
  2302. }
  2303. else
  2304. {
  2305. ::MyLoadString(IDS_STBAR_NOT_TRANSFERING);
  2306. }
  2307. ::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_TRANSFER_FILE, (LPARAM) s_szScratchText);
  2308. // set the progres bar in part 1
  2309. if ((NULL != m_pCurrSendFileInfo)&&m_pCurrSendFileInfo->GetSize())
  2310. {
  2311. iPos = (int)_GetPercent(m_pCurrSendFileInfo->GetTotalSend(), m_pCurrSendFileInfo->GetSize());
  2312. }
  2313. ::SendMessage(m_hwndStatusBar, SB_GETRECT, SBP_PROGRESS, (LPARAM)&rc);
  2314. ::MoveWindow(m_hwndProgressBar,
  2315. rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
  2316. FALSE);
  2317. ::SendMessage(m_hwndProgressBar, PBM_SETPOS, iPos, 0);
  2318. // set the icon in part 2
  2319. hIcon = (NULL != m_pEngine) ? m_hIconInCall : m_hIconNotInCall;
  2320. ::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_SBICON | SBT_OWNERDRAW, (LPARAM)hIcon);
  2321. }
  2322. void CAppletWindow::UpdateListView(CUiSendFileInfo *pFileInfo)
  2323. {
  2324. LVFINDINFO lvfi;
  2325. ::ZeroMemory(&lvfi, sizeof(lvfi));
  2326. lvfi.flags = LVFI_PARAM;
  2327. lvfi.lParam = (LPARAM) pFileInfo;
  2328. int iItem = ListView_FindItem(m_hwndListView, -1, &lvfi);
  2329. if (-1 != iItem)
  2330. {
  2331. for (ULONG i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
  2332. {
  2333. ListView_SetItemText(m_hwndListView, iItem, i, LPSTR_TEXTCALLBACK);
  2334. }
  2335. }
  2336. }
  2337. ////////////////////////////////////////////////////////////////////
  2338. //
  2339. // Save window position for File Transfer
  2340. //
  2341. void CAppletWindow::SaveWindowPosition(void)
  2342. {
  2343. RECT rcWnd;
  2344. RegEntry reWnd( FILEXFER_KEY, HKEY_CURRENT_USER);
  2345. // If we are not maximized or minimized
  2346. if (!::IsZoomed(m_hwndMainUI) && !::IsIconic(m_hwndMainUI))
  2347. {
  2348. ::GetWindowRect(m_hwndMainUI, &rcWnd);
  2349. reWnd.SetValue (REGVAL_WINDOW_XPOS, rcWnd.left);
  2350. reWnd.SetValue (REGVAL_WINDOW_YPOS, rcWnd.top);
  2351. reWnd.SetValue (REGVAL_WINDOW_WIDTH, rcWnd.right - rcWnd.left);
  2352. reWnd.SetValue (REGVAL_WINDOW_HEIGHT, rcWnd.bottom - rcWnd.top);
  2353. }
  2354. }
  2355. void CAppletWindow::FocusNextRecvDlg(void)
  2356. {
  2357. if (!m_RecvDlgList.IsEmpty())
  2358. {
  2359. m_RecvDlgList.Reset();
  2360. CRecvDlg *pRecvDlg = m_RecvDlgList.Iterate();
  2361. if (pRecvDlg)
  2362. {
  2363. SetFocus(pRecvDlg->GetHwnd());
  2364. }
  2365. }
  2366. }
  2367. void CAppletWindow::FocusNextErrorDlg(void)
  2368. {
  2369. if (!m_ErrorDlgList.IsEmpty())
  2370. {
  2371. m_ErrorDlgList.Reset();
  2372. HWND hwndErrorDlg = m_ErrorDlgList.Iterate();
  2373. if (hwndErrorDlg)
  2374. {
  2375. ::SetFocus(hwndErrorDlg);
  2376. }
  2377. }
  2378. }
  2379. /////////////////////////////////////////////////////////////////
  2380. //
  2381. // Utilities
  2382. //
  2383. LPTSTR PathNameToFileName(LPTSTR pszPathName)
  2384. {
  2385. LPTSTR psz = pszPathName;
  2386. while (*psz != '\0')
  2387. {
  2388. BOOL fDirChar = (*psz == TEXT('\\'));
  2389. psz = ::CharNext(psz);
  2390. if (fDirChar)
  2391. {
  2392. pszPathName = psz;
  2393. }
  2394. }
  2395. return pszPathName;
  2396. }
  2397. int MyLoadString(UINT idStr)
  2398. {
  2399. s_szScratchText[0] = TEXT('\0');
  2400. int iRet = ::LoadString(g_hDllInst, idStr, s_szScratchText, MAX_PATH);
  2401. ASSERT(iRet);
  2402. return iRet;
  2403. }
  2404. int MyLoadString(UINT idStr, LPTSTR pszDstStr)
  2405. {
  2406. *pszDstStr = TEXT('\0');
  2407. int iRet = ::LoadString(g_hDllInst, idStr, pszDstStr, MAX_PATH);
  2408. ASSERT(iRet);
  2409. return iRet;
  2410. }
  2411. int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement)
  2412. {
  2413. int cch;
  2414. TCHAR szText[MAX_PATH];
  2415. cch = ::LoadString(g_hDllInst, idStr, szText, count_of(szText));
  2416. if (cch)
  2417. {
  2418. ::wsprintf(pszDstStr, szText, pszElement);
  2419. }
  2420. else
  2421. {
  2422. ASSERT(0);
  2423. *pszDstStr = TEXT('\0');
  2424. }
  2425. return cch;
  2426. }
  2427. int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, LPTSTR pszElement2)
  2428. {
  2429. int cch;
  2430. TCHAR szText[MAX_PATH];
  2431. cch = ::LoadString(g_hDllInst, idStr, szText, count_of(szText));
  2432. if (cch)
  2433. {
  2434. ::wsprintf(pszDstStr, szText, pszElement1, pszElement2);
  2435. }
  2436. else
  2437. {
  2438. ASSERT(0);
  2439. *pszDstStr = TEXT('\0');
  2440. }
  2441. return cch;
  2442. }
  2443. void LoadDefaultStrings(void)
  2444. {
  2445. // load file transfer name
  2446. s_szMSFT[0] = TEXT('\0');
  2447. ::LoadString(g_hDllInst, IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION,
  2448. s_szMSFT, count_of(s_szMSFT));
  2449. }
  2450. /////////////////////////////////////////////////////////////////
  2451. //
  2452. // CUiSendFileInfo
  2453. //
  2454. CUiSendFileInfo::CUiSendFileInfo(CAppletWindow *pWindow, TCHAR szDir[], TCHAR szFile[], BOOL *pfRet)
  2455. :
  2456. m_nFileHandle(0),
  2457. m_cbTotalSend(0),
  2458. m_eSendErrorCode(iMBFT_OK),
  2459. m_percentSent(-1),
  2460. m_fAlreadyShowUI(FALSE),
  2461. m_pszFullName(NULL)
  2462. {
  2463. *pfRet = FALSE; // failure as default
  2464. HANDLE hFile;
  2465. // build a full name
  2466. hFile = GetOpenFile(pWindow, szDir, szFile, TRUE); // try to resolve
  2467. if (INVALID_HANDLE_VALUE == hFile)
  2468. {
  2469. hFile = GetOpenFile(pWindow, szDir, szFile, FALSE);
  2470. }
  2471. if (INVALID_HANDLE_VALUE != hFile)
  2472. {
  2473. // get the file info
  2474. ::ZeroMemory(&m_FileInfo, sizeof(m_FileInfo));
  2475. BOOL rc = ::GetFileInformationByHandle(hFile, &m_FileInfo);
  2476. ::CloseHandle(hFile);
  2477. if (rc)
  2478. {
  2479. ASSERT(0 == m_FileInfo.nFileSizeHigh);
  2480. // make sure the file size is smaller than what the policy says
  2481. if ((! g_cbMaxSendFileSize) || GetSize() <= g_cbMaxSendFileSize * 1024)
  2482. {
  2483. *pfRet = TRUE;
  2484. }
  2485. else if (pWindow->GetUIMode() != FTUIMODE_NOUI)
  2486. {
  2487. ::MyLoadString(IDS_MSGBOX_SEND_BIG_FILE, s_szScratchText, (LPTSTR) g_cbMaxSendFileSize, m_pszFileName);
  2488. ::MessageBox(pWindow->GetHwnd(), s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
  2489. }
  2490. }
  2491. }
  2492. }
  2493. CUiSendFileInfo::~CUiSendFileInfo(void)
  2494. {
  2495. delete m_pszFullName;
  2496. }
  2497. HANDLE CUiSendFileInfo::GetOpenFile(CAppletWindow *pWindow, TCHAR szDir[], TCHAR szFile[], BOOL fResolve)
  2498. {
  2499. // build a full name
  2500. ULONG cch;
  2501. TCHAR szName[MAX_PATH*2];
  2502. HANDLE hFile = INVALID_HANDLE_VALUE;
  2503. if ((NULL != szDir)&&(!_StrChr(szFile, '\\')))
  2504. {
  2505. cch = ::lstrlen(szDir);
  2506. ::wsprintf(szName, (TEXT('\\') == szDir[cch-1]) ? TEXT("%s%s") : TEXT("%s\\%s"), szDir, szFile);
  2507. }
  2508. else
  2509. {
  2510. // file name is the full name
  2511. ::lstrcpy(szName, szFile);
  2512. }
  2513. // resolve shortcut if necessary
  2514. cch = ::lstrlen(szName) + 1;
  2515. if (fResolve&&(cch >= 4))
  2516. {
  2517. if (! lstrcmpi(&szName[cch-5], TEXT(".lnk")))
  2518. {
  2519. pWindow->ResolveShortcut(szName, szName);
  2520. cch = ::lstrlen(szName) + 1;
  2521. }
  2522. }
  2523. if (m_pszFullName)
  2524. {
  2525. delete [] m_pszFullName;
  2526. }
  2527. // construct the full name
  2528. DBG_SAVE_FILE_LINE
  2529. m_pszFullName = new TCHAR[cch];
  2530. if (NULL != m_pszFullName)
  2531. {
  2532. ::CopyMemory(m_pszFullName, szName, cch * sizeof(TCHAR));
  2533. m_pszFileName = ::PathNameToFileName(m_pszFullName);
  2534. // open the file
  2535. hFile = ::CreateFile(m_pszFullName, GENERIC_READ,
  2536. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2537. NULL, OPEN_EXISTING,
  2538. FILE_ATTRIBUTE_NORMAL, NULL);
  2539. }
  2540. return hFile;
  2541. }
  2542. /////////////////////////////////////////////////////////////////
  2543. //
  2544. // CUiRecvFileInfo
  2545. //
  2546. CUiRecvFileInfo::CUiRecvFileInfo(FileOfferNotifyMsg *pMsg, HRESULT *pHr)
  2547. :
  2548. m_nFileHandle(pMsg->m_hFile),
  2549. m_FileDateTime(pMsg->m_FileDateTime),
  2550. m_cbFileSize(pMsg->m_FileSize),
  2551. m_cbTotalRecvSize(0),
  2552. m_pszFullName(NULL),
  2553. m_pszRecvFolder(NULL)
  2554. {
  2555. *pHr = E_FAIL; // failure, at default
  2556. ULONG cchTotal = ::lstrlen(pMsg->m_szFileName);
  2557. // construct the full name
  2558. DBG_SAVE_FILE_LINE
  2559. m_pszFullName = new TCHAR[cchTotal+2];
  2560. if (NULL != m_pszFullName)
  2561. {
  2562. // construct full name and file name
  2563. strcpy(m_pszFullName, pMsg->m_szFileName);
  2564. m_pszFileName = PathNameToFileName(m_pszFullName);
  2565. ULONG cchFile = ::lstrlen(m_pszFileName);
  2566. DBG_SAVE_FILE_LINE
  2567. m_pszRecvFolder = new TCHAR[cchTotal - cchFile + 2];
  2568. if (NULL != m_pszRecvFolder)
  2569. {
  2570. ::CopyMemory(m_pszRecvFolder, m_pszFullName, cchTotal - cchFile);
  2571. m_pszRecvFolder[cchTotal - cchFile - 1] = TEXT('\0');
  2572. *pHr = S_OK;
  2573. }
  2574. }
  2575. }
  2576. CUiRecvFileInfo::~CUiRecvFileInfo(void)
  2577. {
  2578. delete m_pszFullName;
  2579. delete m_pszRecvFolder;
  2580. }
  2581. /////////////////////////////////////////////////////////////////
  2582. //
  2583. // Receive Dialog
  2584. //
  2585. CRecvDlg::CRecvDlg
  2586. (
  2587. CAppletWindow *pWindow,
  2588. T120ConfID nConfID,
  2589. T120NodeID nidSender,
  2590. MBFTEVENTHANDLE nEventHandle,
  2591. CUiRecvFileInfo *pFileInfo,
  2592. HRESULT *pHr
  2593. )
  2594. :
  2595. CRefCount(MAKE_STAMP_ID('F','T','R','D')),
  2596. m_pWindow(pWindow),
  2597. m_nConfID(nConfID),
  2598. m_nidSender(nidSender),
  2599. m_nEventHandle(nEventHandle),
  2600. m_pRecvFileInfo(pFileInfo),
  2601. m_fRecvComplete(FALSE),
  2602. m_fShownRecvCompleteUI(FALSE),
  2603. m_idResult(0),
  2604. m_dwEstTimeLeft(0),
  2605. m_dwPreviousTime(0),
  2606. m_dwPreviousTransferred(0),
  2607. m_dwBytesPerSec(0),
  2608. m_dwStartTime(::GetTickCount())
  2609. {
  2610. *pHr = E_FAIL; // failure, at default
  2611. m_hwndRecvDlg = ::CreateDialogParam(g_hDllInst, MAKEINTRESOURCE(IDD_RECVDLG),
  2612. pWindow->GetHwnd(), RecvDlgProc, (LPARAM) this);
  2613. ASSERT(NULL != m_hwndRecvDlg);
  2614. if (NULL != m_hwndRecvDlg)
  2615. {
  2616. ::ShowWindow(m_hwndRecvDlg, SW_SHOWNORMAL);
  2617. m_pWindow->RegisterRecvDlg(this);
  2618. *pHr = S_OK;
  2619. ::SetForegroundWindow(m_hwndRecvDlg);
  2620. }
  2621. }
  2622. CRecvDlg::~CRecvDlg(void)
  2623. {
  2624. delete m_pRecvFileInfo;
  2625. m_pWindow->UnregisterRecvDlg(this);
  2626. if (NULL != m_hwndRecvDlg)
  2627. {
  2628. HWND hwnd = m_hwndRecvDlg;
  2629. m_hwndRecvDlg = NULL;
  2630. ::EndDialog(hwnd, IDCLOSE);
  2631. }
  2632. }
  2633. /////////////////////////////////////////////////////////////////
  2634. //
  2635. // RecvDlg_OnInitDialog
  2636. //
  2637. void RecvDlg_OnInitDialog(HWND hdlg, WPARAM wParam, LPARAM lParam)
  2638. {
  2639. CRecvDlg *pDlg = (CRecvDlg *) ::GetWindowLongPtr(hdlg, DWLP_USER);
  2640. ASSERT(NULL != pDlg);
  2641. CUiRecvFileInfo *pFileInfo = (CUiRecvFileInfo *) pDlg->GetRecvFileInfo();
  2642. ASSERT(NULL != pFileInfo);
  2643. // move the window to proper location
  2644. ULONG nCaptionHeight = ::GetSystemMetrics(SM_CYCAPTION);
  2645. ULONG nShift = nCaptionHeight * (s_cRecvDlg++ % 8);
  2646. RECT rcDlg;
  2647. ::GetWindowRect(hdlg, &rcDlg);
  2648. ::MoveWindow(hdlg, rcDlg.left + nShift, rcDlg.top + nShift,
  2649. rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top, FALSE);
  2650. // Set font (for international)
  2651. HFONT hfont = (HFONT) ::GetStockObject(DEFAULT_GUI_FONT);
  2652. ASSERT(NULL != hfont);
  2653. ::SendDlgItemMessage(hdlg, IDE_RECVDLG_RECFILE, WM_SETFONT, (WPARAM) hfont, 0);
  2654. ::SendDlgItemMessage(hdlg, IDE_RECVDLG_RECDIR, WM_SETFONT, (WPARAM) hfont, 0);
  2655. ::SendDlgItemMessage(hdlg, IDE_RECVDLG_SENDER, WM_SETFONT, (WPARAM) hfont, 0);
  2656. // cache names
  2657. LPTSTR pszFileName = pFileInfo->GetName();
  2658. LPTSTR pszFullName = pFileInfo->GetFullName();
  2659. // title
  2660. TCHAR szText[MAX_PATH*2];
  2661. if (::MyLoadString(IDS_RECVDLG_TITLE, szText, pszFileName))
  2662. {
  2663. ::SetWindowText(hdlg, szText);
  2664. }
  2665. // filename
  2666. ::lstrcpyn(szText, pszFileName, MAX_FILE_NAME_LENGTH);
  2667. if (::lstrlen(pszFileName) > MAX_FILE_NAME_LENGTH)
  2668. {
  2669. LPTSTR psz = szText;
  2670. int i = MAX_FILE_NAME_LENGTH - 1;
  2671. while (i)
  2672. {
  2673. psz = CharNext(psz);
  2674. i--;
  2675. }
  2676. ::lstrcpy(psz, TEXT("..."));
  2677. }
  2678. ::SetDlgItemText(hdlg, IDE_RECVDLG_RECFILE, szText);
  2679. // directory Name
  2680. LPTSTR psz = szText;
  2681. ::lstrcpyn(szText, pszFullName, (int)(pszFileName - pszFullName));
  2682. HDC hdc = ::GetDC(hdlg);
  2683. if (NULL != hdc)
  2684. {
  2685. SIZE size;
  2686. if (::GetTextExtentPoint32(hdc, szText, ::lstrlen(szText), &size))
  2687. {
  2688. RECT rc;
  2689. ::GetWindowRect(::GetDlgItem(hdlg, IDE_RECVDLG_RECDIR), &rc);
  2690. if (size.cx > (rc.right - rc.left))
  2691. {
  2692. // Just display the folder name
  2693. psz = (LPTSTR) ::GetFileNameFromPath(szText);
  2694. }
  2695. }
  2696. }
  2697. ::ReleaseDC(hdlg, hdc);
  2698. ::SetDlgItemText(hdlg, IDE_RECVDLG_RECDIR, psz);
  2699. // sender Name
  2700. if (::T120_GetNodeName(pDlg->GetConfID(), pDlg->GetSenderID(), szText, count_of(szText)))
  2701. {
  2702. ::SetDlgItemText(hdlg, IDE_RECVDLG_SENDER, szText);
  2703. }
  2704. // update "Received xxx bytes of yyy"
  2705. if (::MyLoadString(IDS_RECVDLG_RECBYTES, szText, pFileInfo->GetTotalRecvSize(), pFileInfo->GetSize()))
  2706. {
  2707. ::SetDlgItemText(hdlg, IDE_RECVDLG_RECBYTES, szText);
  2708. }
  2709. // progress bar
  2710. ::SendMessage(GetDlgItem(hdlg, IDC_RECVDLG_PROGRESS), PBM_SETPOS, pDlg->GetPercent(), 0);
  2711. // start animation
  2712. Animate_Open(GetDlgItem(hdlg, IDC_RECVDLG_ANIMATE), MAKEINTRESOURCE(IDA_RECVDLG_ANIMATION));
  2713. // do the animation work
  2714. if (! pDlg->IsRecvComplete())
  2715. {
  2716. Animate_Play(GetDlgItem(hdlg, IDC_RECVDLG_ANIMATE), 0, -1, -1);
  2717. if (::LoadString(g_hDllInst, IDS_RECVDLG_START, szText, count_of(szText)))
  2718. {
  2719. ::SetDlgItemText(hdlg, IDE_RECVDLG_TIME, szText);
  2720. }
  2721. }
  2722. // show the window now
  2723. ::ShowWindow(hdlg, SW_SHOWNORMAL);
  2724. // UpdateProgress();
  2725. pDlg->OnProgressUpdate();
  2726. }
  2727. /////////////////////////////////////////////////////////////////
  2728. //
  2729. // RecvDlg_OnCommand
  2730. //
  2731. void RecvDlg_OnCommand(HWND hdlg, WPARAM wParam, LPARAM lParam)
  2732. {
  2733. CRecvDlg *pDlg = (CRecvDlg *) ::GetWindowLongPtr(hdlg, DWLP_USER);
  2734. ASSERT(NULL != pDlg);
  2735. switch (GET_WM_COMMAND_ID(wParam, lParam))
  2736. {
  2737. case IDM_RECVDLG_DELETE:
  2738. pDlg->OnDelete();
  2739. break;
  2740. case IDM_RECVDLG_OPEN:
  2741. pDlg->OnOpen();
  2742. break;
  2743. case IDM_RECVDLG_ACCEPT:
  2744. case IDOK:
  2745. case IDCANCEL:
  2746. case IDCLOSE:
  2747. pDlg->OnAccept();
  2748. break;
  2749. default:
  2750. return;
  2751. }
  2752. // dismiss the dialog
  2753. ::EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam));
  2754. pDlg->Release();
  2755. }
  2756. void CRecvDlg::OnOpen(void)
  2757. {
  2758. // create short version of the path name
  2759. TCHAR szDir[MAX_PATH];
  2760. ::GetShortPathName(m_pRecvFileInfo->GetRecvFolder(), szDir, count_of(szDir));
  2761. // create short version of the full name
  2762. TCHAR szFile[MAX_PATH];
  2763. szFile[0] = TEXT('\0');
  2764. ::wsprintf(szFile, TEXT("%s\\%s"), szDir, m_pRecvFileInfo->GetName());
  2765. TRACE_OUT(("FT: Opening [%s] in [%]", m_pRecvFileInfo->GetName(), szDir));
  2766. HINSTANCE hInst = ::ShellExecute(m_pWindow->GetHwnd(),
  2767. NULL,
  2768. szFile,
  2769. NULL,
  2770. szDir,
  2771. SW_SHOWDEFAULT);
  2772. if (32 >= (DWORD_PTR) hInst)
  2773. {
  2774. WARNING_OUT(("Unable to open [%s] - showing file", szFile));
  2775. ::ShellExecute(m_pWindow->GetHwnd(),
  2776. NULL,
  2777. szDir,
  2778. m_pRecvFileInfo->GetFullName(),
  2779. NULL,
  2780. SW_SHOWDEFAULT);
  2781. }
  2782. }
  2783. void CRecvDlg::OnDelete(void)
  2784. {
  2785. StopAnimation();
  2786. // check if transfer has completed
  2787. if (! m_fRecvComplete)
  2788. {
  2789. DBG_SAVE_FILE_LINE
  2790. m_pWindow->GetEngine()->SafePostMessage(
  2791. new FileTransferControlMsg(
  2792. m_nEventHandle,
  2793. m_pRecvFileInfo->GetFileHandle(),
  2794. NULL,
  2795. NULL,
  2796. FileTransferControlMsg::EnumAbortFile));
  2797. }
  2798. else
  2799. {
  2800. ::DeleteFile(m_pRecvFileInfo->GetFullName());
  2801. }
  2802. }
  2803. void CRecvDlg::OnAccept(void)
  2804. {
  2805. StopAnimation();
  2806. }
  2807. /////////////////////////////////////////////////////////////////
  2808. //
  2809. // RecvDlg_OnInitMenuPopup
  2810. //
  2811. void RecvDlg_OnInitMenuPopup(HWND hdlg, WPARAM wParam, LPARAM lParam)
  2812. {
  2813. if (0 != HIWORD(lParam)) // System menu flag
  2814. {
  2815. HMENU hMenu = (HMENU) wParam; // handle of pop-up menu
  2816. ::EnableMenuItem(hMenu, SC_MAXIMIZE, MF_GRAYED);
  2817. ::EnableMenuItem(hMenu, SC_SIZE, MF_GRAYED);
  2818. }
  2819. }
  2820. /////////////////////////////////////////////////////////////////
  2821. //
  2822. // RecvDlgProc
  2823. //
  2824. INT_PTR CALLBACK RecvDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2825. {
  2826. BOOL fRet = TRUE; // processed
  2827. switch (uMsg)
  2828. {
  2829. case WM_INITDIALOG:
  2830. ASSERT(NULL != lParam);
  2831. ::SetWindowLongPtr(hdlg, DWLP_USER, lParam);
  2832. RecvDlg_OnInitDialog(hdlg, wParam, lParam);
  2833. break;
  2834. case WM_COMMAND:
  2835. RecvDlg_OnCommand(hdlg, wParam, lParam);
  2836. break;
  2837. case WM_INITMENUPOPUP:
  2838. RecvDlg_OnInitMenuPopup(hdlg, wParam, lParam);
  2839. fRet = FALSE;
  2840. break;
  2841. // This means user wants to delete the file.
  2842. case WM_CLOSE:
  2843. RecvDlg_OnCommand(hdlg, IDCLOSE, lParam);
  2844. break;;
  2845. default:
  2846. fRet = FALSE; // not processed
  2847. break;
  2848. }
  2849. return fRet;
  2850. }
  2851. /////////////////////////////////////////////////////////////////
  2852. //
  2853. // RecvDlg Animation
  2854. //
  2855. void CRecvDlg::StopAnimation(void)
  2856. {
  2857. HWND hwnd = ::GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_ANIMATE);
  2858. if (NULL != hwnd)
  2859. {
  2860. Animate_Stop(hwnd);
  2861. Animate_Close(hwnd);
  2862. }
  2863. }
  2864. ULONG _GetPercent(ULONG cbTotalRecvSize , ULONG cbFileSize)
  2865. {
  2866. if (! cbFileSize || (cbTotalRecvSize >= cbFileSize))
  2867. {
  2868. return 100;
  2869. }
  2870. // FUTURE: Consider using EnlargedUnsignedMultiply
  2871. if (cbFileSize < 0x01000000)
  2872. {
  2873. return (cbTotalRecvSize * 100) / cbFileSize;
  2874. }
  2875. return cbTotalRecvSize / (cbFileSize / 100);
  2876. }
  2877. /////////////////////////////////////////////////////////////////
  2878. //
  2879. // RecvDlg Progress
  2880. //
  2881. ULONG CRecvDlg::GetPercent(void)
  2882. {
  2883. return _GetPercent(m_pRecvFileInfo->GetTotalRecvSize(), m_pRecvFileInfo->GetSize());
  2884. }
  2885. void CRecvDlg::OnProgressUpdate(FileTransmitMsg *pMsg)
  2886. {
  2887. if (NULL != pMsg)
  2888. {
  2889. ASSERT(iMBFT_FILE_RECEIVE_PROGRESS == (MBFT_NOTIFICATION) pMsg->m_TransmitStatus ||
  2890. iMBFT_FILE_RECEIVE_BEGIN == (MBFT_NOTIFICATION) pMsg->m_TransmitStatus);
  2891. ASSERT(m_nEventHandle == pMsg->m_EventHandle);
  2892. ASSERT(m_pRecvFileInfo->GetFileHandle() == pMsg->m_hFile);
  2893. ASSERT(m_pRecvFileInfo->GetSize() == pMsg->m_FileSize);
  2894. m_pRecvFileInfo->SetTotalRecvSize(pMsg->m_BytesTransmitted);
  2895. if (pMsg->m_BytesTransmitted >= pMsg->m_FileSize)
  2896. {
  2897. m_fRecvComplete = TRUE;
  2898. m_idResult = IDS_RECVDLG_COMPLETE;
  2899. }
  2900. }
  2901. if (m_fRecvComplete && ! m_fShownRecvCompleteUI)
  2902. {
  2903. m_fRecvComplete = TRUE;
  2904. TCHAR szText[MAX_PATH];
  2905. if (::LoadString(g_hDllInst, IDS_RECVDLG_CLOSE, szText, count_of(szText)))
  2906. {
  2907. ::SetDlgItemText(m_hwndRecvDlg, IDM_RECVDLG_ACCEPT, szText);
  2908. }
  2909. if (IDS_RECVDLG_COMPLETE == m_idResult)
  2910. {
  2911. ::EnableWindow(::GetDlgItem(m_hwndRecvDlg, IDM_RECVDLG_OPEN), TRUE);
  2912. }
  2913. else
  2914. {
  2915. ::EnableWindow(::GetDlgItem(m_hwndRecvDlg, IDM_RECVDLG_DELETE), FALSE);
  2916. }
  2917. // Reset animation
  2918. HWND hwnd = ::GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_ANIMATE);
  2919. Animate_Stop(hwnd);
  2920. Animate_Close(hwnd);
  2921. Animate_Open(hwnd, MAKEINTRESOURCE(IDA_RECVDLG_DONE));
  2922. Animate_Seek(hwnd, ((IDS_RECVDLG_COMPLETE == m_idResult) ? 0 : 1));
  2923. m_fShownRecvCompleteUI = TRUE;
  2924. }
  2925. ULONG cbTotalRecvSize = m_pRecvFileInfo->GetTotalRecvSize();
  2926. ULONG cbFileSize = m_pRecvFileInfo->GetSize();
  2927. DWORD dwNow = ::GetTickCount();
  2928. DWORD dwBytesPerSec;
  2929. DWORD dwBytesRead;
  2930. TCHAR szOut[MAX_PATH];
  2931. if (m_dwPreviousTransferred != cbTotalRecvSize)
  2932. {
  2933. TCHAR szFmt[MAX_PATH];
  2934. // Update "Received xxx bytes of yyy"
  2935. if (::LoadString(g_hDllInst, IDS_RECVDLG_RECBYTES, szFmt, count_of(szFmt)))
  2936. {
  2937. ::wsprintf(szOut, szFmt, cbTotalRecvSize, cbFileSize);
  2938. ::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_RECBYTES, szOut);
  2939. }
  2940. // Update Progress Bar
  2941. if (cbTotalRecvSize)
  2942. {
  2943. ::SendMessage(GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_PROGRESS), PBM_SETPOS, GetPercent(), 0);
  2944. }
  2945. }
  2946. // check if no time estimate is required
  2947. if (m_fRecvComplete)
  2948. {
  2949. if (::LoadString(g_hDllInst, m_idResult, szOut, count_of(szOut)))
  2950. {
  2951. ::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_TIME, szOut);
  2952. }
  2953. return;
  2954. }
  2955. // first time we're in here for this file?
  2956. if (! m_dwPreviousTime || ! cbTotalRecvSize)
  2957. {
  2958. // no data, yet
  2959. m_dwPreviousTime = dwNow - 1000;
  2960. ASSERT(! m_dwPreviousTransferred);
  2961. ASSERT(! m_dwBytesPerSec);
  2962. return;
  2963. }
  2964. // Has enough time elapsed to update the display?
  2965. // We do this about every 5 seconds (note the adjustment for first time)
  2966. if ((dwNow - m_dwPreviousTime) < 5000)
  2967. return;
  2968. dwBytesRead = cbTotalRecvSize - m_dwPreviousTransferred;
  2969. // We take 10 times the number of bytes and divide by the number of
  2970. // tenths of a second to minimize both overflow and roundoff
  2971. dwBytesPerSec = dwBytesRead * 10 / ((dwNow - m_dwPreviousTime) / 100);
  2972. if (! dwBytesPerSec)
  2973. {
  2974. // very low transmission rate! Ignore the information?
  2975. return;
  2976. }
  2977. if (m_dwBytesPerSec)
  2978. {
  2979. // Take the average of the current transfer rate and the
  2980. // previously computed one, just to try to smooth out
  2981. // some random fluctuations
  2982. dwBytesPerSec = (dwBytesPerSec + m_dwBytesPerSec) / 2;
  2983. }
  2984. m_dwBytesPerSec = dwBytesPerSec;
  2985. // Calculate time remaining (round up by adding 1)
  2986. m_dwEstTimeLeft = ((cbFileSize - cbTotalRecvSize) / m_dwBytesPerSec) + 1;
  2987. // Reset time and # of bytes read
  2988. m_dwPreviousTime = dwNow;
  2989. m_dwPreviousTransferred = cbTotalRecvSize;
  2990. if (m_dwEstTimeLeft < 3)
  2991. {
  2992. // szOut[0] = _T('\0'); // don't bother updating when almost done
  2993. return;
  2994. }
  2995. if (m_dwEstTimeLeft > 99)
  2996. {
  2997. // dwTime is about 2 mintes
  2998. ::MyLoadString(IDS_RECVDLG_MINUTES, szOut, ((m_dwEstTimeLeft / 60) + 1));
  2999. }
  3000. else
  3001. {
  3002. // Round up to 5 seconds so it doesn't look so random
  3003. ::MyLoadString(IDS_RECVDLG_SECONDS, szOut, (((m_dwEstTimeLeft + 4) / 5) * 5) );
  3004. }
  3005. ::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_TIME, szOut);
  3006. }
  3007. void CRecvDlg::OnCanceled(void)
  3008. {
  3009. m_idResult = IDS_RECVDLG_CANCEL;
  3010. m_fRecvComplete = TRUE;
  3011. OnProgressUpdate();
  3012. }
  3013. void CRecvDlg::OnRejectedFile(void)
  3014. {
  3015. m_idResult = IDS_RECVDLG_SENDER_CANCEL;
  3016. m_fRecvComplete = TRUE;
  3017. OnProgressUpdate();
  3018. }
  3019. //////////////////////////////////////////////////////////////////////
  3020. //
  3021. // Shortcut/Link Management
  3022. //
  3023. void CAppletWindow::ResolveShortcut(LPTSTR pszSrcFile, LPTSTR pszDstFile)
  3024. {
  3025. ASSERT(NULL != pszSrcFile && '\0' != *pszSrcFile);
  3026. ASSERT(NULL != pszDstFile);
  3027. IShellLink *psl;
  3028. HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  3029. IID_IShellLink, (LPVOID *) &psl);
  3030. if (SUCCEEDED(hr))
  3031. {
  3032. IPersistFile *ppf;
  3033. hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *) &ppf);
  3034. if (SUCCEEDED(hr))
  3035. {
  3036. WCHAR wsz[MAX_PATH]; /* Buffer for unicode string */
  3037. #ifdef _UNICODE
  3038. ::lstrcpyn(wsz, pszSrcFile, MAX_PATH);
  3039. #else
  3040. ::MultiByteToWideChar(CP_ACP, 0, pszSrcFile, -1, wsz, MAX_PATH);
  3041. #endif
  3042. hr = ppf->Load(wsz, STGM_READ);
  3043. if (SUCCEEDED(hr))
  3044. {
  3045. /* Resolve the link, this may post UI to find the link */
  3046. hr = psl->Resolve(m_hwndMainUI, SLR_ANY_MATCH);
  3047. if (SUCCEEDED(hr))
  3048. {
  3049. psl->GetPath(pszDstFile, MAX_PATH, NULL, 0);
  3050. }
  3051. TRACE_OUT(("CAppletWindow::ResolveShortcut: File resolved to [%s]", pszDstFile));
  3052. }
  3053. ppf->Release();
  3054. }
  3055. psl->Release();
  3056. }
  3057. }
  3058. /////////////////////////////////////////////////////////////////
  3059. //
  3060. // Non-blocking Message Box
  3061. //
  3062. INT_PTR MsgBox2DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3063. {
  3064. BOOL fHandled = FALSE;
  3065. CAppletWindow *pWindow;
  3066. switch (uMsg)
  3067. {
  3068. case WM_INITDIALOG:
  3069. {
  3070. // get the text to display
  3071. LPTSTR pszText = (LPTSTR) lParam;
  3072. ASSERT(NULL != pszText && TEXT('\0') != *pszText);
  3073. // estimate how big the read-only edit control should be
  3074. HDC hdc = ::GetDC(hdlg);
  3075. if (NULL != hdc)
  3076. {
  3077. SIZE csEdit;
  3078. if (::GetTextExtentPoint32(hdc, pszText, ::lstrlen(pszText), &csEdit))
  3079. {
  3080. const ULONG c_nMarginX = 0;
  3081. const ULONG c_nMarginY = 10;
  3082. ULONG nCaptionHeight = ::GetSystemMetrics(SM_CYCAPTION);
  3083. ULONG nShift = nCaptionHeight * (s_cMsgBox2Dlg++ % 8);
  3084. // move the edit control
  3085. HWND hwndEdit = ::GetDlgItem(hdlg, IDE_MSGBOX2_TEXT);
  3086. POINT ptEdit;
  3087. ptEdit.x = c_nMarginX;
  3088. ptEdit.y = c_nMarginY + (c_nMarginY >> 1);
  3089. csEdit.cx += c_nMarginX << 1;
  3090. csEdit.cy += c_nMarginY << 1;
  3091. ::MoveWindow(hwndEdit, ptEdit.x, ptEdit.y, csEdit.cx, csEdit.cy, FALSE);
  3092. // move the ok button
  3093. HWND hwndOK = ::GetDlgItem(hdlg, IDOK);
  3094. RECT rcOK;
  3095. ::GetWindowRect(hwndOK, &rcOK);
  3096. SIZE csOK;
  3097. csOK.cx = rcOK.right - rcOK.left;
  3098. csOK.cy = rcOK.bottom - rcOK.top;
  3099. POINT ptOK;
  3100. ptOK.x = ptEdit.x + (csEdit.cx >> 1) - (csOK.cx >> 1);
  3101. ptOK.y = ptEdit.y + csEdit.cy + (c_nMarginY >> 1);
  3102. ::MoveWindow(hwndOK, ptOK.x, ptOK.y, csOK.cx, csOK.cy, FALSE);
  3103. // adjust all the windows
  3104. RECT rcDlg, rcClient;
  3105. ::GetWindowRect(hdlg, &rcDlg);
  3106. POINT ptDlg;
  3107. ptDlg.x = rcDlg.left + nShift;
  3108. ptDlg.y = rcDlg.top + nShift;
  3109. ::GetClientRect(hdlg, &rcClient);
  3110. SIZE csDlg;
  3111. csDlg.cx = (rcDlg.right - rcDlg.left) - (rcClient.right - rcClient.left);
  3112. csDlg.cy = (rcDlg.bottom - rcDlg.top) - (rcClient.bottom - rcClient.top);
  3113. csDlg.cx += ptEdit.x + csEdit.cx + c_nMarginX;
  3114. csDlg.cy += ptOK.y + csOK.cy + c_nMarginY;
  3115. ::MoveWindow(hdlg, ptDlg.x, ptDlg.y, csDlg.cx, csDlg.cy, FALSE);
  3116. }
  3117. ::ReleaseDC(hdlg, hdc);
  3118. }
  3119. ::SetDlgItemText(hdlg, IDE_MSGBOX2_TEXT, pszText);
  3120. delete [] pszText; // free the display text
  3121. fHandled = TRUE;
  3122. }
  3123. break;
  3124. case WM_COMMAND:
  3125. switch (GET_WM_COMMAND_ID(wParam, lParam))
  3126. {
  3127. case IDOK:
  3128. case IDCANCEL:
  3129. case IDCLOSE:
  3130. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  3131. {
  3132. case BN_CLICKED:
  3133. pWindow = (CAppletWindow*)::GetWindowLongPtr(hdlg, DWLP_USER);
  3134. ASSERT (pWindow);
  3135. if (pWindow)
  3136. {
  3137. pWindow->RemoveErrorDlg(hdlg);
  3138. pWindow->FocusNextErrorDlg();
  3139. }
  3140. ::EndDialog(hdlg, IDOK);
  3141. break;
  3142. }
  3143. break;
  3144. }
  3145. fHandled = TRUE;
  3146. break;
  3147. }
  3148. return(fHandled);
  3149. }
  3150. BOOL MsgBox2(CAppletWindow *pWindow, LPTSTR pszText)
  3151. {
  3152. BOOL fRet = FALSE;
  3153. ULONG cch = ::lstrlen(pszText) + 1;
  3154. DBG_SAVE_FILE_LINE
  3155. LPTSTR pszNew = new TCHAR[cch];
  3156. if (NULL != pszNew)
  3157. {
  3158. ::CopyMemory(pszNew, pszText, cch);
  3159. HWND hwndDlg = ::CreateDialogParam(g_hDllInst, MAKEINTRESOURCE(IDD_MSGBOX2),
  3160. pWindow->GetHwnd(), MsgBox2DlgProc, (LPARAM) pszNew);
  3161. ASSERT(NULL != hwndDlg);
  3162. if (NULL != hwndDlg)
  3163. {
  3164. ::ShowWindow(hwndDlg, SW_SHOWNORMAL);
  3165. fRet = TRUE;
  3166. ::SetForegroundWindow(hwndDlg);
  3167. ::SetWindowLongPtr(hwndDlg, DWLP_USER, (LPARAM)pWindow);
  3168. pWindow->AddErrorDlg(hwndDlg);
  3169. }
  3170. }
  3171. else
  3172. {
  3173. ERROR_OUT(("FT::MsgBox2: cannot duplicate string [%s]", pszText));
  3174. }
  3175. return fRet;
  3176. }
  3177. /////////////////////////////////////////////////////////////////
  3178. //
  3179. // Receive Folder Management
  3180. //
  3181. HRESULT GetRecvFolder(LPTSTR pszInFldr, LPTSTR pszOutFldr)
  3182. {
  3183. LPTSTR psz;
  3184. TCHAR szPath[MAX_PATH];
  3185. RegEntry reFileXfer(FILEXFER_KEY, HKEY_CURRENT_USER);
  3186. if (NULL == pszInFldr)
  3187. {
  3188. // NULL directory specified - get info from registry or use default
  3189. psz = reFileXfer.GetString(REGVAL_FILEXFER_PATH);
  3190. if (NULL != psz && TEXT('\0') != *psz)
  3191. {
  3192. ::lstrcpyn(szPath, psz, count_of(szPath));
  3193. }
  3194. else
  3195. {
  3196. TCHAR szInstallDir[MAX_PATH];
  3197. ::GetInstallDirectory(szInstallDir);
  3198. ::MyLoadString(IDS_RECDIR_DEFAULT, szPath, szInstallDir);
  3199. }
  3200. pszInFldr = szPath;
  3201. }
  3202. ::lstrcpyn(pszOutFldr, pszInFldr, MAX_PATH);
  3203. // Remove trailing backslash, if any
  3204. for (psz = pszOutFldr; *psz; psz = CharNext(psz))
  3205. {
  3206. if ('\\' == *psz && '\0' == *CharNext(psz))
  3207. {
  3208. *psz = '\0';
  3209. break;
  3210. }
  3211. }
  3212. HRESULT hr;
  3213. if (!FEnsureDirExists(pszOutFldr))
  3214. {
  3215. WARNING_OUT(("ChangeRecDir: FT directory is invalid [%s]", pszOutFldr));
  3216. hr = E_FAIL;
  3217. }
  3218. else
  3219. {
  3220. // update the registry
  3221. reFileXfer.SetValue(REGVAL_FILEXFER_PATH, pszOutFldr);
  3222. hr = S_OK;
  3223. }
  3224. return hr;
  3225. }
  3226. void EnsureTrailingSlash(LPTSTR psz)
  3227. {
  3228. LPTSTR psz2;
  3229. // Make sure the directory name has a trailing '\'
  3230. while (TEXT('\0') != *psz)
  3231. {
  3232. psz2 = ::CharNext(psz);
  3233. if (TEXT('\\') == *psz && TEXT('\0') == *psz2)
  3234. {
  3235. // The path already ends with a backslash
  3236. return;
  3237. }
  3238. psz = psz2;
  3239. }
  3240. // Append a trailing backslash
  3241. *psz = TEXT('\\');
  3242. psz = ::CharNext(psz);
  3243. *psz = TEXT('\0');
  3244. }
  3245.