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

// File: ftui.h
#include "mbftpch.h"
#include <commctrl.h>
#include <regentry.h>
#include "ftui.h"
#include "version.h"
#include <iappldr.h>
#include <nmhelp.h>
static ULONG s_cMsgBox2Dlg = 0; // for alignment
static ULONG s_cRecvDlg = 0; // for alignment
static ULONG s_sort = -1;
ULONG _GetPercent(ULONG cbTotalRecvSize , ULONG cbFileSize);
TCHAR s_szMSFT[64];
static TCHAR s_szScratchText[MAX_PATH*2];
static const TCHAR s_cszHtmlHelpFile[] = TEXT("conf.chm");
#define MAX_FILE_NAME_LENGTH 30
LRESULT CALLBACK FtMainWndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK RecvDlgProc(HWND, UINT, WPARAM, LPARAM);
LPTSTR PathNameToFileName(LPTSTR pszPathName);
HRESULT GetRecvFolder(LPTSTR pszInFldr, LPTSTR pszOutFldr);
BOOL MsgBox2(CAppletWindow *pWindow, LPTSTR pszText);
void ShiftFocus(HWND hwndTop, BOOL bForward);
void EnsureTrailingSlash(LPTSTR);
int MyLoadString(UINT idStr);
int MyLoadString(UINT idStr, LPTSTR pszDstStr);
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement);
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, LPTSTR pszElement2);
__inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement)
{ return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement); }
__inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement1, UINT_PTR nElement2)
{ return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement1, (LPTSTR) nElement2); }
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, UINT_PTR nElement2)
{ return MyLoadString(idStr, pszDstStr, pszElement1, (LPTSTR) nElement2); }
__inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement1, LPTSTR pszElement2)
{ return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement1, pszElement2); }
#define count_of(array) (sizeof(array) / sizeof(array[0]))
void OnChangeFolder(void);
BOOL FBrowseForFolder(LPTSTR pszFolder, UINT cchMax, LPCTSTR pszTitle);
extern BOOL g_fShutdownByT120;
void OPT_GetFTWndPosition(RECT *pRect)
{
int iLeft, iTop, iRight, iBottom;
RegEntry reWnd( FILEXFER_KEY, HKEY_CURRENT_USER);
iLeft = reWnd.GetNumber(REGVAL_WINDOW_XPOS, 0);
iTop = reWnd.GetNumber(REGVAL_WINDOW_YPOS, 0);
iRight = reWnd.GetNumber(REGVAL_WINDOW_WIDTH, 0) + iLeft;
iBottom = reWnd.GetNumber(REGVAL_WINDOW_HEIGHT, 0) + iTop;
// If it was empty, use the new rect
if (!(iBottom || iTop || iLeft || iRight))
{
return;
}
// Make sure that the window rectangle is (at least partially) on
// screen, and not too large. First get the screen size
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
// Check the window size
if ((iRight - iLeft) > screenWidth)
{
iRight = iLeft + screenWidth;
}
if ((iBottom - iTop) > screenHeight)
{
iTop = screenHeight;
}
// Check the window position
if (iLeft >= screenWidth)
{
// Off screen to the right - keep the width the same
iLeft = screenWidth - (iRight - iLeft);
iRight = screenWidth;
}
if (iRight < 0)
{
// Off screen to the left - keep the width the same
iRight = iRight - iLeft;
iLeft = 0;
}
if (iTop >= screenHeight)
{
// Off screen to the bottom - keep the height the same
iTop = screenHeight - (iBottom - iTop);
iBottom = screenHeight;
}
if (iBottom < 0)
{
// Off screen to the top - keep the height the same
iBottom = (iBottom - iTop);
iTop = 0;
}
pRect->left = iLeft;
pRect->top = iTop;
pRect->right = iRight - iLeft;
pRect->bottom = iBottom - iTop;
}
CAppletWindow::CAppletWindow(BOOL fNoUI, HRESULT *pHr)
:
CRefCount(MAKE_STAMP_ID('F','T','U','I')),
m_hwndMainUI(NULL),
m_pToolbar(NULL),
m_hwndListView(NULL),
m_hwndStatusBar(NULL),
m_pEngine(NULL),
m_fInFileOpenDialog(FALSE),
m_pCurrSendFileInfo(NULL),
m_nCurrSendEventHandle(0),
m_hIconInCall(NULL),
m_hIconNotInCall(NULL)
{
m_UIMode = fNoUI ? FTUIMODE_NOUI : FTUIMODE_UIHIDDEN;
::GetCurrentDirectory(MAX_PATH, m_szDefaultDir);
*pHr = E_FAIL; // failure, at default
// create window class name
::wsprintf(&m_szFtMainWndClassName[0], TEXT("FTMainWnd%0X_%0X"), ::GetCurrentProcessId(), ::GetTickCount());
ASSERT(::lstrlenA(&m_szFtMainWndClassName[0]) < sizeof(m_szFtMainWndClassName));
// register window class first
WNDCLASS wc;
::ZeroMemory(&wc, sizeof(wc));
//wc.style = 0;
wc.lpfnWndProc = FtMainWndProc;
// wc.cbClsExtra = 0;
// wc.cbWndExtra = 0;
wc.hInstance = g_hDllInst;
wc.hIcon = ::LoadIcon(g_hDllInst, MAKEINTRESOURCE(IDI_FILE_TRANSFER));
// wc.hbrBackground = NULL;
// wc.hCursor = NULL;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_FT);
wc.lpszClassName = m_szFtMainWndClassName;
if (::RegisterClass(&wc))
{
::MyLoadString(IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION);
m_hwndMainUI = ::CreateWindow(
m_szFtMainWndClassName,
s_szScratchText,
WS_OVERLAPPEDWINDOW | WS_TABSTOP,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // no parent window
NULL, // use class' menu
g_hDllInst,
(LPVOID) this); // this window is for this object
if (NULL != m_hwndMainUI)
{
// success
*pHr = S_OK;
}
}
m_hAccel = ::LoadAccelerators(g_hDllInst, MAKEINTRESOURCE(RECVDLGACCELTABLE));
m_hLVAccel = ::LoadAccelerators(g_hDllInst, MAKEINTRESOURCE(LISTVIEWACCELTABLE));
}
CAppletWindow::~CAppletWindow(void)
{
ASSERT(NULL == m_hwndMainUI);
::UnregisterClass(m_szFtMainWndClassName, g_hDllInst);
ClearSendInfo(FALSE);
ClearRecvInfo();
if (m_hIconInCall)
::DestroyIcon(m_hIconInCall);
if (m_hIconNotInCall)
::DestroyIcon(m_hIconNotInCall);
ASSERT(NULL == m_pEngine);
}
BOOL CAppletWindow::FilterMessage(MSG *pMsg)
{
CRecvDlg *pRecvDlg;
HWND hwndError;
HWND hwndForeground = ::GetForegroundWindow();
m_RecvDlgList.Reset();
while (NULL != (pRecvDlg = m_RecvDlgList.Iterate()))
{
if (::IsDialogMessage(pRecvDlg->GetHwnd(), pMsg))
{
return TRUE;
}
}
if (hwndForeground == m_hwndMainUI)
{
BOOL fRet = ::TranslateAccelerator(m_hwndMainUI, m_hLVAccel, pMsg);
return fRet;
}
m_ErrorDlgList.Reset();
while (NULL != (hwndError = m_ErrorDlgList.Iterate()))
{
if (::IsDialogMessage(hwndError, pMsg))
{
return TRUE;
}
}
return FALSE;
}
BOOL CAppletWindow::QueryShutdown(BOOL fShutdown)
{
if (m_UIMode != FTUIMODE_NOUI)
{
int id = 0;
if (m_nCurrSendEventHandle)
{
id = (fShutdown)?IDS_QUERY_SEND_SHUTDOWN:IDS_QUERY_SEND_HANGUP;
}
else if (IsReceiving())
{
id = (fShutdown)?IDS_QUERY_RECVING_SHUTDOWN:IDS_QUERY_RECVING_HANGUP;
}
if (id)
{
// could be in any thread
TCHAR szText[MAX_PATH];
if (::MyLoadString(id, szText))
{
if (IDNO == ::MessageBox(NULL, szText, s_szMSFT, MB_TASKMODAL | MB_YESNO | MB_ICONQUESTION))
{
return FALSE;
}
}
}
}
if (m_nCurrSendEventHandle)
{
OnStopSending();
}
if (IsReceiving())
{
CRecvDlg *pRecvDlg = NULL;
m_RecvDlgList.Reset();
while (NULL != (pRecvDlg = m_RecvDlgList.Iterate()))
{
DBG_SAVE_FILE_LINE
GetEngine()->SafePostMessage(
new FileTransferControlMsg(
pRecvDlg->GetEventHandle(),
pRecvDlg->GetFileHandle(),
NULL,
NULL,
FileTransferControlMsg::EnumAbortFile));
}
}
return TRUE;
}
void CAppletWindow::RegisterEngine(MBFTEngine *pEngine)
{
ASSERT(NULL == m_pEngine);
pEngine->AddRef();
m_pEngine = pEngine;
UpdateUI();
}
void CAppletWindow::UnregisterEngine(void)
{
if (NULL != m_pEngine)
{
m_pEngine->Release();
m_pEngine = NULL;
ClearSendInfo(TRUE);
ClearRecvInfo();
}
if (UIHidden())
{ // exit
::PostMessage(m_hwndMainUI, WM_CLOSE, 0, 0);
}
else
{
UpdateUI(); // don't quit
}
}
void CAppletWindow::RegisterRecvDlg(CRecvDlg *pDlg)
{
m_RecvDlgList.Prepend(pDlg);
}
void CAppletWindow::UnregisterRecvDlg(CRecvDlg *pDlg)
{
m_RecvDlgList.Remove(pDlg);
FocusNextRecvDlg();
}
BOOL CAppletWindow::IsReceiving(void)
{
BOOL fRet = FALSE;
CRecvDlg *pDlg;
CUiRecvFileInfo *pRecvFile;
m_RecvDlgList.Reset();
while (NULL != (pDlg = m_RecvDlgList.Iterate()))
{
pRecvFile = pDlg->GetRecvFileInfo();
if (pRecvFile && (pRecvFile->GetTotalRecvSize() < pRecvFile->GetSize()))
{
fRet = TRUE;
break;
}
}
return fRet;
}
CRecvDlg * CAppletWindow::FindDlgByHandles(MBFTEVENTHANDLE nEventHandle, MBFTFILEHANDLE nFileHandle)
{
CRecvDlg *pDlg;
m_RecvDlgList.Reset();
while (NULL != (pDlg = m_RecvDlgList.Iterate()))
{
if (nEventHandle == pDlg->GetEventHandle() &&
nFileHandle == pDlg->GetFileHandle())
{
break;
}
}
return pDlg;
}
/////////////////////////////////////////////////////////////////
//
// WM_CREATE
//
LRESULT OnCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CREATESTRUCT *p = (CREATESTRUCT *) lParam;
CAppletWindow *pWindow = (CAppletWindow *) p->lpCreateParams;
ASSERT(NULL != pWindow);
::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) p->lpCreateParams);
pWindow->SetHwnd(hwnd);
::InitCommonControls();
pWindow->CreateToolBar();
pWindow->CreateStatusBar();
pWindow->CreateListView();
::DragAcceptFiles(hwnd, g_fSendAllowed);
// resize the window
MINMAXINFO mmi;
::ZeroMemory(&mmi, sizeof(mmi));
pWindow->OnGetMinMaxInfo(&mmi);
RECT rcUI;
::GetWindowRect(pWindow->GetHwnd(), &rcUI);
rcUI.right = mmi.ptMinTrackSize.x;
rcUI.bottom = mmi.ptMinTrackSize.y + 30;
OPT_GetFTWndPosition(&rcUI);
::MoveWindow(pWindow->GetHwnd(), rcUI.left, rcUI.top,
rcUI.right, rcUI.bottom, TRUE);
pWindow->UpdateUI();
#if defined(TEST_PLUGABLE) && defined(_DEBUG)
::OnPluggableBegin(hwnd);
#endif
return 0;
}
enum
{
TB_IDX_ADD_FILES = 0,
TB_IDX_REMOVE_FILES,
TB_IDX_BREAK_1,
TB_IDX_IDM_SEND_ALL,
TB_IDX_IDM_SEND_ONE,
TB_IDX_IDM_STOP_SENDING,
TB_IDX_BREAK_2,
TB_IDX_IDM_OPEN_RECV_FOLDER,
TB_IDX_IDM_CHANGE_FOLDER,
TB_IDX_BREAK_3,
TB_IDX_IDM_HELP,
};
static Buttons buttons [] =
{
{IDB_ADDFILES, CBitmapButton::Disabled+1, 1, IDM_ADD_FILES, (LPCSTR)IDS_MENU_ADD_FILES,},
{IDB_REMOVEFILES, CBitmapButton::Disabled+1, 1, IDM_REMOVE_FILES, (LPCSTR)IDS_MENU_REMOVE_FILES,},
{0, 0, 0, 0, 0,},
{IDB_SENDFILE, CBitmapButton::Disabled+1, 1, IDM_SEND_ALL, (LPCSTR)IDS_MENU_SEND_ALL,},
{IDB_STOPSEND, CBitmapButton::Disabled+1, 1, IDM_STOP_SENDING, (LPCSTR)IDS_MENU_STOP_SENDING,},
{0, 0, 0, 0, 0,},
{IDB_FOLDER, CBitmapButton::Disabled+1, 1, IDM_OPEN_RECV_FOLDER, (LPCSTR)IDS_MENU_OPEN_RECV_FOLDER,},
{0, 0, 0, 0, 0},
};
BOOL CAppletWindow::CreateToolBar(void)
{
DBG_SAVE_FILE_LINE
m_pToolbar = new CComboToolbar();
if (m_pToolbar)
{
m_pToolbar->Create(m_hwndMainUI, &buttons[0], count_of(buttons), this);
m_pToolbar->Release();
return TRUE;
}
return FALSE;
}
BOOL CAppletWindow::CreateStatusBar(void)
{
m_hwndStatusBar = ::CreateWindowEx(0,
STATUSCLASSNAME, // status bar class
TEXT(""), // no default text
WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP,
0, 0, 0, 0,
m_hwndMainUI,
(HMENU) IDC_STATUS_BAR,
g_hDllInst,
NULL);
ASSERT(NULL != m_hwndStatusBar);
if (NULL != m_hwndStatusBar)
{
// Load Call Icons
m_hIconInCall = (HICON) ::LoadImage(g_hDllInst,
MAKEINTRESOURCE(IDI_INCALL),
IMAGE_ICON,
::GetSystemMetrics(SM_CXSMICON),
::GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR);
m_hIconNotInCall = (HICON) ::LoadImage(g_hDllInst,
MAKEINTRESOURCE(IDI_NOT_INCALL),
IMAGE_ICON,
::GetSystemMetrics(SM_CXSMICON),
::GetSystemMetrics(SM_CYSMICON),
LR_DEFAULTCOLOR);
if (CreateProgressBar())
{
return TRUE;
}
}
return FALSE;
}
BOOL CAppletWindow::CreateProgressBar(void)
{
RECT rcl;
GetClientRect(m_hwndStatusBar, &rcl);
m_hwndProgressBar = ::CreateWindowEx(0, PROGRESS_CLASS, TEXT(""),
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
rcl.right/2 + 2, 2, rcl.right - rcl.right/2 - 40, rcl.bottom - 8,
m_hwndStatusBar, (HMENU)IDC_PROGRESS_BAR,
g_hDllInst, NULL);
if (m_hwndProgressBar)
{
::SendMessage(m_hwndProgressBar, PBM_SETRANGE, 0L, MAKELONG(0, 100));
return TRUE;
}
return FALSE;
}
BOOL CAppletWindow::CreateListView(void)
{
// get the size and position of the main window
RECT rcWindow, rcToolBar, rcStatusBar;
SIZE szToolBar;
::GetClientRect(m_hwndMainUI, &rcWindow);
m_pToolbar->GetDesiredSize(&szToolBar);
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
ULONG x = 0;
ULONG y = szToolBar.cy - 1;
ULONG cx = rcWindow.right - rcWindow.left;
ULONG cy = rcWindow.bottom - rcWindow.top - y - (rcStatusBar.bottom - rcStatusBar.top) + 1;
// create the list view window
m_hwndListView = ::CreateWindowEx(WS_EX_CLIENTEDGE, // sunken look
WC_LISTVIEW , // list view class
TEXT(""), // no default text
WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT |WS_TABSTOP |
LVS_AUTOARRANGE | WS_CLIPCHILDREN | LVS_SHOWSELALWAYS,
x, y, cx, cy,
m_hwndMainUI,
(HMENU) IDC_LIST_VIEW,
g_hDllInst,
NULL);
ASSERT(NULL != m_hwndListView);
if (NULL != m_hwndListView)
{
// set extended list view styles
DWORD dwExtStyle = ListView_GetExtendedListViewStyle(m_hwndListView);
dwExtStyle |= (LVS_EX_HEADERDRAGDROP | LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT);
ListView_SetExtendedListViewStyle(m_hwndListView, dwExtStyle);
// enable window only if we can send files
::EnableWindow(m_hwndListView, g_fSendAllowed);
// set up the columns
ULONG i;
LVCOLUMN lvc;
LVITEM lvi;
TCHAR szText[64];
int iColumnSize[NUM_LIST_VIEW_COLUMNS] = {150, 80, 70, 130}; // listview column size
// initialize the common part of the columns
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT; // left-aligned column
lvc.pszText = szText;
// initialize columns one by one
for (i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
{
lvc.iSubItem = i;
::LoadString(g_hDllInst, IDS_LV_FILE_NAME + i, szText, count_of(szText));
lvc.cx = iColumnSize[i];
int iRet = ListView_InsertColumn(m_hwndListView, lvc.iSubItem, &lvc);
ASSERT(-1 != iRet);
}
return TRUE;
}
return FALSE;
}
BOOL CAppletWindow::DrawItem(LPDRAWITEMSTRUCT pdis)
{
ASSERT(pdis);
if (NULL != (pdis->itemData))
{
int nWidth = pdis->rcItem.right - pdis->rcItem.left;
int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
int nLeft = pdis->rcItem.left;
int nTop = pdis->rcItem.top;
int xSmIcon = ::GetSystemMetrics(SM_CXSMICON);
int ySmIcon = ::GetSystemMetrics(SM_CYSMICON);
if (nWidth > xSmIcon)
{
nLeft += (nWidth - xSmIcon) / 2 - 5;
nWidth = xSmIcon;
}
if (nHeight > ySmIcon)
{
nTop += (nHeight - ySmIcon) / 2;
nHeight = ySmIcon;
}
::DrawIconEx( pdis->hDC,
nLeft,
nTop,
(HICON) (pdis->itemData),
nWidth,
nHeight,
0,
NULL,
DI_NORMAL);
}
return TRUE;
}
void CAppletWindow::OnCommand(WORD wId, HWND hwndCtl, WORD codeNotify)
{
switch (wId)
{
case IDM_ADD_FILES:
OnAddFiles();
UpdateUI();
break;
case IDM_REMOVE_FILES:
OnRemoveFiles();
UpdateUI();
break;
case IDM_SEND_ALL:
s_cMsgBox2Dlg = 0;
SetSendMode(TRUE);
OnSendAll();
UpdateUI();
break;
case IDM_SEND_ONE:
s_cMsgBox2Dlg = 0;
SetSendMode(FALSE);
OnSendOne();
UpdateUI();
break;
case IDM_STOP_SENDING:
OnStopSending();
UpdateUI();
break;
case IDM_OPEN_RECV_FOLDER:
OnOpenRecvFolder();
break;
case IDM_CHANGE_FOLDER:
OnChangeFolder();
break;
case IDM_EXIT:
OnExit();
break;
case IDM_HELP:
OnHelp();
break;
case ID_NAV_TAB:
ShiftFocus(m_hwndMainUI, TRUE);
if(GetFocus() == m_hwndListView)
{
SetListViewFocus();
}
break;
case ID_NAV_SHIFT_TAB:
ShiftFocus(m_hwndMainUI, FALSE);
if(GetFocus() == m_hwndListView)
{
SetListViewFocus();
}
break;
case IDM_ABOUT:
OnAbout();
break;
default:
WARNING_OUT(("FT::OnCommand: unknown command ID=%u", (UINT) wId));
break;
}
return;
}
/////////////////////////////////////////////////////////////////
//
// WM_COMMAND
//
LRESULT OnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (NULL != pWindow)
{
WORD wNotifyCode = GET_WM_COMMAND_CMD(wParam, lParam); // notification code
WORD wID = GET_WM_COMMAND_ID(wParam, lParam); // item, control, or accelerator identifier
HWND hwndCtl = (HWND) lParam; // handle of control
pWindow->OnCommand(wID, hwndCtl, wNotifyCode);
return 0;
}
else
{
WARNING_OUT((" CAppletWindow::OnCommand--Received unhandled window message.\n"));
}
return (DefWindowProc(hwnd, WM_COMMAND, wParam, lParam));
}
//
// OnAddFiles
//
UINT_PTR APIENTRY SendFileDlgHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (WM_INITDIALOG == uMsg)
{
hdlg = ::GetParent(hdlg); // Real dialog is this window's parent
if (::MyLoadString(IDS_FILEDLG_SEND))
{
::SetDlgItemText(hdlg, IDOK, s_szScratchText);
}
}
return 0;
}
void CAppletWindow::OnAddFiles(void)
{
TCHAR szTitle[MAX_PATH];
TCHAR szFilter[MAX_PATH];
TCHAR szDirSav[MAX_PATH];
TCHAR szSendDir[MAX_PATH];
// Load dialog title and filter strings
if (::MyLoadString(IDS_FILEDLG_TITLE, szTitle) &&
::MyLoadString(IDS_FILEDLG_FILTER, szFilter))
{
// replace '|' to '\0'
LPTSTR pszFltr = szFilter;
while (TEXT('\0') != *pszFltr)
{
if (TEXT('|') == *pszFltr)
{
*pszFltr = TEXT('\0');
pszFltr++; // cannot use CharNext
}
else
{
pszFltr = ::CharNext(pszFltr);
}
}
// only allow one "Select a file to send" dialog
if (! m_fInFileOpenDialog)
{
m_fInFileOpenDialog = TRUE;
// Allocate a really large buffer to hold the file list
ULONG cbBufSize = 8192;
DBG_SAVE_FILE_LINE
LPTSTR pszBuffer = new TCHAR[cbBufSize];
if (NULL != pszBuffer)
{
*pszBuffer = TEXT('\0'); // start with null string
OPENFILENAME ofn;
::ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hwndMainUI;
ofn.hInstance = g_hDllInst;
ofn.lpstrFilter = &szFilter[0];
ofn.nFilterIndex = 1L; // FUTURE: remember filter preference
ofn.lpstrFile = pszBuffer;
ofn.nMaxFile = cbBufSize - 1; // Number of TCHAR in pszFiles (not including NULL)
ofn.lpstrTitle = &szTitle[0];
ofn.lpstrInitialDir = m_szDefaultDir;
ofn.lpfnHook = SendFileDlgHookProc;
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_ENABLEHOOK | // OFN_HIDEREADONLY |
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
// remember current directory
::ZeroMemory(szSendDir, sizeof(szSendDir));
::GetCurrentDirectory(count_of(szDirSav), szDirSav);
::lstrcpyn(szSendDir, szDirSav, count_of(szSendDir));
if (::GetOpenFileName(&ofn))
{
// if there is only a single file, the first string is the full path.
// if there are more than one file, the first string is the directory path
// and followed by a list of file names. terminated by double null
// remember the working directory for next time
ULONG cchDirPath;
LPTSTR pszFileName;
ULONG cchFile = ::lstrlen(ofn.lpstrFile);
if (TEXT('\0') == ofn.lpstrFile[cchFile] && TEXT('\0') == ofn.lpstrFile[cchFile+1])
{
//
// only a single file
//
pszFileName = ::PathNameToFileName(ofn.lpstrFile);
cchDirPath = (ULONG)(pszFileName - ofn.lpstrFile);
if (cchDirPath)
{
cchDirPath--; // back to '\\'
}
ASSERT(TEXT('\\') == ofn.lpstrFile[cchDirPath]);
ofn.lpstrFile[cchDirPath] = TEXT('\0');
}
else
{
//
// multiple files
//
cchDirPath = ::lstrlen(ofn.lpstrFile);
pszFileName = ofn.lpstrFile + cchDirPath + 1;
}
::lstrcpy(m_szDefaultDir, ofn.lpstrFile);
EnsureTrailingSlash(m_szDefaultDir);
::ZeroMemory(szSendDir, sizeof(szSendDir));
::CopyMemory(szSendDir, ofn.lpstrFile, cchDirPath * sizeof(TCHAR));
EnsureTrailingSlash(szSendDir);
// set up the common portion of list view item
LVITEM lvi;
::ZeroMemory(&lvi, sizeof(lvi));
// lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
// iterate the file name
while ('\0' != *pszFileName)
{
BOOL fRet;
DBG_SAVE_FILE_LINE
CUiSendFileInfo *pFileInfo = new CUiSendFileInfo(this, szSendDir, pszFileName, &fRet);
if (NULL != pFileInfo && fRet)
{
// put it to the list view
lvi.iItem = ListView_GetItemCount(m_hwndListView);
lvi.iSubItem = 0;
// we are responsible for storing the text to display
lvi.pszText = LPSTR_TEXTCALLBACK;
lvi.cchTextMax = MAX_PATH;
lvi.lParam = (LPARAM) pFileInfo;
int iRet = ListView_InsertItem(m_hwndListView, &lvi);
ASSERT(-1 != iRet);
// UpdateListView(pFileInfo);
}
else
{
delete pFileInfo;
}
// get to the next file name
pszFileName += ::lstrlen(pszFileName) + 1;
} // while
}
else
{
// err code for cancel is zero, which is ok.
ASSERT(! ::CommDlgExtendedError());
}
// restore old working directory
::SetCurrentDirectory(szDirSav);
}
delete [] pszBuffer;
m_fInFileOpenDialog = FALSE;
}
else
{
// bring the active dialog to the front
BringToFront();
}
} // if LoadString
}
//
// OnRemoveFiles
//
void CAppletWindow::OnRemoveFiles(void)
{
UINT nState;
ULONG cItems = ListView_GetItemCount(m_hwndListView);
LVITEM lvi;
::ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM | LVIF_STATE;
lvi.stateMask = LVIS_SELECTED;
ULONG i = 0;
while (i < cItems)
{
lvi.iItem = i;
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
if (fRet && lvi.state & LVIS_SELECTED)
{
CUiSendFileInfo *pFileInfo = (CUiSendFileInfo *) lvi.lParam;
if (pFileInfo == m_pCurrSendFileInfo)
{
OnStopSending();
ClearSendInfo(FALSE);
}
delete pFileInfo;
fRet = ListView_DeleteItem(m_hwndListView, i);
ASSERT(fRet);
cItems--;
ASSERT((ULONG) ListView_GetItemCount(m_hwndListView) == cItems);
}
else
{
i++;
}
}
if (cItems > 0) // set focus to first remaining item
{
SetListViewFocus();
}
}
void CAppletWindow::OnRemoveAllFiles(void)
{
BOOL fRet;
CUiSendFileInfo *pFileInfo;
ULONG cItems = ListView_GetItemCount(m_hwndListView);
LVITEM lvi;
::ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM;
for (ULONG i = 0; i < cItems; i++)
{
lvi.iItem = i;
fRet = ListView_GetItem(m_hwndListView, &lvi);
ASSERT(fRet);
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
if (pFileInfo == m_pCurrSendFileInfo)
{
ClearSendInfo(FALSE);
}
delete pFileInfo;
}
fRet = ListView_DeleteAllItems(m_hwndListView);
ASSERT(fRet);
}
void CAppletWindow::OnSendAll(void)
{
if ((NULL == m_pCurrSendFileInfo)&&(NULL != m_pEngine))
{
CUiSendFileInfo *pFileInfo = ChooseFirstUnSentFile();
SendNow(pFileInfo);
}
}
void CAppletWindow::OnSendOne(void)
{
if ((NULL == m_pCurrSendFileInfo)&&(NULL != m_pEngine))
{
CUiSendFileInfo *pFileInfo = ChooseSelectedFile();
if (!pFileInfo)
{
pFileInfo = ChooseFirstUnSentFile();
}
SendNow(pFileInfo);
}
}
//
// SendNow
//
BOOL CAppletWindow::SendNow(CUiSendFileInfo *pFileInfo)
{
BOOL fRet;
if (NULL != pFileInfo)
{
// send this file now...
m_pCurrSendFileInfo = pFileInfo;
m_nCurrSendEventHandle = ::GetNewEventHandle();
pFileInfo->SetFileHandle(::GetNewFileHandle());
// duplicate full file name
ULONG cbSize = ::lstrlen(pFileInfo->GetFullName()) + 1;
DBG_SAVE_FILE_LINE
LPTSTR pszFullName = new TCHAR[cbSize];
if (NULL != pszFullName)
{
::CopyMemory(pszFullName, pFileInfo->GetFullName(), cbSize);
DBG_SAVE_FILE_LINE
if (S_OK == m_pEngine->SafePostMessage(
new CreateSessionMsg(MBFT_PRIVATE_SEND_TYPE,
m_nCurrSendEventHandle)))
{
int iSelect;
MEMBER_ID nMemberID;
iSelect = m_pToolbar->GetSelectedItem((LPARAM*)&nMemberID);
if (0 == iSelect)
{ // Send to All
DBG_SAVE_FILE_LINE
if (S_OK == m_pEngine->SafePostMessage(
new SubmitFileSendMsg(0, 0, pszFullName,
pFileInfo->GetFileHandle(),
m_nCurrSendEventHandle,
FALSE)))
{
return TRUE;
}
else
{
ERROR_OUT(("CAppletWindow::SendNow: cannot create SubmitFileSendMsg"));
}
}
else
{ // Send to one
T120UserID uidRecv = GET_PEER_ID_FROM_MEMBER_ID(nMemberID);
DBG_SAVE_FILE_LINE
if (S_OK == m_pEngine->SafePostMessage(
new SubmitFileSendMsg(uidRecv, 0, pszFullName,
pFileInfo->GetFileHandle(),
m_nCurrSendEventHandle,
FALSE)))
{
return TRUE;
}
else
{
ERROR_OUT(("CAppletWindow::SendNow: cannot create SubmitFileSendMsg to 1"));
}
}
}
else
{
ERROR_OUT(("CAppletWindow::SendNow: cannot create CreateSessionMsg"));
}
delete [] pszFullName;
}
ClearSendInfo(TRUE);
}
return FALSE;
}
CUiSendFileInfo *CAppletWindow::ChooseFirstUnSentFile(void)
{
CUiSendFileInfo *pFileInfo = NULL;
ULONG cItems = ListView_GetItemCount(m_hwndListView);
if (cItems > 0)
{
// examine each item one by one
LVITEM lvi;
::ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM;
for (ULONG i = 0; i < cItems; i++, pFileInfo = NULL)
{
lvi.iItem = i;
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
ASSERT(fRet);
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
// if file handle is not zero, then it has been sent
if (! pFileInfo->GetFileHandle())
{
break;
}
}
}
return pFileInfo;
}
CUiSendFileInfo *CAppletWindow::ChooseSelectedFile(void)
{
CUiSendFileInfo *pFileInfo = NULL;
ULONG cItems = ListView_GetItemCount(m_hwndListView);
LVITEM lvi;
::ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM | LVIF_STATE;
lvi.stateMask = LVIS_SELECTED;
ULONG i = 0;
while (i < cItems)
{
lvi.iItem = i;
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
if (fRet && lvi.state & LVIS_SELECTED)
{
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
pFileInfo->SetErrorCode(iMBFT_OK);
break;
}
else
{
i++;
pFileInfo = NULL;
}
}
return pFileInfo;
}
//
// OnMenuSelect
//
void CAppletWindow::OnMenuSelect(UINT uiItemID, UINT uiFlags, HMENU hSysMenu)
{
UINT firstMenuId;
UINT statusId;
//
// Work out the help ID for the menu item. We have to store this now
// because when the user presses F1 from a menu item, we can't tell
// which item it was.
//
if ((uiFlags & MF_POPUP) && (uiFlags & MF_SYSMENU))
{
// System menu selected
statusId = (m_pCurrSendFileInfo)?IDS_STBAR_SENDING_XYZ:IDS_STBAR_NOT_TRANSFERING;
}
else if (uiFlags & MF_POPUP)
{
// get popup menu handle and first item
HMENU hPopup = ::GetSubMenu( hSysMenu, uiItemID );
firstMenuId = ::GetMenuItemID( hPopup, 0 );
switch(firstMenuId)
{
case IDM_ADD_FILES:
statusId = IDS_MENU_FILE;
break;
case IDM_HELP:
statusId = IDS_MENU_HELP;
break;
default:
statusId = (m_pCurrSendFileInfo)?IDS_STBAR_SENDING_XYZ:IDS_STBAR_NOT_TRANSFERING;
}
}
else
{
// A normal menu item has been selected
statusId = uiItemID;
}
// Set the new help text
TCHAR szStatus[256];
if (::LoadString(g_hDllInst, statusId, szStatus, 256))
{
::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_TRANSFER_FILE, (LPARAM)szStatus);
}
}
//
// OnStopSending
//
void CAppletWindow::OnStopSending(void)
{
m_fSendALL = FALSE;
if (m_nCurrSendEventHandle)
{
DBG_SAVE_FILE_LINE
HRESULT hr = m_pEngine->SafePostMessage(
new FileTransferControlMsg(
m_nCurrSendEventHandle,
m_pCurrSendFileInfo->GetFileHandle(),
NULL,
NULL,
FileTransferControlMsg::EnumAbortFile));
ASSERT(hr == S_OK);
}
}
//
// OnOpenRecvFolder
//
void CAppletWindow::OnOpenRecvFolder(void)
{
TCHAR szRecvFolder[MAX_PATH];
while (1)
{
if (S_OK == ::GetRecvFolder(NULL, szRecvFolder))
{
::ShellExecute(NULL, NULL, szRecvFolder, NULL, NULL, SW_SHOWNORMAL);
break;
}
else if (m_UIMode != FTUIMODE_NOUI)
{
::MyLoadString(IDS_RECVDLG_DIRNOEXIST, s_szScratchText, szRecvFolder);
if (IDYES == ::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_YESNO))
{
OnChangeFolder();
}
else
{
break;
}
}
}
}
//
// OnChageFolder
//
void OnChangeFolder(void)
{
BOOL rc;
TCHAR szPath[MAX_PATH];
::GetRecvFolder(NULL, szPath);
if (::lstrlen(szPath) > MAX_FILE_NAME_LENGTH)
{
LPTSTR psz = szPath;
int i = MAX_FILE_NAME_LENGTH - 1;
while (i)
{
psz = CharNext(psz);
i--;
}
::lstrcpy(psz, TEXT("..."));
}
::MyLoadString(IDS_BROWSETITLE, s_szScratchText, szPath);
if (FBrowseForFolder(szPath, CCHMAX(szPath), s_szScratchText))
{
::GetRecvFolder(szPath, szPath);
}
}
//
// OnExit
//
void CAppletWindow::OnExit(BOOL fNoQuery)
{
if ((g_pFileXferApplet->InConf() || g_pFileXferApplet->HasSDK())
&& ! g_fShutdownByT120)
{
// There 2.x node inside the conference
// hide the window
::ShowWindow(m_hwndMainUI, SW_HIDE);
m_UIMode = g_fNoUI ? FTUIMODE_NOUI : FTUIMODE_UIHIDDEN;
}
else
if (fNoQuery || QueryShutdown())
{
#if defined(TEST_PLUGABLE) && defined(_DEBUG)
::OnPluggableEnd();
#endif
MBFTEngine *pEngine = m_pEngine;
::T120_AppletStatus(APPLET_ID_FT, APPLET_CLOSING);
if (NULL != m_pEngine)
{
GCCAppPermissionToEnrollInd Ind;
::ZeroMemory(&Ind, sizeof(Ind));
Ind.nConfID = m_pEngine->GetConfID();
Ind.fPermissionGranted = FALSE;
m_pEngine->OnPermitToEnrollIndication(&Ind);
UnregisterEngine();
}
OnRemoveAllFiles();
::SetWindowLongPtr(m_hwndMainUI, GWLP_USERDATA, 0);
SaveWindowPosition();
HWND hwnd = m_hwndMainUI;
m_hwndMainUI = NULL;
::DestroyWindow(hwnd);
if (NULL != g_pFileXferApplet)
{
g_pFileXferApplet->UnregisterWindow(this);
g_pFileXferApplet->UnregisterEngine(pEngine);
}
Release();
}
}
//
// OnHelp
//
void CAppletWindow::OnHelp(void)
{
DebugEntry(CAppletWindow::OnHelp);
ShowNmHelp(s_cszHtmlHelpFile);
DebugExitVOID(CAppletWindow::OnHelp);
}
//
// OnAbout
//
INT_PTR AboutDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL fHandled = FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
TCHAR szFormat[256];
TCHAR szVersion[512];
::GetDlgItemText(hdlg, IDC_ABOUT_VERSION, szFormat, count_of(szFormat));
::wsprintf(szVersion, szFormat, VER_PRODUCTRELEASE_STR,
VER_PRODUCTVERSION_STR);
::SetDlgItemText(hdlg, IDC_ABOUT_VERSION, szVersion);
fHandled = TRUE;
}
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
case IDCANCEL:
case IDCLOSE:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case BN_CLICKED:
::EndDialog(hdlg, IDCANCEL);
break;
}
break;
}
fHandled = TRUE;
break;
}
return(fHandled);
}
void CAppletWindow::OnAbout(void)
{
::DialogBoxParam(g_hDllInst, MAKEINTRESOURCE(IDD_ABOUTBOX), m_hwndMainUI,
AboutDlgProc, 0);
}
BOOL FBrowseForFolder(LPTSTR pszFolder, UINT cchMax, LPCTSTR pszTitle)
{
LPITEMIDLIST pidlRoot;
if(FAILED(SHGetSpecialFolderLocation(HWND_DESKTOP, CSIDL_DRIVES, &pidlRoot)))
{
return FALSE;
}
BROWSEINFO bi;
ClearStruct(&bi);
bi.hwndOwner = NULL;
bi.lpszTitle = pszTitle;
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.pidlRoot = pidlRoot;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
BOOL fRet = (pidl != NULL);
if (fRet)
{
ASSERT(cchMax >= MAX_PATH);
SHGetPathFromIDList(pidl, pszFolder);
ASSERT(lstrlen(pszFolder) < (int) cchMax);
}
// Get the shell's allocator to free PIDLs
LPMALLOC lpMalloc;
if (FAILED(SHGetMalloc(&lpMalloc)) && (NULL != lpMalloc))
{
if (NULL != pidlRoot)
{
lpMalloc->Free(pidlRoot);
}
if (pidl)
{
lpMalloc->Free(pidl);
}
lpMalloc->Release();
}
return fRet;
}
/////////////////////////////////////////////////////////////////
//
// WM_NOTIFY
//
LRESULT OnNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (NULL != pWindow)
{
switch (wParam)
{
case IDC_LIST_VIEW:
pWindow->OnNotifyListView(lParam);
break;
default:
if (TTN_NEEDTEXT == ((NMHDR *) lParam)->code)
{
// display the tool tip text
TOOLTIPTEXT *pToolTipText = (TOOLTIPTEXT *) lParam;
ULONG_PTR nID;
// get id and hwnd
if (pToolTipText->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND) pToolTipText->hdr.idFrom);
}
else
{
nID = pToolTipText->hdr.idFrom;
}
// give it to em
pToolTipText->lpszText = MAKEINTRESOURCE(nID);
pToolTipText->hinst = g_hDllInst;
}
break;
}
}
return 0;
}
int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CUiSendFileInfo *pFileInfo1 = (CUiSendFileInfo *) lParam1;
CUiSendFileInfo *pFileInfo2 = (CUiSendFileInfo *) lParam2;
int iResult;
iResult = 0; // equal, at default
switch (lParamSort)
{
case (IDS_LV_FILE_NAME - IDS_LV_FILE_NAME):
iResult = lstrcmpi(pFileInfo1->GetName(), pFileInfo2->GetName());
break;
case (IDS_LV_FILE_SIZE - IDS_LV_FILE_NAME):
if (pFileInfo1->GetSize() > pFileInfo2->GetSize())
{
iResult = 1;
}
else
if (pFileInfo1->GetSize() < pFileInfo2->GetSize())
{
iResult = -1;
}
break;
case (IDS_LV_FILE_STATUS - IDS_LV_FILE_NAME):
if ((pFileInfo1->GetTotalSend() == pFileInfo1->GetSize()) >( pFileInfo2->GetTotalSend() == pFileInfo2->GetSize()))
{
iResult = 1;
}
else
if ((pFileInfo1->GetTotalSend() == pFileInfo1->GetSize()) < (pFileInfo2->GetTotalSend() == pFileInfo2->GetSize()))
{
iResult = -1;
}
break;
case (IDS_LV_FILE_MODIFIED - IDS_LV_FILE_NAME):
FILETIME fTime1 = pFileInfo1->GetLastWrite();
FILETIME fTime2 = pFileInfo2->GetLastWrite();
iResult = CompareFileTime(&fTime1,&fTime2);
break;
}
return iResult*s_sort;
}
void CAppletWindow::OnNotifyListView(LPARAM lParam)
{
LV_DISPINFO *pDispInfo = (LV_DISPINFO *) lParam;
NM_LISTVIEW *pLVN = (NM_LISTVIEW *) lParam;
FILETIME ftFileTime;
SYSTEMTIME stSystemTime;
CUiSendFileInfo *pFileInfo;
int iSize;
TCHAR szBuffer[MAX_PATH];
switch (pLVN->hdr.code)
{
case LVN_GETDISPINFO:
pFileInfo = (CUiSendFileInfo *) pDispInfo->item.lParam;
ASSERT(NULL != pFileInfo);
switch (pDispInfo->item.iSubItem)
{
case (IDS_LV_FILE_NAME - IDS_LV_FILE_NAME):
pDispInfo->item.pszText = pFileInfo->GetName();
break;
case (IDS_LV_FILE_SIZE - IDS_LV_FILE_NAME):
::wsprintf(szBuffer, TEXT("%u"), pFileInfo->GetSize());
iSize = GetNumberFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE,
szBuffer, NULL, s_szScratchText, MAX_PATH);
s_szScratchText[iSize - 4] = '\0'; // remove the trailing ".00"
pDispInfo->item.pszText = s_szScratchText;
break;
case (IDS_LV_FILE_STATUS - IDS_LV_FILE_NAME):
{
ULONG cbTotalSend = pFileInfo->GetTotalSend();
ULONG cbFileSize = pFileInfo->GetSize();
s_szScratchText[0] = TEXT('\0');
switch (pFileInfo->GetErrorCode())
{
case iMBFT_OK:
case iMBFT_MULT_RECEIVER_ABORTED:
if (!pFileInfo->GetFileHandle())
break; // handle == NULL, if cbTotalSend == 0, zero length file to be sent.
if (cbTotalSend >= cbFileSize)
{
::MyLoadString(IDS_LV_FILE_SENT);
}
else
if (cbTotalSend)
{
if (m_pEngine)
{
::MyLoadString(IDS_LV_FILE_SENDING);
}
else
{
::MyLoadString(IDS_LV_FILE_CANCELED);
}
}
break;
case iMBFT_SENDER_ABORTED:
case iMBFT_RECEIVER_ABORTED:
case iMBFT_NO_MORE_FILES:
::MyLoadString(IDS_LV_FILE_CANCELED);
break;
default:
::MyLoadString(IDS_LV_FILE_FAILED);
break;
}
pDispInfo->item.pszText = s_szScratchText;
}
break;
case (IDS_LV_FILE_MODIFIED - IDS_LV_FILE_NAME):
ftFileTime = pFileInfo->GetLastWrite();
FileTimeToSystemTime(&ftFileTime, &stSystemTime);
iSize = GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &stSystemTime,
"MM'/'dd'/'yyyy", s_szScratchText, MAX_PATH);
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &stSystemTime,
" hh':'mm tt", &s_szScratchText[iSize - 1], MAX_PATH-iSize-1);
pDispInfo->item.pszText = s_szScratchText;
break;
}
break;
case LVN_COLUMNCLICK:
{
s_sort = s_sort *(-1);
BOOL fRet = ListView_SortItems(pLVN->hdr.hwndFrom, ListViewCompareProc, (LPARAM) pLVN->iSubItem);
ASSERT(fRet);
}
break;
}
}
/////////////////////////////////////////////////////////////////
//
// WM_DROPFILES
//
LRESULT OnDropFiles(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
if (g_fSendAllowed)
{
return pWindow->OnDropFiles((HANDLE) wParam);
}
else
{
::MyLoadString(IDS_MSGBOX_POL_PREVENT);
::MessageBox(pWindow->GetHwnd(), s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
return 1;
}
}
LRESULT CAppletWindow::OnDropFiles(HANDLE hDrop)
{
if (NULL != m_pEngine && m_pEngine->GetPeerCount() > 1)
{
HRESULT hr;
// get the number of dropped files
ULONG cFiles = ::DragQueryFile((HDROP) hDrop, 0xFFFFFFFF, NULL, 0);
// set up the common portion of list view item
LVITEM lvi;
::ZeroMemory(&lvi, sizeof(lvi));
// lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
// iterate on these files
for (ULONG i = 0; i < cFiles; i++)
{
BOOL fRet;
TCHAR szFile[MAX_PATH];
if (::DragQueryFile((HDROP) hDrop, i, szFile, count_of(szFile)))
{
DBG_SAVE_FILE_LINE
CUiSendFileInfo *pFileInfo = new CUiSendFileInfo(this, NULL, szFile, &fRet);
if (NULL != pFileInfo && fRet)
{
// put it to the list view
lvi.iItem = ListView_GetItemCount(m_hwndListView);
lvi.iSubItem = 0;
// we are responsible for storing the text to display
lvi.pszText = LPSTR_TEXTCALLBACK;
lvi.cchTextMax = MAX_PATH;
lvi.lParam = (LPARAM) pFileInfo;
int iRet = ListView_InsertItem(m_hwndListView, &lvi);
ASSERT(-1 != iRet);
// UpdateListView(pFileInfo);
}
else
{
// BUGBUG: we should pop up some error message box here!
::MyLoadString(IDS_INVALID_FILENAME, s_szScratchText, szFile);
::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
delete pFileInfo;
}
}
}
::DragFinish((HDROP) hDrop);
SetForegroundWindow(m_hwndMainUI);
UpdateUI();
return 0;
}
::MyLoadString(IDS_MSGBOX_NO_CONF);
::SetForegroundWindow(m_hwndMainUI);
::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
return 1;
}
/////////////////////////////////////////////////////////////////
//
// WM_CONTEXTMENU
//
LRESULT OnContextMenu(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
LRESULT rc = 0;
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
if ((WPARAM) pWindow->GetHwnd() == wParam)
{
// BUGBUG use TrackPopupMenu to show context sensitive menu
pWindow->OnContextMenuForMainUI(lParam);
}
else
if ((WPARAM) pWindow->GetListView() == wParam)
{
// BUGBUG use TrackPopupMenu to show context sensitive menu
pWindow->OnContextMenuForListView(lParam);
}
else
{
rc = 1;
}
return rc;
}
enum
{
MENU_IDX_ADD_FILES,
MENU_IDX_REMOVE_FILES,
MENU_IDX_BREAK_1,
MENU_IDX_SEND_ALL,
MENU_IDX_SEND_ONE,
MENU_IDX_STOP_SENDING,
MENU_IDX_BREAK_2,
MENU_IDX_OPEN_RECV_FOLDER,
};
static UI_MENU_INFO s_aMenuInfo[] =
{
{ IDS_MENU_ADD_FILES, IDM_ADD_FILES, MF_ENABLED | MF_STRING },
{ IDS_MENU_REMOVE_FILES, IDM_REMOVE_FILES, MF_ENABLED | MF_STRING },
{ 0, 0, MF_SEPARATOR}, // menu break
{ IDS_MENU_SEND_ALL, IDM_SEND_ALL, MF_ENABLED | MF_STRING },
{ IDS_MENU_SEND_ONE, IDM_SEND_ONE, MF_ENABLED | MF_STRING },
{ IDS_MENU_STOP_SENDING, IDM_STOP_SENDING, MF_ENABLED | MF_STRING },
{ 0, 0, MF_SEPARATOR}, // menu break
{ IDS_MENU_OPEN_RECV_FOLDER, IDM_OPEN_RECV_FOLDER, MF_ENABLED | MF_STRING },
{ IDS_MENU_CHANGE_FOLDER, IDM_CHANGE_FOLDER, MF_ENABLED | MF_STRING },
{ 0, 0, MF_SEPARATOR }, // menu break
{ IDS_MENU_EXIT, IDM_EXIT, MF_ENABLED | MF_STRING },
};
void CAppletWindow::SetContextMenuStates(void)
{
if (g_fSendAllowed)
{
BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
s_aMenuInfo[MENU_IDX_ADD_FILES].nFlags = fMoreThanOne ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
ULONG cItems = ListView_GetItemCount(m_hwndListView);
s_aMenuInfo[MENU_IDX_REMOVE_FILES].nFlags = cItems ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_SEND_ALL].nFlags = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_SEND_ONE].nFlags = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(FALSE)) ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_STOP_SENDING].nFlags = m_nCurrSendEventHandle ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
}
else
{
s_aMenuInfo[MENU_IDX_ADD_FILES].nFlags =(MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_REMOVE_FILES].nFlags =(MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_SEND_ALL].nFlags = (MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_SEND_ONE].nFlags = (MF_GRAYED | MF_STRING);
s_aMenuInfo[MENU_IDX_STOP_SENDING].nFlags = (MF_GRAYED | MF_STRING);
}
}
void CAppletWindow::OnContextMenuForMainUI(LPARAM lParam)
{
SetContextMenuStates();
CreateMenu(lParam, count_of(s_aMenuInfo), &s_aMenuInfo[0]);
}
void CAppletWindow::OnContextMenuForListView(LPARAM lParam)
{
SetContextMenuStates();
CreateMenu(lParam, 6, &s_aMenuInfo[0]);
}
void CAppletWindow::CreateMenu(LPARAM lParam, ULONG cItems, UI_MENU_INFO aMenuInfo[])
{
HMENU hMenu = ::CreatePopupMenu();
if (NULL != hMenu)
{
for (ULONG i = 0; i < cItems; i++)
{
if (aMenuInfo[i].idCommand)
{
if (::MyLoadString(aMenuInfo[i].idString))
{
::AppendMenu(hMenu, aMenuInfo[i].nFlags, aMenuInfo[i].idCommand, s_szScratchText);
}
}
else
{
::AppendMenu(hMenu, aMenuInfo[i].nFlags, 0, 0);
}
}
::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON,
GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
0, // reserved, must be zero
m_hwndMainUI,
NULL); // ignore
}
}
/////////////////////////////////////////////////////////////////
//
// WM_SIZE
//
LRESULT OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
pWindow->OnSizeToolBar();
pWindow->OnSizeStatusBar();
pWindow->OnSizeListView();
return 0;
}
void CAppletWindow::OnSizeToolBar(void)
{
RECT rcWindow;
SIZE szToolBar;
::GetClientRect(m_hwndMainUI, &rcWindow);
m_pToolbar->GetDesiredSize(&szToolBar);
ULONG cx = rcWindow.right - rcWindow.left;
ULONG cy = szToolBar.cy;;
ULONG x = 0;
ULONG y = 0;
::MoveWindow(m_pToolbar->GetWindow(), x, y, cx, cy, TRUE);
}
void CAppletWindow::OnSizeStatusBar(void)
{
RECT rcWindow, rcStatusBar;
::GetClientRect(m_hwndMainUI, &rcWindow);
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
ULONG cx = rcWindow.right - rcWindow.left;
ULONG cy = rcStatusBar.bottom - rcStatusBar.top;
ULONG x = 0;
ULONG y = rcWindow.bottom - cy;
::MoveWindow(m_hwndStatusBar, x, y, cx, cy, TRUE);
::MoveWindow(m_hwndProgressBar, x + cx/2, y, cx/2 - 40, cy, TRUE);
int aWidths[NUM_STATUS_BAR_PARTS];
aWidths[0] = cx / 2; // conference state
aWidths[1] = cx - 40; // transfer name
aWidths[2] = -1; // transfer percentage
ASSERT(3 == NUM_STATUS_BAR_PARTS);
::SendMessage(m_hwndStatusBar, SB_SETPARTS, NUM_STATUS_BAR_PARTS, (LPARAM) &aWidths[0]);
}
void CAppletWindow::OnSizeListView(void)
{
// get the size and position of the main window
RECT rcWindow, rcToolBar, rcStatusBar;
SIZE szToolBar;
::GetClientRect(m_hwndMainUI, &rcWindow);
m_pToolbar->GetDesiredSize(&szToolBar);
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
ULONG x = 0;
ULONG y = szToolBar.cy - 1;
ULONG cx = rcWindow.right - rcWindow.left;
ULONG cy = rcWindow.bottom - rcWindow.top - y - (rcStatusBar.bottom - rcStatusBar.top) + 1;
::MoveWindow(m_hwndListView, x, y, cx, cy, TRUE);
}
/////////////////////////////////////////////////////////////////
//
// WM_HELP
//
LRESULT OnHelp(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
pWindow->OnHelp();
return 0;
}
/////////////////////////////////////////////////////////////////
//
// WM_CLOSE
//
LRESULT OnClose(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
if (NULL != pWindow)
{
pWindow->OnExit();
}
return 0;
}
/////////////////////////////////////////////////////////////////
//
// WM_INITMENUPOPUP
//
/*
LRESULT OnInitMenuPopup(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
if (0 != HIWORD(lParam)) // System menu flag
{
HMENU hMenu = (HMENU) wParam; // handle of pop-up menu
::EnableMenuItem(hMenu, SC_MAXIMIZE, MF_GRAYED);
::EnableMenuItem(hMenu, SC_SIZE, MF_GRAYED);
return 0;
}
return 1;
}
*/
/////////////////////////////////////////////////////////////////
//
// WM_MENUSELECT
//
LRESULT OnMenuSelect(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
if (NULL != pWindow)
{
pWindow->OnMenuSelect(GET_WM_MENUSELECT_CMD(wParam, lParam),
GET_WM_MENUSELECT_FLAGS(wParam, lParam),
GET_WM_MENUSELECT_HMENU(wParam, lParam));
}
return 0;
}
/////////////////////////////////////////////////////////////////
//
// WM_INITMENUPOPUP
//
LRESULT OnGetMinMaxInfo(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (NULL != pWindow)
{
pWindow->OnGetMinMaxInfo((LPMINMAXINFO) lParam);
return 0;
}
return 1;
}
void CAppletWindow::OnGetMinMaxInfo(LPMINMAXINFO pMMI)
{
static BOOL s_fEnterBefore = FALSE;
static SIZE s_csFrame;
static SIZE s_csSeparator;
static SIZE s_csScrollBars;
static SIZE s_csToolBar;
static SIZE s_csStatusBar;
static SIZE s_csSum;
if (! s_fEnterBefore)
{
s_fEnterBefore = TRUE;
s_csFrame.cx = ::GetSystemMetrics(SM_CXSIZEFRAME);
s_csFrame.cy = ::GetSystemMetrics(SM_CYSIZEFRAME);
s_csSeparator.cx = ::GetSystemMetrics(SM_CXEDGE);
s_csSeparator.cy = ::GetSystemMetrics(SM_CYEDGE);
s_csScrollBars.cx = ::GetSystemMetrics(SM_CXVSCROLL);
s_csScrollBars.cy = ::GetSystemMetrics(SM_CYHSCROLL);
m_pToolbar->GetDesiredSize(&s_csToolBar);
RECT rcStatusBar;
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
s_csStatusBar.cx = rcStatusBar.right - rcStatusBar.left;
s_csStatusBar.cy = rcStatusBar.bottom - rcStatusBar.top;
s_csSum.cx = (s_csFrame.cx << 1);
s_csSum.cy = (s_csFrame.cy << 1) + (s_csSeparator.cy << 3) +
s_csToolBar.cy + (rcStatusBar.bottom - rcStatusBar.top) +
::GetSystemMetrics( SM_CYCAPTION ) + ::GetSystemMetrics( SM_CYMENU );
}
RECT rcListViewItem;
SIZE csListView;
csListView.cx = 0;
for (ULONG i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
{
csListView.cx += ListView_GetColumnWidth(m_hwndListView, i);
}
if (ListView_GetItemRect(m_hwndListView, 0, &rcListViewItem, LVIR_BOUNDS))
{
csListView.cy = 20 + 3 * (rcListViewItem.bottom - rcListViewItem.top);
}
else
{
csListView.cy = 20 + 30;
}
// Set the minimum width and height of the window
pMMI->ptMinTrackSize.x = s_csSum.cx + max(s_csToolBar.cx, csListView.cx);
pMMI->ptMinTrackSize.y = s_csSum.cy + csListView.cy;
//
// Retrieves the size of the work area on the primary display monitor. The work
// area is the portion of the screen not obscured by the system taskbar or by
// application desktop toolbars
//
RECT rcWorkArea;
::SystemParametersInfo( SPI_GETWORKAREA, 0, (&rcWorkArea), NULL );
SIZE csMaxSize;
csMaxSize.cx = rcWorkArea.right - rcWorkArea.left;
csMaxSize.cy = rcWorkArea.bottom - rcWorkArea.top;
pMMI->ptMaxPosition.x = 0;
pMMI->ptMaxPosition.y = 0;
pMMI->ptMaxSize.x = csMaxSize.cx;
pMMI->ptMaxSize.y = csMaxSize.cy;
pMMI->ptMaxTrackSize.x = csMaxSize.cx;
pMMI->ptMaxTrackSize.y = csMaxSize.cy;
}
/////////////////////////////////////////////////////////////////
//
// WM_QUERYENDSESSION
//
LRESULT OnQueryEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
ASSERT(NULL != pWindow);
if (NULL != pWindow)
{
return pWindow->QueryShutdown(); // TRUE: ok to send session; FALSE, no.
}
return TRUE; // ok to end session
}
/////////////////////////////////////////////////////////////////
//
// WM_ENDSESSION
//
LRESULT OnEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (wParam && NULL != pWindow)
{
pWindow->OnExit(TRUE);
}
return 0;
}
/////////////////////////////////////////////////////////////////
//
// WM_DRAWITEM
//
LRESULT OnDrawItem(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (wParam && NULL != pWindow)
{
pWindow->DrawItem((DRAWITEMSTRUCT *)lParam);
}
return 0;
}
/////////////////////////////////////////////////////////////////
//
// WM_SEND_NEXT
//
LRESULT OnSendNext(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (NULL != pWindow)
{
pWindow->OnSendAll();
pWindow->UpdateUI();
}
return 0;
}
/////////////////////////////////////////////////////////////////
//
// Main windows procedure
//
LRESULT CALLBACK FtMainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT rc = 0;
switch (uMsg)
{
case WM_CREATE:
rc = ::OnCreate(hwnd, wParam, lParam);
break;
case WM_COMMAND:
rc = ::OnCommand(hwnd, wParam, lParam);
break;
case WM_NOTIFY:
rc = ::OnNotify(hwnd, wParam, lParam);
break;
case WM_DROPFILES:
rc = ::OnDropFiles(hwnd, wParam, lParam);
break;
case WM_CONTEXTMENU:
rc = ::OnContextMenu(hwnd, wParam, lParam);
break;
case WM_SIZE:
rc = ::OnSize(hwnd, wParam, lParam);
break;
case WM_HELP:
rc = ::OnHelp(hwnd, wParam, lParam);
break;
case WM_DRAWITEM:
rc = ::OnDrawItem(hwnd, wParam, lParam);
break;
case WM_CLOSE:
rc = ::OnClose(hwnd, wParam, lParam);
break;
case WM_INITMENUPOPUP:
// rc = ::OnInitMenuPopup(hwnd, wParam, lParam);
break;
case WM_MENUSELECT:
rc = ::OnMenuSelect(hwnd, wParam, lParam);
break;
case WM_GETMINMAXINFO:
rc = ::OnGetMinMaxInfo(hwnd, wParam, lParam);
break;
case WM_QUERYENDSESSION:
rc = OnQueryEndSession(hwnd, wParam, lParam);
break;
case WM_ENDSESSION:
rc = ::OnEndSession(hwnd, wParam, lParam);
break;
case WM_SEND_NEXT:
rc = ::OnSendNext(hwnd, wParam, lParam);
break;
#if defined(TEST_PLUGABLE) && defined(_DEBUG)
case WM_PLUGABLE_SOCKET:
rc = ::OnPluggableSocket(hwnd, wParam, lParam);
break;
#endif
default:
rc = ::DefWindowProc(hwnd, uMsg, wParam, lParam);
break;
}
return rc;
}
/////////////////////////////////////////////////////////////////
//
// OnEngineNotify
//
void CAppletWindow::OnEngineNotify(MBFTMsg *pMsg)
{
BOOL fHeartBeat = FALSE;
switch (pMsg->GetMsgType())
{
case EnumFileOfferNotifyMsg:
if (m_UIMode != FTUIMODE_NOUI)
{
HandleFileOfferNotify((FileOfferNotifyMsg *) pMsg);
}
break;
case EnumFileTransmitMsg:
if (m_UIMode != FTUIMODE_NOUI)
{
HandleProgressNotify((FileTransmitMsg *) pMsg);
}
fHeartBeat = TRUE;
break;
case EnumFileErrorMsg:
if (m_UIMode != FTUIMODE_NOUI)
{
HandleErrorNotify((FileErrorMsg *) pMsg);
}
break;
case EnumPeerMsg:
HandlePeerNotification((PeerMsg *) pMsg);
break;
case EnumInitUnInitNotifyMsg:
HandleInitUninitNotification((InitUnInitNotifyMsg *) pMsg);
break;
case EnumFileEventEndNotifyMsg:
if (m_UIMode != FTUIMODE_NOUI)
{
HandleFileEventEndNotification((FileEventEndNotifyMsg *) pMsg);
}
break;
default:
ASSERT(0);
break;
} // switch
}
void CAppletWindow::HandleFileOfferNotify(FileOfferNotifyMsg *pMsg)
{
HRESULT hr = S_OK;
if (g_fRecvAllowed)
{
DBG_SAVE_FILE_LINE
CUiRecvFileInfo *pRecvFileInfo = new CUiRecvFileInfo(pMsg, &hr);
if (NULL != pRecvFileInfo && S_OK == hr)
{
if (NULL != m_pEngine)
{
DBG_SAVE_FILE_LINE
CRecvDlg *pDlg = new CRecvDlg(this,
m_pEngine->GetConfID(),
pMsg->m_NodeID,
pMsg->m_EventHandle,
pRecvFileInfo,
&hr);
if (NULL != pDlg && S_OK == hr)
{
DBG_SAVE_FILE_LINE
if (S_OK == m_pEngine->SafePostMessage(
new FileTransferControlMsg(
pMsg->m_EventHandle,
pMsg->m_hFile,
pRecvFileInfo->GetRecvFolder(),
pMsg->m_szFileName,
FileTransferControlMsg::EnumAcceptFile)))
{
return;
}
else
{
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot confirm file offer"));
}
}
else
{
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot allocate CRecvDlg, hr=0x%x", hr));
}
delete pDlg;
}
else
{
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: no file transfer engine"));
}
}
else
{
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot allocate CUiRecvFileInfo, hr=0x%x", hr));
}
delete pRecvFileInfo;
}
else
{
DBG_SAVE_FILE_LINE
if (S_OK != m_pEngine->SafePostMessage(
new FileTransferControlMsg(
pMsg->m_EventHandle,
pMsg->m_hFile,
NULL,
pMsg->m_szFileName,
FileTransferControlMsg::EnumRejectFile)))
{
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot confirm file offer"));
}
}
}
void CAppletWindow::HandleProgressNotify(FileTransmitMsg *pMsg)
{
CRecvDlg *pDlg = NULL;
MBFT_NOTIFICATION wMBFTCode = (MBFT_NOTIFICATION) pMsg->m_TransmitStatus;
ULONG totalSent = 0;
ULONG fileSize = 0;
ULONG percentSent = 0;
switch (wMBFTCode)
{
case iMBFT_FILE_SEND_BEGIN:
// fall through... because the file start PDU can have data.
case iMBFT_FILE_SEND_PROGRESS:
if (NULL != m_pCurrSendFileInfo)
{
ASSERT(m_nCurrSendEventHandle == pMsg->m_EventHandle);
ASSERT(m_pCurrSendFileInfo->GetFileHandle() == pMsg->m_hFile);
ASSERT(m_pCurrSendFileInfo->GetSize() == pMsg->m_FileSize);
fileSize = m_pCurrSendFileInfo->GetSize();
totalSent = m_pCurrSendFileInfo->GetTotalSend();
m_pCurrSendFileInfo->SetTotalSend(pMsg->m_BytesTransmitted);
percentSent = _GetPercent(totalSent, fileSize)*10;
if(m_pCurrSendFileInfo->GetPercentSent()!= percentSent || fileSize == totalSent)
{
UpdateListView(m_pCurrSendFileInfo);
UpdateStatusBar();
m_pCurrSendFileInfo->SetPercentSent(percentSent);
}
}
break;
break;
case iMBFT_FILE_SEND_END:
if (NULL != m_pCurrSendFileInfo)
{
UpdateListView(m_pCurrSendFileInfo);
UpdateStatusBar();
}
break;
case iMBFT_FILE_RECEIVE_BEGIN:
// fall through... because the file start PDU can have data.
case iMBFT_FILE_RECEIVE_PROGRESS:
pDlg = FindDlgByHandles(pMsg->m_EventHandle, pMsg->m_hFile);
if (NULL != pDlg)
{
pDlg->OnProgressUpdate(pMsg);
}
break;
case iMBFT_FILE_RECEIVE_END:
// doing nothing...
break;
default:
ASSERT(0);
break;
}
}
void CAppletWindow::HandleErrorNotify(FileErrorMsg *pMsg)
{
MBFTFILEHANDLE nFileHandle = pMsg->m_hFile;
if(LOWORD(nFileHandle) == LOWORD(_iMBFT_PROSHARE_ALL_FILES))
{
nFileHandle = _iMBFT_PROSHARE_ALL_FILES;
}
if (m_nCurrSendEventHandle == pMsg->m_EventHandle &&
m_pCurrSendFileInfo->GetFileHandle() == nFileHandle)
{
m_pCurrSendFileInfo->SetErrorCode((MBFT_ERROR_CODE) pMsg->m_ErrorCode);
UINT idString;
switch ((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
{
case iMBFT_OK:
idString = 0;
break;
case iMBFT_SENDER_ABORTED:
case iMBFT_RECEIVER_ABORTED:
case iMBFT_NO_MORE_FILES:
idString = IDS_MSGBOX2_CANCELED;
break;
case iMBFT_MULT_RECEIVER_ABORTED:
idString = IDS_MSGBOX2_MULT_CANCEL;
break;
// case iMBFT_RECEIVER_REJECTED:
default:
idString = IDS_MSGBOX2_SEND_FAILED;
break;
}
if (idString)
{
if (! m_pCurrSendFileInfo->HasShownUI())
{
if (::MyLoadString(idString, s_szScratchText, m_pCurrSendFileInfo->GetName()))
{
m_pCurrSendFileInfo->SetShowUI();
::MsgBox2(this, s_szScratchText);
}
else
{
ASSERT(0);
}
}
}
UpdateListView(m_pCurrSendFileInfo);
UpdateStatusBar();
ClearSendInfo(TRUE);
if (! idString)
{
// send the next one now
if (m_fSendALL)
{
::PostMessage(m_hwndMainUI, WM_SEND_NEXT, 0, 0);
}
}
}
else
{
CRecvDlg *pDlg = FindDlgByHandles(pMsg->m_EventHandle, nFileHandle);
if (NULL != pDlg)
{
switch ((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
{
case iMBFT_RECEIVER_ABORTED:
case iMBFT_MULT_RECEIVER_ABORTED:
pDlg->OnCanceled();
break;
default:
pDlg->OnRejectedFile();
break;
}
}
else
{
switch((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
{
case iMBFT_INVALID_PATH:
::MyLoadString(IDS_MSGBOX2_INVALID_DIRECTORY,
s_szScratchText, pMsg->m_stFileInfo.szFileName);
break;
case iMBFT_DIRECTORY_FULL_ERROR:
::MyLoadString(IDS_MSGBOX2_DIRECTORY_FULL,
s_szScratchText, pMsg->m_stFileInfo.lFileSize,
pMsg->m_stFileInfo.szFileName);
break;
case iMBFT_FILE_ACCESS_DENIED:
::MyLoadString(IDS_MSGBOX2_FILE_CREATE_FAILED,
s_szScratchText, pMsg->m_stFileInfo.szFileName);
break;
default:
return;
}
::MsgBox2(this, s_szScratchText);
}
}
}
void CAppletWindow::HandlePeerNotification(PeerMsg *pMsg)
{
m_pToolbar->HandlePeerNotification(m_pEngine->GetConfID(),
m_pEngine->GetNodeID(), pMsg);
}
void CAppletWindow::HandleInitUninitNotification(InitUnInitNotifyMsg *pMsg)
{
if (pMsg->m_iNotifyMessage == EnumInvoluntaryUnInit)
{
UnregisterEngine();
}
}
void CAppletWindow::HandleFileEventEndNotification(FileEventEndNotifyMsg *pMsg)
{
if (m_nCurrSendEventHandle == pMsg->m_EventHandle)
{
ClearSendInfo(TRUE);
// send the next one now
if (m_fSendALL)
{
::PostMessage(m_hwndMainUI, WM_SEND_NEXT, 0, 0);
}
}
}
/////////////////////////////////////////////////////////////////
//
// Main UI methods
//
void CAppletWindow::BringToFront(void)
{
if (NULL != m_hwndMainUI)
{
int nCmdShow = SW_SHOW;
WINDOWPLACEMENT wp;
::ZeroMemory(&wp, sizeof(wp));
wp.length = sizeof(wp);
if (::GetWindowPlacement(m_hwndMainUI, &wp))
{
if (SW_MINIMIZE == wp.showCmd || SW_SHOWMINIMIZED == wp.showCmd)
{
// The window is minimized - restore it:
nCmdShow = SW_RESTORE;
}
}
// show the window now
::ShowWindow(m_hwndMainUI, nCmdShow);
m_UIMode = FTUIMODE_SHOWUI;
// bring it to the foreground
::SetForegroundWindow(m_hwndMainUI);
}
}
void CAppletWindow::ClearSendInfo(BOOL fUpdateUI)
{
m_pCurrSendFileInfo = NULL;
m_nCurrSendEventHandle = NULL;
if (fUpdateUI)
{
UpdateUI();
}
}
void CAppletWindow::ClearRecvInfo(void)
{
CRecvDlg *pDlg;
while (NULL != (pDlg = m_RecvDlgList.Get()))
{
::EndDialog(pDlg->GetHwnd(), IDCLOSE);
pDlg->Release();
}
}
BOOL CAppletWindow::HasUnSentFiles(BOOL fUnSentOnly)
{
BOOL fRc = FALSE;
ULONG cItems = ListView_GetItemCount(m_hwndListView);
CUiSendFileInfo *pFileInfo;
LVITEM lvi;
if (!fUnSentOnly && cItems) {
return TRUE;
}
::ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM; // examine each item one by one
for (ULONG i = 0; i < cItems; i++, pFileInfo = NULL)
{
lvi.iItem = i;
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
ASSERT(fRet);
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
if (!pFileInfo->GetFileHandle()) // if file handle is not zero, then it has been sent or cancelled
{
fRc = TRUE;
break;
}
}
return fRc;
}
void CAppletWindow::UpdateUI(void)
{
UpdateTitle();
UpdateMenu();
UpdateToolBar();
UpdateStatusBar();
}
void CAppletWindow::UpdateTitle(void)
{
UINT captionID;
if ((! m_pEngine) || (m_pEngine->GetPeerCount() <= 1))
{
captionID = IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION;
}
else
{
captionID = IDS_MSFT_IN_CALL_WINDOW_CAPTION;
}
::LoadString(g_hDllInst, captionID, s_szMSFT, sizeof(s_szMSFT));
SetWindowText(m_hwndMainUI, s_szMSFT);
}
void CAppletWindow::UpdateMenu(void)
{
HMENU hMenu = ::GetMenu(m_hwndMainUI);
if (NULL != hMenu)
{
if (g_fSendAllowed)
{
BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
::EnableMenuItem(hMenu, IDM_ADD_FILES, fMoreThanOne ? MF_ENABLED : MF_GRAYED);
ULONG cItems = ListView_GetItemCount(m_hwndListView);
::EnableMenuItem(hMenu, IDM_REMOVE_FILES, cItems ? MF_ENABLED : MF_GRAYED);
::EnableMenuItem(hMenu, IDM_SEND_ALL, (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? MF_ENABLED : MF_GRAYED);
::EnableMenuItem(hMenu, IDM_SEND_ONE, (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(FALSE)) ? MF_ENABLED : MF_GRAYED);
::EnableMenuItem(hMenu, IDM_STOP_SENDING, m_nCurrSendEventHandle ? MF_ENABLED : MF_GRAYED);
}
else
{
::EnableMenuItem(hMenu, IDM_ADD_FILES, MF_GRAYED);
::EnableMenuItem(hMenu, IDM_REMOVE_FILES, MF_GRAYED);
::EnableMenuItem(hMenu, IDM_SEND_ALL, MF_GRAYED);
::EnableMenuItem(hMenu, IDM_SEND_ONE, MF_GRAYED);
::EnableMenuItem(hMenu, IDM_STOP_SENDING, MF_GRAYED);
}
}
}
void CAppletWindow::UpdateToolBar(void)
{
int iFlags[count_of(buttons)];
::ZeroMemory(iFlags, sizeof(iFlags));
iFlags[2] = iFlags[5] = iFlags[6] = 1; // separators
iFlags[7] = 1; // open recv folders
if (g_fSendAllowed)
{
BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
ULONG cItems = ListView_GetItemCount(m_hwndListView);
iFlags[0] = fMoreThanOne ? TRUE : FALSE; // Add files
iFlags[1] = cItems ? TRUE : FALSE; // Delete files
iFlags[3] = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? TRUE : FALSE; // Send file(s)
iFlags[4] = m_nCurrSendEventHandle ? TRUE : FALSE; // Stop sending
m_pToolbar->UpdateButton(iFlags);
}
else
{
m_pToolbar->UpdateButton(iFlags);
}
}
void CAppletWindow::UpdateStatusBar(void)
{
int idString, iPos = 0;
HICON hIcon;
RECT rc;
// set the text in part 0
s_szScratchText[0] = TEXT('\0');
if ((NULL != m_pEngine) && (NULL != m_pCurrSendFileInfo))
{
idString = IDS_STBAR_SENDING_XYZ;
::MyLoadString(idString, s_szScratchText, m_pCurrSendFileInfo->GetName());
}
else if (NULL == m_pEngine)
{
::MyLoadString(IDS_STBAR_NOT_IN_CALL);
}
else
{
::MyLoadString(IDS_STBAR_NOT_TRANSFERING);
}
::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_TRANSFER_FILE, (LPARAM) s_szScratchText);
// set the progres bar in part 1
if ((NULL != m_pCurrSendFileInfo)&&m_pCurrSendFileInfo->GetSize())
{
iPos = (int)_GetPercent(m_pCurrSendFileInfo->GetTotalSend(), m_pCurrSendFileInfo->GetSize());
}
::SendMessage(m_hwndStatusBar, SB_GETRECT, SBP_PROGRESS, (LPARAM)&rc);
::MoveWindow(m_hwndProgressBar,
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
FALSE);
::SendMessage(m_hwndProgressBar, PBM_SETPOS, iPos, 0);
// set the icon in part 2
hIcon = (NULL != m_pEngine) ? m_hIconInCall : m_hIconNotInCall;
::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_SBICON | SBT_OWNERDRAW, (LPARAM)hIcon);
}
void CAppletWindow::UpdateListView(CUiSendFileInfo *pFileInfo)
{
LVFINDINFO lvfi;
::ZeroMemory(&lvfi, sizeof(lvfi));
lvfi.flags = LVFI_PARAM;
lvfi.lParam = (LPARAM) pFileInfo;
int iItem = ListView_FindItem(m_hwndListView, -1, &lvfi);
if (-1 != iItem)
{
for (ULONG i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
{
ListView_SetItemText(m_hwndListView, iItem, i, LPSTR_TEXTCALLBACK);
}
}
}
////////////////////////////////////////////////////////////////////
//
// Save window position for File Transfer
//
void CAppletWindow::SaveWindowPosition(void)
{
RECT rcWnd;
RegEntry reWnd( FILEXFER_KEY, HKEY_CURRENT_USER);
// If we are not maximized or minimized
if (!::IsZoomed(m_hwndMainUI) && !::IsIconic(m_hwndMainUI))
{
::GetWindowRect(m_hwndMainUI, &rcWnd);
reWnd.SetValue (REGVAL_WINDOW_XPOS, rcWnd.left);
reWnd.SetValue (REGVAL_WINDOW_YPOS, rcWnd.top);
reWnd.SetValue (REGVAL_WINDOW_WIDTH, rcWnd.right - rcWnd.left);
reWnd.SetValue (REGVAL_WINDOW_HEIGHT, rcWnd.bottom - rcWnd.top);
}
}
void CAppletWindow::FocusNextRecvDlg(void)
{
if (!m_RecvDlgList.IsEmpty())
{
m_RecvDlgList.Reset();
CRecvDlg *pRecvDlg = m_RecvDlgList.Iterate();
if (pRecvDlg)
{
SetFocus(pRecvDlg->GetHwnd());
}
}
}
void CAppletWindow::FocusNextErrorDlg(void)
{
if (!m_ErrorDlgList.IsEmpty())
{
m_ErrorDlgList.Reset();
HWND hwndErrorDlg = m_ErrorDlgList.Iterate();
if (hwndErrorDlg)
{
::SetFocus(hwndErrorDlg);
}
}
}
/////////////////////////////////////////////////////////////////
//
// Utilities
//
LPTSTR PathNameToFileName(LPTSTR pszPathName)
{
LPTSTR psz = pszPathName;
while (*psz != '\0')
{
BOOL fDirChar = (*psz == TEXT('\\'));
psz = ::CharNext(psz);
if (fDirChar)
{
pszPathName = psz;
}
}
return pszPathName;
}
int MyLoadString(UINT idStr)
{
s_szScratchText[0] = TEXT('\0');
int iRet = ::LoadString(g_hDllInst, idStr, s_szScratchText, MAX_PATH);
ASSERT(iRet);
return iRet;
}
int MyLoadString(UINT idStr, LPTSTR pszDstStr)
{
*pszDstStr = TEXT('\0');
int iRet = ::LoadString(g_hDllInst, idStr, pszDstStr, MAX_PATH);
ASSERT(iRet);
return iRet;
}
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement)
{
int cch;
TCHAR szText[MAX_PATH];
cch = ::LoadString(g_hDllInst, idStr, szText, count_of(szText));
if (cch)
{
::wsprintf(pszDstStr, szText, pszElement);
}
else
{
ASSERT(0);
*pszDstStr = TEXT('\0');
}
return cch;
}
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, LPTSTR pszElement2)
{
int cch;
TCHAR szText[MAX_PATH];
cch = ::LoadString(g_hDllInst, idStr, szText, count_of(szText));
if (cch)
{
::wsprintf(pszDstStr, szText, pszElement1, pszElement2);
}
else
{
ASSERT(0);
*pszDstStr = TEXT('\0');
}
return cch;
}
void LoadDefaultStrings(void)
{
// load file transfer name
s_szMSFT[0] = TEXT('\0');
::LoadString(g_hDllInst, IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION,
s_szMSFT, count_of(s_szMSFT));
}
/////////////////////////////////////////////////////////////////
//
// CUiSendFileInfo
//
CUiSendFileInfo::CUiSendFileInfo(CAppletWindow *pWindow, TCHAR szDir[], TCHAR szFile[], BOOL *pfRet)
:
m_nFileHandle(0),
m_cbTotalSend(0),
m_eSendErrorCode(iMBFT_OK),
m_percentSent(-1),
m_fAlreadyShowUI(FALSE),
m_pszFullName(NULL)
{
*pfRet = FALSE; // failure as default
HANDLE hFile;
// build a full name
hFile = GetOpenFile(pWindow, szDir, szFile, TRUE); // try to resolve
if (INVALID_HANDLE_VALUE == hFile)
{
hFile = GetOpenFile(pWindow, szDir, szFile, FALSE);
}
if (INVALID_HANDLE_VALUE != hFile)
{
// get the file info
::ZeroMemory(&m_FileInfo, sizeof(m_FileInfo));
BOOL rc = ::GetFileInformationByHandle(hFile, &m_FileInfo);
::CloseHandle(hFile);
if (rc)
{
ASSERT(0 == m_FileInfo.nFileSizeHigh);
// make sure the file size is smaller than what the policy says
if ((! g_cbMaxSendFileSize) || GetSize() <= g_cbMaxSendFileSize * 1024)
{
*pfRet = TRUE;
}
else if (pWindow->GetUIMode() != FTUIMODE_NOUI)
{
::MyLoadString(IDS_MSGBOX_SEND_BIG_FILE, s_szScratchText, (LPTSTR) g_cbMaxSendFileSize, m_pszFileName);
::MessageBox(pWindow->GetHwnd(), s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
}
}
}
}
CUiSendFileInfo::~CUiSendFileInfo(void)
{
delete m_pszFullName;
}
HANDLE CUiSendFileInfo::GetOpenFile(CAppletWindow *pWindow, TCHAR szDir[], TCHAR szFile[], BOOL fResolve)
{
// build a full name
ULONG cch;
TCHAR szName[MAX_PATH*2];
HANDLE hFile = INVALID_HANDLE_VALUE;
if ((NULL != szDir)&&(!_StrChr(szFile, '\\')))
{
cch = ::lstrlen(szDir);
::wsprintf(szName, (TEXT('\\') == szDir[cch-1]) ? TEXT("%s%s") : TEXT("%s\\%s"), szDir, szFile);
}
else
{
// file name is the full name
::lstrcpy(szName, szFile);
}
// resolve shortcut if necessary
cch = ::lstrlen(szName) + 1;
if (fResolve&&(cch >= 4))
{
if (! lstrcmpi(&szName[cch-5], TEXT(".lnk")))
{
pWindow->ResolveShortcut(szName, szName);
cch = ::lstrlen(szName) + 1;
}
}
if (m_pszFullName)
{
delete [] m_pszFullName;
}
// construct the full name
DBG_SAVE_FILE_LINE
m_pszFullName = new TCHAR[cch];
if (NULL != m_pszFullName)
{
::CopyMemory(m_pszFullName, szName, cch * sizeof(TCHAR));
m_pszFileName = ::PathNameToFileName(m_pszFullName);
// open the file
hFile = ::CreateFile(m_pszFullName, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
return hFile;
}
/////////////////////////////////////////////////////////////////
//
// CUiRecvFileInfo
//
CUiRecvFileInfo::CUiRecvFileInfo(FileOfferNotifyMsg *pMsg, HRESULT *pHr)
:
m_nFileHandle(pMsg->m_hFile),
m_FileDateTime(pMsg->m_FileDateTime),
m_cbFileSize(pMsg->m_FileSize),
m_cbTotalRecvSize(0),
m_pszFullName(NULL),
m_pszRecvFolder(NULL)
{
*pHr = E_FAIL; // failure, at default
ULONG cchTotal = ::lstrlen(pMsg->m_szFileName);
// construct the full name
DBG_SAVE_FILE_LINE
m_pszFullName = new TCHAR[cchTotal+2];
if (NULL != m_pszFullName)
{
// construct full name and file name
strcpy(m_pszFullName, pMsg->m_szFileName);
m_pszFileName = PathNameToFileName(m_pszFullName);
ULONG cchFile = ::lstrlen(m_pszFileName);
DBG_SAVE_FILE_LINE
m_pszRecvFolder = new TCHAR[cchTotal - cchFile + 2];
if (NULL != m_pszRecvFolder)
{
::CopyMemory(m_pszRecvFolder, m_pszFullName, cchTotal - cchFile);
m_pszRecvFolder[cchTotal - cchFile - 1] = TEXT('\0');
*pHr = S_OK;
}
}
}
CUiRecvFileInfo::~CUiRecvFileInfo(void)
{
delete m_pszFullName;
delete m_pszRecvFolder;
}
/////////////////////////////////////////////////////////////////
//
// Receive Dialog
//
CRecvDlg::CRecvDlg
(
CAppletWindow *pWindow,
T120ConfID nConfID,
T120NodeID nidSender,
MBFTEVENTHANDLE nEventHandle,
CUiRecvFileInfo *pFileInfo,
HRESULT *pHr
)
:
CRefCount(MAKE_STAMP_ID('F','T','R','D')),
m_pWindow(pWindow),
m_nConfID(nConfID),
m_nidSender(nidSender),
m_nEventHandle(nEventHandle),
m_pRecvFileInfo(pFileInfo),
m_fRecvComplete(FALSE),
m_fShownRecvCompleteUI(FALSE),
m_idResult(0),
m_dwEstTimeLeft(0),
m_dwPreviousTime(0),
m_dwPreviousTransferred(0),
m_dwBytesPerSec(0),
m_dwStartTime(::GetTickCount())
{
*pHr = E_FAIL; // failure, at default
m_hwndRecvDlg = ::CreateDialogParam(g_hDllInst, MAKEINTRESOURCE(IDD_RECVDLG),
pWindow->GetHwnd(), RecvDlgProc, (LPARAM) this);
ASSERT(NULL != m_hwndRecvDlg);
if (NULL != m_hwndRecvDlg)
{
::ShowWindow(m_hwndRecvDlg, SW_SHOWNORMAL);
m_pWindow->RegisterRecvDlg(this);
*pHr = S_OK;
::SetForegroundWindow(m_hwndRecvDlg);
}
}
CRecvDlg::~CRecvDlg(void)
{
delete m_pRecvFileInfo;
m_pWindow->UnregisterRecvDlg(this);
if (NULL != m_hwndRecvDlg)
{
HWND hwnd = m_hwndRecvDlg;
m_hwndRecvDlg = NULL;
::EndDialog(hwnd, IDCLOSE);
}
}
/////////////////////////////////////////////////////////////////
//
// RecvDlg_OnInitDialog
//
void RecvDlg_OnInitDialog(HWND hdlg, WPARAM wParam, LPARAM lParam)
{
CRecvDlg *pDlg = (CRecvDlg *) ::GetWindowLongPtr(hdlg, DWLP_USER);
ASSERT(NULL != pDlg);
CUiRecvFileInfo *pFileInfo = (CUiRecvFileInfo *) pDlg->GetRecvFileInfo();
ASSERT(NULL != pFileInfo);
// move the window to proper location
ULONG nCaptionHeight = ::GetSystemMetrics(SM_CYCAPTION);
ULONG nShift = nCaptionHeight * (s_cRecvDlg++ % 8);
RECT rcDlg;
::GetWindowRect(hdlg, &rcDlg);
::MoveWindow(hdlg, rcDlg.left + nShift, rcDlg.top + nShift,
rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top, FALSE);
// Set font (for international)
HFONT hfont = (HFONT) ::GetStockObject(DEFAULT_GUI_FONT);
ASSERT(NULL != hfont);
::SendDlgItemMessage(hdlg, IDE_RECVDLG_RECFILE, WM_SETFONT, (WPARAM) hfont, 0);
::SendDlgItemMessage(hdlg, IDE_RECVDLG_RECDIR, WM_SETFONT, (WPARAM) hfont, 0);
::SendDlgItemMessage(hdlg, IDE_RECVDLG_SENDER, WM_SETFONT, (WPARAM) hfont, 0);
// cache names
LPTSTR pszFileName = pFileInfo->GetName();
LPTSTR pszFullName = pFileInfo->GetFullName();
// title
TCHAR szText[MAX_PATH*2];
if (::MyLoadString(IDS_RECVDLG_TITLE, szText, pszFileName))
{
::SetWindowText(hdlg, szText);
}
// filename
::lstrcpyn(szText, pszFileName, MAX_FILE_NAME_LENGTH);
if (::lstrlen(pszFileName) > MAX_FILE_NAME_LENGTH)
{
LPTSTR psz = szText;
int i = MAX_FILE_NAME_LENGTH - 1;
while (i)
{
psz = CharNext(psz);
i--;
}
::lstrcpy(psz, TEXT("..."));
}
::SetDlgItemText(hdlg, IDE_RECVDLG_RECFILE, szText);
// directory Name
LPTSTR psz = szText;
::lstrcpyn(szText, pszFullName, (int)(pszFileName - pszFullName));
HDC hdc = ::GetDC(hdlg);
if (NULL != hdc)
{
SIZE size;
if (::GetTextExtentPoint32(hdc, szText, ::lstrlen(szText), &size))
{
RECT rc;
::GetWindowRect(::GetDlgItem(hdlg, IDE_RECVDLG_RECDIR), &rc);
if (size.cx > (rc.right - rc.left))
{
// Just display the folder name
psz = (LPTSTR) ::GetFileNameFromPath(szText);
}
}
}
::ReleaseDC(hdlg, hdc);
::SetDlgItemText(hdlg, IDE_RECVDLG_RECDIR, psz);
// sender Name
if (::T120_GetNodeName(pDlg->GetConfID(), pDlg->GetSenderID(), szText, count_of(szText)))
{
::SetDlgItemText(hdlg, IDE_RECVDLG_SENDER, szText);
}
// update "Received xxx bytes of yyy"
if (::MyLoadString(IDS_RECVDLG_RECBYTES, szText, pFileInfo->GetTotalRecvSize(), pFileInfo->GetSize()))
{
::SetDlgItemText(hdlg, IDE_RECVDLG_RECBYTES, szText);
}
// progress bar
::SendMessage(GetDlgItem(hdlg, IDC_RECVDLG_PROGRESS), PBM_SETPOS, pDlg->GetPercent(), 0);
// start animation
Animate_Open(GetDlgItem(hdlg, IDC_RECVDLG_ANIMATE), MAKEINTRESOURCE(IDA_RECVDLG_ANIMATION));
// do the animation work
if (! pDlg->IsRecvComplete())
{
Animate_Play(GetDlgItem(hdlg, IDC_RECVDLG_ANIMATE), 0, -1, -1);
if (::LoadString(g_hDllInst, IDS_RECVDLG_START, szText, count_of(szText)))
{
::SetDlgItemText(hdlg, IDE_RECVDLG_TIME, szText);
}
}
// show the window now
::ShowWindow(hdlg, SW_SHOWNORMAL);
// UpdateProgress();
pDlg->OnProgressUpdate();
}
/////////////////////////////////////////////////////////////////
//
// RecvDlg_OnCommand
//
void RecvDlg_OnCommand(HWND hdlg, WPARAM wParam, LPARAM lParam)
{
CRecvDlg *pDlg = (CRecvDlg *) ::GetWindowLongPtr(hdlg, DWLP_USER);
ASSERT(NULL != pDlg);
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDM_RECVDLG_DELETE:
pDlg->OnDelete();
break;
case IDM_RECVDLG_OPEN:
pDlg->OnOpen();
break;
case IDM_RECVDLG_ACCEPT:
case IDOK:
case IDCANCEL:
case IDCLOSE:
pDlg->OnAccept();
break;
default:
return;
}
// dismiss the dialog
::EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam));
pDlg->Release();
}
void CRecvDlg::OnOpen(void)
{
// create short version of the path name
TCHAR szDir[MAX_PATH];
::GetShortPathName(m_pRecvFileInfo->GetRecvFolder(), szDir, count_of(szDir));
// create short version of the full name
TCHAR szFile[MAX_PATH];
szFile[0] = TEXT('\0');
::wsprintf(szFile, TEXT("%s\\%s"), szDir, m_pRecvFileInfo->GetName());
TRACE_OUT(("FT: Opening [%s] in [%]", m_pRecvFileInfo->GetName(), szDir));
HINSTANCE hInst = ::ShellExecute(m_pWindow->GetHwnd(),
NULL,
szFile,
NULL,
szDir,
SW_SHOWDEFAULT);
if (32 >= (DWORD_PTR) hInst)
{
WARNING_OUT(("Unable to open [%s] - showing file", szFile));
::ShellExecute(m_pWindow->GetHwnd(),
NULL,
szDir,
m_pRecvFileInfo->GetFullName(),
NULL,
SW_SHOWDEFAULT);
}
}
void CRecvDlg::OnDelete(void)
{
StopAnimation();
// check if transfer has completed
if (! m_fRecvComplete)
{
DBG_SAVE_FILE_LINE
m_pWindow->GetEngine()->SafePostMessage(
new FileTransferControlMsg(
m_nEventHandle,
m_pRecvFileInfo->GetFileHandle(),
NULL,
NULL,
FileTransferControlMsg::EnumAbortFile));
}
else
{
::DeleteFile(m_pRecvFileInfo->GetFullName());
}
}
void CRecvDlg::OnAccept(void)
{
StopAnimation();
}
/////////////////////////////////////////////////////////////////
//
// RecvDlg_OnInitMenuPopup
//
void RecvDlg_OnInitMenuPopup(HWND hdlg, WPARAM wParam, LPARAM lParam)
{
if (0 != HIWORD(lParam)) // System menu flag
{
HMENU hMenu = (HMENU) wParam; // handle of pop-up menu
::EnableMenuItem(hMenu, SC_MAXIMIZE, MF_GRAYED);
::EnableMenuItem(hMenu, SC_SIZE, MF_GRAYED);
}
}
/////////////////////////////////////////////////////////////////
//
// RecvDlgProc
//
INT_PTR CALLBACK RecvDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL fRet = TRUE; // processed
switch (uMsg)
{
case WM_INITDIALOG:
ASSERT(NULL != lParam);
::SetWindowLongPtr(hdlg, DWLP_USER, lParam);
RecvDlg_OnInitDialog(hdlg, wParam, lParam);
break;
case WM_COMMAND:
RecvDlg_OnCommand(hdlg, wParam, lParam);
break;
case WM_INITMENUPOPUP:
RecvDlg_OnInitMenuPopup(hdlg, wParam, lParam);
fRet = FALSE;
break;
// This means user wants to delete the file.
case WM_CLOSE:
RecvDlg_OnCommand(hdlg, IDCLOSE, lParam);
break;;
default:
fRet = FALSE; // not processed
break;
}
return fRet;
}
/////////////////////////////////////////////////////////////////
//
// RecvDlg Animation
//
void CRecvDlg::StopAnimation(void)
{
HWND hwnd = ::GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_ANIMATE);
if (NULL != hwnd)
{
Animate_Stop(hwnd);
Animate_Close(hwnd);
}
}
ULONG _GetPercent(ULONG cbTotalRecvSize , ULONG cbFileSize)
{
if (! cbFileSize || (cbTotalRecvSize >= cbFileSize))
{
return 100;
}
// FUTURE: Consider using EnlargedUnsignedMultiply
if (cbFileSize < 0x01000000)
{
return (cbTotalRecvSize * 100) / cbFileSize;
}
return cbTotalRecvSize / (cbFileSize / 100);
}
/////////////////////////////////////////////////////////////////
//
// RecvDlg Progress
//
ULONG CRecvDlg::GetPercent(void)
{
return _GetPercent(m_pRecvFileInfo->GetTotalRecvSize(), m_pRecvFileInfo->GetSize());
}
void CRecvDlg::OnProgressUpdate(FileTransmitMsg *pMsg)
{
if (NULL != pMsg)
{
ASSERT(iMBFT_FILE_RECEIVE_PROGRESS == (MBFT_NOTIFICATION) pMsg->m_TransmitStatus ||
iMBFT_FILE_RECEIVE_BEGIN == (MBFT_NOTIFICATION) pMsg->m_TransmitStatus);
ASSERT(m_nEventHandle == pMsg->m_EventHandle);
ASSERT(m_pRecvFileInfo->GetFileHandle() == pMsg->m_hFile);
ASSERT(m_pRecvFileInfo->GetSize() == pMsg->m_FileSize);
m_pRecvFileInfo->SetTotalRecvSize(pMsg->m_BytesTransmitted);
if (pMsg->m_BytesTransmitted >= pMsg->m_FileSize)
{
m_fRecvComplete = TRUE;
m_idResult = IDS_RECVDLG_COMPLETE;
}
}
if (m_fRecvComplete && ! m_fShownRecvCompleteUI)
{
m_fRecvComplete = TRUE;
TCHAR szText[MAX_PATH];
if (::LoadString(g_hDllInst, IDS_RECVDLG_CLOSE, szText, count_of(szText)))
{
::SetDlgItemText(m_hwndRecvDlg, IDM_RECVDLG_ACCEPT, szText);
}
if (IDS_RECVDLG_COMPLETE == m_idResult)
{
::EnableWindow(::GetDlgItem(m_hwndRecvDlg, IDM_RECVDLG_OPEN), TRUE);
}
else
{
::EnableWindow(::GetDlgItem(m_hwndRecvDlg, IDM_RECVDLG_DELETE), FALSE);
}
// Reset animation
HWND hwnd = ::GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_ANIMATE);
Animate_Stop(hwnd);
Animate_Close(hwnd);
Animate_Open(hwnd, MAKEINTRESOURCE(IDA_RECVDLG_DONE));
Animate_Seek(hwnd, ((IDS_RECVDLG_COMPLETE == m_idResult) ? 0 : 1));
m_fShownRecvCompleteUI = TRUE;
}
ULONG cbTotalRecvSize = m_pRecvFileInfo->GetTotalRecvSize();
ULONG cbFileSize = m_pRecvFileInfo->GetSize();
DWORD dwNow = ::GetTickCount();
DWORD dwBytesPerSec;
DWORD dwBytesRead;
TCHAR szOut[MAX_PATH];
if (m_dwPreviousTransferred != cbTotalRecvSize)
{
TCHAR szFmt[MAX_PATH];
// Update "Received xxx bytes of yyy"
if (::LoadString(g_hDllInst, IDS_RECVDLG_RECBYTES, szFmt, count_of(szFmt)))
{
::wsprintf(szOut, szFmt, cbTotalRecvSize, cbFileSize);
::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_RECBYTES, szOut);
}
// Update Progress Bar
if (cbTotalRecvSize)
{
::SendMessage(GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_PROGRESS), PBM_SETPOS, GetPercent(), 0);
}
}
// check if no time estimate is required
if (m_fRecvComplete)
{
if (::LoadString(g_hDllInst, m_idResult, szOut, count_of(szOut)))
{
::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_TIME, szOut);
}
return;
}
// first time we're in here for this file?
if (! m_dwPreviousTime || ! cbTotalRecvSize)
{
// no data, yet
m_dwPreviousTime = dwNow - 1000;
ASSERT(! m_dwPreviousTransferred);
ASSERT(! m_dwBytesPerSec);
return;
}
// Has enough time elapsed to update the display?
// We do this about every 5 seconds (note the adjustment for first time)
if ((dwNow - m_dwPreviousTime) < 5000)
return;
dwBytesRead = cbTotalRecvSize - m_dwPreviousTransferred;
// We take 10 times the number of bytes and divide by the number of
// tenths of a second to minimize both overflow and roundoff
dwBytesPerSec = dwBytesRead * 10 / ((dwNow - m_dwPreviousTime) / 100);
if (! dwBytesPerSec)
{
// very low transmission rate! Ignore the information?
return;
}
if (m_dwBytesPerSec)
{
// Take the average of the current transfer rate and the
// previously computed one, just to try to smooth out
// some random fluctuations
dwBytesPerSec = (dwBytesPerSec + m_dwBytesPerSec) / 2;
}
m_dwBytesPerSec = dwBytesPerSec;
// Calculate time remaining (round up by adding 1)
m_dwEstTimeLeft = ((cbFileSize - cbTotalRecvSize) / m_dwBytesPerSec) + 1;
// Reset time and # of bytes read
m_dwPreviousTime = dwNow;
m_dwPreviousTransferred = cbTotalRecvSize;
if (m_dwEstTimeLeft < 3)
{
// szOut[0] = _T('\0'); // don't bother updating when almost done
return;
}
if (m_dwEstTimeLeft > 99)
{
// dwTime is about 2 mintes
::MyLoadString(IDS_RECVDLG_MINUTES, szOut, ((m_dwEstTimeLeft / 60) + 1));
}
else
{
// Round up to 5 seconds so it doesn't look so random
::MyLoadString(IDS_RECVDLG_SECONDS, szOut, (((m_dwEstTimeLeft + 4) / 5) * 5) );
}
::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_TIME, szOut);
}
void CRecvDlg::OnCanceled(void)
{
m_idResult = IDS_RECVDLG_CANCEL;
m_fRecvComplete = TRUE;
OnProgressUpdate();
}
void CRecvDlg::OnRejectedFile(void)
{
m_idResult = IDS_RECVDLG_SENDER_CANCEL;
m_fRecvComplete = TRUE;
OnProgressUpdate();
}
//////////////////////////////////////////////////////////////////////
//
// Shortcut/Link Management
//
void CAppletWindow::ResolveShortcut(LPTSTR pszSrcFile, LPTSTR pszDstFile)
{
ASSERT(NULL != pszSrcFile && '\0' != *pszSrcFile);
ASSERT(NULL != pszDstFile);
IShellLink *psl;
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID *) &psl);
if (SUCCEEDED(hr))
{
IPersistFile *ppf;
hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *) &ppf);
if (SUCCEEDED(hr))
{
WCHAR wsz[MAX_PATH]; /* Buffer for unicode string */
#ifdef _UNICODE
::lstrcpyn(wsz, pszSrcFile, MAX_PATH);
#else
::MultiByteToWideChar(CP_ACP, 0, pszSrcFile, -1, wsz, MAX_PATH);
#endif
hr = ppf->Load(wsz, STGM_READ);
if (SUCCEEDED(hr))
{
/* Resolve the link, this may post UI to find the link */
hr = psl->Resolve(m_hwndMainUI, SLR_ANY_MATCH);
if (SUCCEEDED(hr))
{
psl->GetPath(pszDstFile, MAX_PATH, NULL, 0);
}
TRACE_OUT(("CAppletWindow::ResolveShortcut: File resolved to [%s]", pszDstFile));
}
ppf->Release();
}
psl->Release();
}
}
/////////////////////////////////////////////////////////////////
//
// Non-blocking Message Box
//
INT_PTR MsgBox2DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL fHandled = FALSE;
CAppletWindow *pWindow;
switch (uMsg)
{
case WM_INITDIALOG:
{
// get the text to display
LPTSTR pszText = (LPTSTR) lParam;
ASSERT(NULL != pszText && TEXT('\0') != *pszText);
// estimate how big the read-only edit control should be
HDC hdc = ::GetDC(hdlg);
if (NULL != hdc)
{
SIZE csEdit;
if (::GetTextExtentPoint32(hdc, pszText, ::lstrlen(pszText), &csEdit))
{
const ULONG c_nMarginX = 0;
const ULONG c_nMarginY = 10;
ULONG nCaptionHeight = ::GetSystemMetrics(SM_CYCAPTION);
ULONG nShift = nCaptionHeight * (s_cMsgBox2Dlg++ % 8);
// move the edit control
HWND hwndEdit = ::GetDlgItem(hdlg, IDE_MSGBOX2_TEXT);
POINT ptEdit;
ptEdit.x = c_nMarginX;
ptEdit.y = c_nMarginY + (c_nMarginY >> 1);
csEdit.cx += c_nMarginX << 1;
csEdit.cy += c_nMarginY << 1;
::MoveWindow(hwndEdit, ptEdit.x, ptEdit.y, csEdit.cx, csEdit.cy, FALSE);
// move the ok button
HWND hwndOK = ::GetDlgItem(hdlg, IDOK);
RECT rcOK;
::GetWindowRect(hwndOK, &rcOK);
SIZE csOK;
csOK.cx = rcOK.right - rcOK.left;
csOK.cy = rcOK.bottom - rcOK.top;
POINT ptOK;
ptOK.x = ptEdit.x + (csEdit.cx >> 1) - (csOK.cx >> 1);
ptOK.y = ptEdit.y + csEdit.cy + (c_nMarginY >> 1);
::MoveWindow(hwndOK, ptOK.x, ptOK.y, csOK.cx, csOK.cy, FALSE);
// adjust all the windows
RECT rcDlg, rcClient;
::GetWindowRect(hdlg, &rcDlg);
POINT ptDlg;
ptDlg.x = rcDlg.left + nShift;
ptDlg.y = rcDlg.top + nShift;
::GetClientRect(hdlg, &rcClient);
SIZE csDlg;
csDlg.cx = (rcDlg.right - rcDlg.left) - (rcClient.right - rcClient.left);
csDlg.cy = (rcDlg.bottom - rcDlg.top) - (rcClient.bottom - rcClient.top);
csDlg.cx += ptEdit.x + csEdit.cx + c_nMarginX;
csDlg.cy += ptOK.y + csOK.cy + c_nMarginY;
::MoveWindow(hdlg, ptDlg.x, ptDlg.y, csDlg.cx, csDlg.cy, FALSE);
}
::ReleaseDC(hdlg, hdc);
}
::SetDlgItemText(hdlg, IDE_MSGBOX2_TEXT, pszText);
delete [] pszText; // free the display text
fHandled = TRUE;
}
break;
case WM_COMMAND:
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDOK:
case IDCANCEL:
case IDCLOSE:
switch (GET_WM_COMMAND_CMD(wParam, lParam))
{
case BN_CLICKED:
pWindow = (CAppletWindow*)::GetWindowLongPtr(hdlg, DWLP_USER);
ASSERT (pWindow);
if (pWindow)
{
pWindow->RemoveErrorDlg(hdlg);
pWindow->FocusNextErrorDlg();
}
::EndDialog(hdlg, IDOK);
break;
}
break;
}
fHandled = TRUE;
break;
}
return(fHandled);
}
BOOL MsgBox2(CAppletWindow *pWindow, LPTSTR pszText)
{
BOOL fRet = FALSE;
ULONG cch = ::lstrlen(pszText) + 1;
DBG_SAVE_FILE_LINE
LPTSTR pszNew = new TCHAR[cch];
if (NULL != pszNew)
{
::CopyMemory(pszNew, pszText, cch);
HWND hwndDlg = ::CreateDialogParam(g_hDllInst, MAKEINTRESOURCE(IDD_MSGBOX2),
pWindow->GetHwnd(), MsgBox2DlgProc, (LPARAM) pszNew);
ASSERT(NULL != hwndDlg);
if (NULL != hwndDlg)
{
::ShowWindow(hwndDlg, SW_SHOWNORMAL);
fRet = TRUE;
::SetForegroundWindow(hwndDlg);
::SetWindowLongPtr(hwndDlg, DWLP_USER, (LPARAM)pWindow);
pWindow->AddErrorDlg(hwndDlg);
}
}
else
{
ERROR_OUT(("FT::MsgBox2: cannot duplicate string [%s]", pszText));
}
return fRet;
}
/////////////////////////////////////////////////////////////////
//
// Receive Folder Management
//
HRESULT GetRecvFolder(LPTSTR pszInFldr, LPTSTR pszOutFldr)
{
LPTSTR psz;
TCHAR szPath[MAX_PATH];
RegEntry reFileXfer(FILEXFER_KEY, HKEY_CURRENT_USER);
if (NULL == pszInFldr)
{
// NULL directory specified - get info from registry or use default
psz = reFileXfer.GetString(REGVAL_FILEXFER_PATH);
if (NULL != psz && TEXT('\0') != *psz)
{
::lstrcpyn(szPath, psz, count_of(szPath));
}
else
{
TCHAR szInstallDir[MAX_PATH];
::GetInstallDirectory(szInstallDir);
::MyLoadString(IDS_RECDIR_DEFAULT, szPath, szInstallDir);
}
pszInFldr = szPath;
}
::lstrcpyn(pszOutFldr, pszInFldr, MAX_PATH);
// Remove trailing backslash, if any
for (psz = pszOutFldr; *psz; psz = CharNext(psz))
{
if ('\\' == *psz && '\0' == *CharNext(psz))
{
*psz = '\0';
break;
}
}
HRESULT hr;
if (!FEnsureDirExists(pszOutFldr))
{
WARNING_OUT(("ChangeRecDir: FT directory is invalid [%s]", pszOutFldr));
hr = E_FAIL;
}
else
{
// update the registry
reFileXfer.SetValue(REGVAL_FILEXFER_PATH, pszOutFldr);
hr = S_OK;
}
return hr;
}
void EnsureTrailingSlash(LPTSTR psz)
{
LPTSTR psz2;
// Make sure the directory name has a trailing '\'
while (TEXT('\0') != *psz)
{
psz2 = ::CharNext(psz);
if (TEXT('\\') == *psz && TEXT('\0') == *psz2)
{
// The path already ends with a backslash
return;
}
psz = psz2;
}
// Append a trailing backslash
*psz = TEXT('\\');
psz = ::CharNext(psz);
*psz = TEXT('\0');
}