windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/history.cpp
2020-09-26 16:20:57 +08:00

457 lines
10 KiB
C++

// File: history.cpp
#include "precomp.h"
#include "resource.h"
#include "dirutil.h"
#include "upropdlg.h"
#include "history.h"
// CCallLogEntry flags:
const DWORD CLEF_ACCEPTED = 0x00000001;
const DWORD CLEF_REJECTED = 0x00000002;
const DWORD CLEF_AUTO_ACCEPTED = 0x00000004; // call was auto-accepted
const DWORD CLEF_TIMED_OUT = 0x00000008; // call was rejected due to timeout
const DWORD CLEF_SECURE = 0x00000010; // call was secure
const DWORD CLEF_NO_CALL = 0x40000000; // No call back information
const DWORD CLEF_DELETED = 0x80000000; // Record marked for deletion
const WCHAR g_cszwULS[] = L"ULS:";
static const int _rgIdMenu[] = {
IDM_DLGCALL_DELETE,
0
};
/* C H I S T O R Y */
/*-------------------------------------------------------------------------
%%Function: CHISTORY
-------------------------------------------------------------------------*/
CHISTORY::CHISTORY() :
CALV(IDS_DLGCALL_HISTORY, II_HISTORY, _rgIdMenu)
{
DbgMsg(iZONE_OBJECTS, "CHISTORY - Constructed(%08X)", this);
RegEntry re(LOG_INCOMING_KEY, HKEY_CURRENT_USER);
m_pszFile = PszAlloc(re.GetString(REGVAL_LOG_FILE));
// Make sure file exists and can be read/written
m_hFile = OpenLogFile();
SetAvailable(NULL != m_hFile);
}
CHISTORY::~CHISTORY()
{
if (NULL != m_hFile)
{
CloseHandle(m_hFile);
}
delete m_pszFile;
DbgMsg(iZONE_OBJECTS, "CHISTORY - Destroyed(%08X)", this);
}
int
CHISTORY::Compare
(
LPARAM param1,
LPARAM param2
)
{
int ret = 0;
LPTSTR pszName1, pszAddress1;
LPTSTR pszName2, pszAddress2;
LOGHDR logHdr1, logHdr2;
if (SUCCEEDED(ReadEntry((DWORD)param1, &logHdr1, &pszName1, &pszAddress1)))
{
if (SUCCEEDED(ReadEntry((DWORD)param2, &logHdr2, &pszName2, &pszAddress2)))
{
FILETIME ft1, ft2;
SystemTimeToFileTime(&logHdr1.sysTime, &ft1);
SystemTimeToFileTime(&logHdr2.sysTime, &ft2);
// Sort in reverse order so most recent is at the top
ret = -CompareFileTime(&ft1, &ft2);
delete pszName2;
delete pszAddress2;
}
delete pszName1;
delete pszAddress1;
}
return(ret);
}
int
CALLBACK
CHISTORY::StaticCompare
(
LPARAM param1,
LPARAM param2,
LPARAM pThis
)
{
return(reinterpret_cast<CHISTORY*>(pThis)->Compare(param1, param2));
}
///////////////////////////////////////////////////////////////////////////
// CALV methods
/* S H O W I T E M S */
/*-------------------------------------------------------------------------
%%Function: ShowItems
-------------------------------------------------------------------------*/
VOID CHISTORY::ShowItems(HWND hwnd)
{
CALV::SetHeader(hwnd, IDS_ADDRESS);
TCHAR szReceived[CCHMAXSZ];
if( FLoadString(IDS_RECEIVED, szReceived, CCHMAX(szReceived)) )
{
LV_COLUMN lvc;
ClearStruct(&lvc);
lvc.mask = LVCF_TEXT | LVCF_SUBITEM;
lvc.pszText = szReceived;
lvc.iSubItem = IDI_MISC1;
ListView_InsertColumn(hwnd, IDI_MISC1, &lvc);
}
if (!FAvailable())
return;
LoadFileData(hwnd);
ListView_SortItems( hwnd, StaticCompare, (LPARAM) this );
}
VOID CHISTORY::ClearItems(void)
{
CALV::ClearItems();
HWND hWndListView = GetHwnd();
if( IsWindow(hWndListView) )
{
ListView_DeleteColumn(hWndListView, IDI_MISC1);
}
}
VOID CHISTORY::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDM_DLGCALL_DELETE:
CmdDelete();
break;
case IDM_DLGCALL_PROPERTIES:
CmdProperties();
break;
default:
CALV::OnCommand(wParam, lParam);
break;
}
}
VOID CHISTORY::CmdDelete(void)
{
int iItem = GetSelection();
if (-1 == iItem)
return;
LPARAM lParam = LParamFromItem(iItem);
if (SUCCEEDED(DeleteEntry((DWORD)lParam)))
{
DeleteItem(iItem);
}
}
UINT CHISTORY::GetStatusString(DWORD dwCLEF)
{
if (CLEF_ACCEPTED & dwCLEF)
return IDS_HISTORY_ACCEPTED;
if (CLEF_TIMED_OUT & dwCLEF)
return IDS_HISTORY_NOT_ANSWERED;
ASSERT(CLEF_REJECTED & dwCLEF);
return IDS_HISTORY_IGNORED;
}
VOID CHISTORY::CmdProperties(void)
{
int iItem = GetSelection();
if (-1 == iItem)
return;
LPTSTR pszName;
LPTSTR pszAddress;
TCHAR szStatus[CCHMAXSZ];
TCHAR szTime[CCHMAXSZ];
LOGHDR logHdr;
PBYTE pbCert = NULL;
PCCERT_CONTEXT pCert = NULL;
LPARAM lParam = LParamFromItem(iItem);
if (SUCCEEDED(ReadEntry((DWORD)lParam, &logHdr, &pszName, &pszAddress)))
{
if (logHdr.dwCLEF & CLEF_SECURE) // is secure call
{
ASSERT(logHdr.cbCert);
pbCert = new BYTE[logHdr.cbCert];
if (FSetFilePos(lParam+sizeof(logHdr)+logHdr.cbName+logHdr.cbData))
{
if (FReadData(pbCert, logHdr.cbCert))
{
pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pbCert, logHdr.cbCert);
if (NULL == pCert)
{
WARNING_OUT(("Certificate in Call Log is damaged."));
}
}
}
delete []pbCert;
}
FLoadString(GetStatusString(logHdr.dwCLEF), szStatus, CCHMAX(szStatus));
FmtDateTime(&logHdr.sysTime, szTime, CCHMAX(szTime));
if (NULL == pszAddress)
{
pszAddress = PszLoadString(IDS_HISTORY_NO_ADDRESS);
}
UPROPDLGENTRY rgProp[] = {
{IDS_UPROP_ADDRESS, pszAddress},
{IDS_UPROP_STATUS, szStatus},
{IDS_UPROP_RECEIVED, szTime},
};
CUserPropertiesDlg dlgUserProp(GetHwnd(), IDI_LARGE);
dlgUserProp.DoModal(rgProp, ARRAY_ELEMENTS(rgProp), pszName, pCert);
}
if ( pCert )
CertFreeCertificateContext ( pCert );
delete pszName;
delete pszAddress;
}
///////////////////////////////////////////////////////////////////////////
/* O P E N L O G F I L E */
/*-------------------------------------------------------------------------
%%Function: OpenLogFile
Open the log file and return a handle to file.
Return NULL if there was a problem.
-------------------------------------------------------------------------*/
HANDLE CHISTORY::OpenLogFile(VOID)
{
HANDLE hFile = CreateFile(m_pszFile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
ERROR_OUT(("OpenLogFile: Unable to open call log file"));
hFile = NULL;
}
return hFile;
}
BOOL CHISTORY::FSetFilePos(DWORD dwOffset)
{
ASSERT(NULL != m_hFile);
return (INVALID_FILE_SIZE != SetFilePointer(m_hFile, dwOffset, NULL, FILE_BEGIN));
}
/* L O A D F I L E D A T A */
/*-------------------------------------------------------------------------
%%Function: LoadFileData
Load the call log data from the file
-------------------------------------------------------------------------*/
VOID CHISTORY::LoadFileData(HWND hwnd)
{
HANDLE hFile = OpenLogFile();
if (NULL == hFile)
return;
LPTSTR pszName, pszAddress;
LOGHDR logHdr;
DWORD dwOffset = 0;
HRESULT hr = S_OK;
while (SUCCEEDED(hr))
{
hr = ReadEntry(dwOffset, &logHdr, &pszName, &pszAddress);
if (S_OK == hr)
{
TCHAR szTime[CCHMAXSZ];
FmtDateTime(&logHdr.sysTime, szTime, CCHMAX(szTime));
DlgCallAddItem(hwnd, pszName, pszAddress, II_COMPUTER, dwOffset, 0,
szTime);
}
dwOffset += logHdr.dwSize;
delete pszName;
pszName = NULL;
delete pszAddress;
pszAddress = NULL;
}
CloseHandle(hFile);
}
/* R E A D E N T R Y */
/*-------------------------------------------------------------------------
%%Function: ReadEntry
Read the next entry from the file.
Return Values:
S_OK - data was read successfully
S_FALSE - data exists, but was deleted
E_FAIL - problem reading file
-------------------------------------------------------------------------*/
HRESULT CHISTORY::ReadEntry(DWORD dwOffset,
LOGHDR * pLogHdr, LPTSTR * ppszName, LPTSTR * ppszAddress)
{
ASSERT(NULL != m_hFile);
*ppszName = NULL;
*ppszAddress = NULL;
if (!FSetFilePos(dwOffset))
return E_FAIL;
// Read record header
if (!FReadData(pLogHdr, sizeof(LOGHDR)) )
return E_FAIL;
// Read Name
WCHAR szwName[CCHMAXSZ_NAME];
if (!FReadData(szwName, min(pLogHdr->cbName, sizeof(szwName))))
return E_FAIL;
*ppszName = PszFromBstr(szwName);
if (FReadData(szwName, min(pLogHdr->cbData, sizeof(szwName))))
{
LPCWSTR pchw = _StrStrW(szwName, g_cszwULS);
if (NULL != pchw)
{
pchw += CCHMAX(g_cszwULS)-1; // -1 for NULL
*ppszAddress = PszFromBstr(pchw);
}
}
return (0 == (pLogHdr->dwCLEF & CLEF_DELETED)) ? S_OK : S_FALSE;
}
/* R E A D D A T A */
/*-------------------------------------------------------------------------
%%Function: FReadData
-------------------------------------------------------------------------*/
BOOL CHISTORY::FReadData(PVOID pv, UINT cb)
{
DWORD cbRead;
ASSERT(NULL != m_hFile);
ASSERT(NULL != pv);
if (0 == cb)
return TRUE;
if (!ReadFile(m_hFile, pv, cb, &cbRead, NULL))
return FALSE;
return (cb == cbRead);
}
/* D E L E T E E N T R Y */
/*-------------------------------------------------------------------------
%%Function: DeleteEntry
Delete a single entry.
-------------------------------------------------------------------------*/
HRESULT CHISTORY::DeleteEntry(DWORD dwOffset)
{
// Calculate offset to "CLEF"
dwOffset += FIELD_OFFSET(LOGHDR,dwCLEF);
if (!FSetFilePos(dwOffset))
return E_FAIL;
DWORD dwFlags;
if (!FReadData(&dwFlags, sizeof(dwFlags)))
return E_FAIL;
dwFlags = dwFlags | CLEF_DELETED;
if (!FSetFilePos(dwOffset))
return E_FAIL;
return WriteData(&dwOffset, &dwFlags, sizeof(dwFlags));
}
/* W R I T E D A T A */
/*-------------------------------------------------------------------------
%%Function: WriteData
Write the data to the file.
The file will be automatically opened/close if hFile is NULL.
-------------------------------------------------------------------------*/
HRESULT CHISTORY::WriteData(LPDWORD pdwOffset, PVOID pv, DWORD cb)
{
ASSERT(NULL != m_hFile);
ASSERT(0 != cb);
ASSERT(NULL != pv);
ASSERT(NULL != pdwOffset);
ASSERT(INVALID_FILE_SIZE != *pdwOffset);
HRESULT hr = E_FAIL;
if (FSetFilePos(*pdwOffset))
{
DWORD cbWritten;
if (WriteFile(m_hFile, pv, cb, &cbWritten, NULL) && (cb == cbWritten))
{
*pdwOffset += cbWritten;
hr = S_OK;
}
}
return hr;
}