|
|
///////////////////////////////////////////////////////////////////////////////
/* File: action.cpp
Description: Implements classes to handle actions associated with user notifications (email, popup dialog etc). CAction CActionEmail CActionPopup
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 07/01/97 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
#include <precomp.hxx>
#pragma hdrstop
#include <commctrl.h>
#include "action.h"
#include "history.h"
#include "stats.h"
#include "resource.h"
#include "mapisend.h"
//-----------------------------------------------------------------------------
// CActionEmail
//-----------------------------------------------------------------------------
#ifdef UNICODE
# define EMAIL_UNICODE TRUE
#else
# define EMAIL_UNICODE FALSE
#endif
CActionEmail::CActionEmail( CMapiSession& MapiSession, // For sending message.
LPMAPIFOLDER pMapiFolder, // For initializing message object.
LPTSTR pszRecipientsTo, // Other recips on "To:" line.
LPTSTR pszRecipientsCc, // Other recips on "Cc:" line.
LPTSTR pszRecipientsBcc, // Other recips on "Bcc:" line.
LPCTSTR pszSubject, // Message subject line.
CMapiMessageBody& MsgBody // Message body text.
) : m_MapiSession(MapiSession), m_MapiRecipients(EMAIL_UNICODE), m_MapiMsg(pMapiFolder, MsgBody, pszSubject) { HRESULT hr;
m_Mapi.Load();
//
// NOTE: We hold a reference to a CMapiSession object.
// The CMapiSession object doen't employ any reference
// counting of it's own. This code assumes that the
// lifetime of the referenced section object exceeds the
// lifetime of the action object.
LPSPropValue pProps = NULL; ULONG cbProps = 0;
//
// Get the address properties for the MAPI session user.
//
hr = m_MapiSession.GetSessionUser(&pProps, &cbProps); if (SUCCEEDED(hr)) { if (5 == cbProps) { SPropValue rgProp[5];
//
// Get the string resource containing "NT Disk Quota Administrator".
// It's a resource for localization.
//
// FEATURE: This currently doesn't work although the Exchange guys
// tell me it should. Currently, the mail message always
// arrives with the local user's name on the "From:" line.
// It should read "NT Disk Quota Administrator".
// Needs work. [brianau - 07/10/97]
//
CString strEmailFromName(g_hInstDll, IDS_EMAIL_FROM_NAME);
//
// Set the "PR_SENT_REPRESENTING_XXXX" props to the same
// values as the "PR_SENDER_XXXX" props.
//
rgProp[0].ulPropTag = PR_SENT_REPRESENTING_ADDRTYPE; rgProp[0].Value.LPSZ = pProps[0].Value.LPSZ;
rgProp[1].ulPropTag = PR_SENT_REPRESENTING_NAME; rgProp[1].Value.LPSZ = (LPTSTR)strEmailFromName;
rgProp[2].ulPropTag = PR_SENT_REPRESENTING_EMAIL_ADDRESS; rgProp[2].Value.LPSZ = pProps[2].Value.LPSZ;
rgProp[3].ulPropTag = PR_SENT_REPRESENTING_ENTRYID; rgProp[3].Value.bin.cb = pProps[3].Value.bin.cb; rgProp[3].Value.bin.lpb = pProps[3].Value.bin.lpb;
rgProp[4].ulPropTag = PR_SENT_REPRESENTING_SEARCH_KEY; rgProp[4].Value.bin.cb = pProps[4].Value.bin.cb; rgProp[4].Value.bin.lpb = pProps[4].Value.bin.lpb;
LPSPropProblemArray pProblems = NULL;
//
// Set the new properties.
//
hr = m_MapiMsg.SetProps(ARRAYSIZE(rgProp), rgProp, &pProblems); hr = m_MapiMsg.SaveChanges(KEEP_OPEN_READWRITE);
//
// Add the recipient to the list of recipients.
//
hr = m_MapiRecipients.AddRecipient(pProps[2].Value.LPSZ, MAPI_TO); } m_Mapi.FreeBuffer(pProps); }
//
// Each element of this array contains a pointer to a list of
// recipient names (semicolon-delmited) and a recipient type
// code. This allows us to process all of the recipients
// in a single loop.
//
struct recip { LPTSTR pszName; DWORD dwType; } rgRecips[] = { { pszRecipientsTo, MAPI_TO }, { pszRecipientsCc, MAPI_CC }, { pszRecipientsBcc, MAPI_BCC }, };
for (INT i = 0; i < ARRAYSIZE(rgRecips); i++) { LPTSTR pszNext = rgRecips[i].pszName; LPCTSTR pszPrev = pszNext; //
// Process the current list of recipient names until we reach
// the terminating nul character.
//
while(TEXT('\0') != *pszPrev) { while((TEXT('\0') != *pszNext) && (TEXT(';') != *pszNext)) { //
// Find the next semicolon or the terminating nul.
//
pszNext++; } if (TEXT('\0') != *pszNext) { //
// Found a semicolon. Replace it with a nul and
// skip ahead to the start of the next name.
//
*pszNext++ = TEXT('\0'); } //
// Add the name of the recipient pointed to by pszPrev
// using the type code associated with this list of recipients.
//
m_MapiRecipients.AddRecipient(pszPrev, rgRecips[i].dwType); pszPrev = pszNext; } } }
CActionEmail::~CActionEmail( VOID ) { m_Mapi.Unload(); }
//
// Send the email and record the send operation in our history record.
//
HRESULT CActionEmail::DoAction( CHistory& history ) { HRESULT hr;
//
// Try sending the mail using the current ANSI/Unicode contents.
//
hr = m_MapiSession.Send(m_MapiRecipients, m_MapiMsg); if (MAPI_E_BAD_CHARWIDTH == hr) { //
// Failed because the provider can't handle the character width.
// Convert the address list to the opposite character width.
//
// FEATURE: Currently, we just convert the address list. We
// should probably do the same thing with the message body
// and subject line.
//
CMapiRecipients recipTemp(!m_MapiRecipients.IsUnicode()); recipTemp = m_MapiRecipients; //
// Try to send again.
//
hr = m_MapiSession.Send(recipTemp, m_MapiMsg); } if (SUCCEEDED(hr)) { //
// Record in the history log that we've sent email.
//
history.RecordEmailSent(); } return hr; }
//-----------------------------------------------------------------------------
// CActionPopup
//-----------------------------------------------------------------------------
UINT CActionPopup::m_idAutoCloseTimer = 1; UINT CActionPopup::m_uAutoCloseTimeout = 300000; // Timeout in 5 minutes.
CActionPopup::CActionPopup( CStatisticsList& stats ) : m_stats(stats), m_hiconDialog(NULL), m_hwnd(NULL) { m_hiconDialog = LoadIcon(g_hInstDll, MAKEINTRESOURCE(IDI_QUOTA)); }
CActionPopup::~CActionPopup( VOID ) {
}
typedef BOOL (WINAPI *LPFNINITCOMMONCONTROLSEX)(LPINITCOMMONCONTROLSEX);
HRESULT CActionPopup::CreateAndRunPopup( HINSTANCE hInst, LPCTSTR pszDlgTemplate, HWND hwndParent ) { INT iResult = 1;
//
// Load and initialize comctl32.dll.
// We need it for the listview control in the dialog.
//
m_hmodCOMCTL32 = ::LoadLibrary(TEXT("comctl32.dll")); if (NULL != m_hmodCOMCTL32) { LPFNINITCOMMONCONTROLSEX pfnInitCommonControlsEx = NULL;
pfnInitCommonControlsEx = (LPFNINITCOMMONCONTROLSEX)::GetProcAddress(m_hmodCOMCTL32, "InitCommonControlsEx"); if (NULL != pfnInitCommonControlsEx) { INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(iccex); iccex.dwICC = ICC_LISTVIEW_CLASSES;
if ((*pfnInitCommonControlsEx)(&iccex)) { iResult = DialogBoxParam(hInst, pszDlgTemplate, hwndParent, DlgProc, (LPARAM)this); } } }
return (0 == iResult) ? NOERROR : E_FAIL; }
HRESULT CActionPopup::DoAction( CHistory& history ) { HRESULT hr = E_FAIL; if (0 == CreateAndRunPopup(g_hInstDll, MAKEINTRESOURCE(IDD_QUOTA_POPUP), GetDesktopWindow())) { //
// Record in the history log that we've popped up a dialog.
//
history.RecordDialogPoppedUp(); hr = NOERROR; }
return hr; }
///////////////////////////////////////////////////////////////////////////////
/* Function: CActionPopup::DlgProc [static]
Description: Message procedure for the dialog.
Arguments: Standard Win32 message proc arguments.
Returns: Standard Win32 message proc return values.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 05/28/97 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK CActionPopup::DlgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { //
// Retrieve the dialog object's ptr from the window's userdata.
// Place there in response to WM_INITDIALOG.
//
CActionPopup *pThis = (CActionPopup *)GetWindowLong(hwnd, GWL_USERDATA);
switch(uMsg) { case WM_INITDIALOG: //
// Store "this" ptr in window's userdata.
//
SetWindowLong(hwnd, GWL_USERDATA, (LONG)lParam); pThis = (CActionPopup *)lParam; //
// Save the HWND in our object. We'll need it later.
//
pThis->m_hwnd = hwnd;
return pThis->OnInitDialog(hwnd);
case WM_DESTROY: return pThis->OnDestroy(hwnd);
case WM_NCDESTROY: return pThis->OnNcDestroy(hwnd);
case WM_TIMER: if (m_idAutoCloseTimer != wParam) break; //
// Fall through to EndDialog...
//
DebugMsg(DM_ERROR, TEXT("CActionPopup::DlgProc - Dialog closed automatically."));
case WM_COMMAND: EndDialog(hwnd, 0); break;
} return FALSE; }
BOOL CActionPopup::OnInitDialog( HWND hwnd ) { BOOL bResult = TRUE;
//
// Set the quota icon.
//
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)m_hiconDialog); SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)m_hiconDialog);
//
// Populate the listview with notification records.
//
InitializeList(GetDlgItem(hwnd, IDC_LIST_POPUP));
//
// Set the timer that will automatically close the dialog after 2 minutes.
//
SetTimer(hwnd, m_idAutoCloseTimer, m_uAutoCloseTimeout, NULL);
return bResult; }
///////////////////////////////////////////////////////////////////////////////
/* Function: CActionPopup::OnDestroy
Description:
Arguments: hwnd - Dialog window handle. Returns: Always returns FALSE.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 07/01/97 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
BOOL CActionPopup::OnDestroy( HWND hwnd ) { KillTimer(hwnd, m_idAutoCloseTimer); return FALSE; }
///////////////////////////////////////////////////////////////////////////////
/* Function: CActionPopup::OnNcDestroy
Description:
Arguments: hwnd - Dialog window handle. Returns: Always returns FALSE.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 07/01/97 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
BOOL CActionPopup::OnNcDestroy( HWND hwnd ) { //
// We no longer need comctl32.
// Unload it.
//
if (NULL != m_hmodCOMCTL32) { FreeLibrary(m_hmodCOMCTL32); m_hmodCOMCTL32 = NULL; } return FALSE; }
//
// Creates the listview columns and populates the listview from
// the statistics list object.
//
VOID CActionPopup::InitializeList( HWND hwndList ) { //
// We want to base pixel units off of dialog units.
//
INT DialogBaseUnitsX = LOWORD(GetDialogBaseUnits());
#define PIXELSX(du) ((INT)((DialogBaseUnitsX * du) / 4))
//
// Create the header titles.
//
CString strVolume(g_hInstDll, IDS_LVHDR_VOLUME); CString strUsed(g_hInstDll, IDS_LVHDR_USED); CString strWarning(g_hInstDll, IDS_LVHDR_WARNING); CString strLimit(g_hInstDll, IDS_LVHDR_LIMIT);
#define LVCOLMASK (LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM)
LV_COLUMN rgCols[] = { { LVCOLMASK, LVCFMT_LEFT, PIXELSX(70), strVolume, 0, 0 }, { LVCOLMASK, LVCFMT_LEFT, PIXELSX(60), strUsed, 0, 1 }, { LVCOLMASK, LVCFMT_LEFT, PIXELSX(50), strWarning, 0, 2 }, { LVCOLMASK, LVCFMT_LEFT, PIXELSX(50), strLimit, 0, 3 } };
//
// Add the columns to the listview.
//
for (INT i = 0; i < ARRAYSIZE(rgCols); i++) { if (-1 == ListView_InsertColumn(hwndList, i, &rgCols[i])) { DebugMsg(DM_ERROR, TEXT("CActionPopup::InitializeList failed to add column %d"), i); } }
//
// How many statistics objects are there in the stats list?
//
INT cEntries = m_stats.Count(); //
// This prevents the listview from having to extend itself each time we
// add an item.
//
ListView_SetItemCount(hwndList, cEntries);
//
// Item struct for adding listview items and setting item text.
//
LV_ITEM item; item.mask = LVIF_TEXT;
//
// Scratch string for storing formatted column text.
//
CString str;
//
// For each row...
//
INT iRow = 0; for (INT iEntry = 0; iEntry < cEntries; iEntry++) { item.iItem = iRow; //
// Retrieve the statistics object for this row.
//
const CStatistics *pStats = m_stats.GetEntry(iEntry); Assert(NULL != pStats);
if (0 == iEntry) { //
// First row. Get the user's display name and
// format/set the header message.
//
str.Format(g_hInstDll, IDS_POPUP_HEADER); SetWindowText(GetDlgItem(m_hwnd, IDC_TXT_POPUP_HEADER), str); } if (pStats->IncludeInReport()) { //
// For each column...
//
for (INT iCol = 0; iCol < ARRAYSIZE(rgCols); iCol++) { item.iSubItem = iCol; switch(iCol) { case 0: //
// Location (volume display name)
//
item.pszText = pStats->GetVolumeDisplayName() ? (LPTSTR)((LPCTSTR)pStats->GetVolumeDisplayName()) : TEXT(""); break;
case 1: { TCHAR szBytes[40]; TCHAR szBytesOver[40]; //
// Quota Used
//
XBytes::FormatByteCountForDisplay(pStats->GetUserQuotaUsed().QuadPart, szBytes, ARRAYSIZE(szBytes));
__int64 diff = pStats->GetUserQuotaUsed().QuadPart - pStats->GetUserQuotaThreshold().QuadPart; if (0 > diff) { diff = 0; }
XBytes::FormatByteCountForDisplay(diff, szBytesOver, ARRAYSIZE(szBytesOver)); str.Format(g_hInstDll, IDS_LVFMT_USED, szBytes, szBytesOver);
item.pszText = (LPTSTR)str; break; }
case 2: //
// Warning Level
//
XBytes::FormatByteCountForDisplay(pStats->GetUserQuotaThreshold().QuadPart, str.GetBuffer(40), 40); item.pszText = (LPTSTR)str; break;
case 3: //
// Quota Limit.
//
XBytes::FormatByteCountForDisplay(pStats->GetUserQuotaLimit().QuadPart, str.GetBuffer(40), 40); item.pszText = (LPTSTR)str; break;
default: break; } if (0 == iCol) { //
// Add the item to the listview.
//
if (-1 == ListView_InsertItem(hwndList, &item)) { DebugMsg(DM_ERROR, TEXT("CActionPopup::InitializeList failed to add entry %d,%d"), iRow, iCol); } } else { //
// Set the text for a listview column entry.
// Note: There's no return value to check.
//
ListView_SetItemText(hwndList, iRow, iCol, (item.pszText)); } } iRow++; } } }
|