// --perftest.c-----------------------------------------------------------------
//
// Performance monitoring sample.
//
// Copyright (C) Microsoft Corp. 1986-1996. All Rights Reserved.
// -----------------------------------------------------------------------------
#include "edk.h"
#include "gwmain.h"
#include "prfcount.h"
#include "monitor.h"
#include "perftest.chk"
// Defined for NT service shell
TCHAR szAppName[] = TEXT("PERFTEST");
TCHAR szWindowTitle[] = TEXT("Performance Monitoring Sample");
static LPMAPISESSION lpSession = NULL;
static LPMDB lpStore = NULL;
static LPMAPIFOLDER lpRootFolder = NULL;
static LPMAPIFOLDER lpMtsInFolder = NULL;
static LPMAPIFOLDER lpMtsOutFolder = NULL;
static ULONG cbGalEid = 0;
static LPENTRYID lpGalEid = NULL;
#define REPLY_PREFIX "RE: "
TCHAR szServiceName[MAX_SERVICE_NAME_LENGTH+1] = {0};
static BOOL fMonitorRunning= FALSE;
LPCOUNTER lpcntUserDefinedCounter = NULL;
// The array rgcdCounters describes the counters published to the performance
// monitor by PerfTest. Defined constants named PLACEHOLDER_* must be replaced
// by pointers to MAPI folder objects before calling HrMonInit.
#define PLACEHOLDER_MTS_OUT ((LPMAPIFOLDER) 1)
COUNTERDEF rgcdCounters[] =
{
{
COUNTER_MESSAGES_IN,
COUNTERTYPE_MESSAGES_TRANSFERRED_IN,
NULL,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_BYTES_IN,
COUNTERTYPE_BYTES_TRANSFERRED_IN,
NULL,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_MESSAGES_OUT,
COUNTERTYPE_MESSAGES_TRANSFERRED_OUT,
NULL,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_BYTES_OUT,
COUNTERTYPE_BYTES_TRANSFERRED_OUT,
NULL,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_MESSAGES_IN_OUT_QUEUE,
COUNTERTYPE_MESSAGES_IN_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_NONE,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_BYTES_IN_OUT_QUEUE,
COUNTERTYPE_BYTES_IN_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_NONE,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_MESSAGES_ENTERING_OUT_QUEUE,
COUNTERTYPE_MESSAGES_ENTERING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_BYTES_ENTERING_OUT_QUEUE,
COUNTERTYPE_BYTES_ENTERING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_MESSAGES_LEAVING_OUT_QUEUE,
COUNTERTYPE_MESSAGES_LEAVING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_BYTES_LEAVING_OUT_QUEUE,
COUNTERTYPE_BYTES_LEAVING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_CONTINUOUS,
0,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_HOUR_MESSAGES_ENTERING_OUT_QUEUE,
COUNTERTYPE_MESSAGES_ENTERING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_LAST_N_MINUTES,
60,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_HOUR_BYTES_ENTERING_OUT_QUEUE,
COUNTERTYPE_BYTES_ENTERING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_LAST_N_MINUTES,
60,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_HOUR_MESSAGES_LEAVING_OUT_QUEUE,
COUNTERTYPE_MESSAGES_LEAVING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_LAST_N_MINUTES,
60,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_HOUR_BYTES_LEAVING_OUT_QUEUE,
COUNTERTYPE_BYTES_LEAVING_FOLDER,
PLACEHOLDER_MTS_OUT,
PERIODTYPE_LAST_N_MINUTES,
60,
NULL,
0,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_USER_1,
COUNTERTYPE_USER_DEFINED,
NULL,
PERIODTYPE_NONE,
0,
&lpcntUserDefinedCounter,
PERF_COUNTER_RAWCOUNT,
PERF_DETAIL_NOVICE,
0
},
{
COUNTER_USER_2,
COUNTERTYPE_USER_DEFINED,
NULL,
PERIODTYPE_NONE,
0,
&lpcntUserDefinedCounter,
PERF_COUNTER_LARGE_RAWCOUNT,
PERF_DETAIL_NOVICE,
0
},
};
//$--HrCreateReplySubject-------------------------------------------------------
// Create reply subject.
// -----------------------------------------------------------------------------
HRESULT HrCreateReplySubject( // RETURNS: HRESULT
IN OUT LPMESSAGE lpMessage) // pointer to message
{
HRESULT hr = NOERROR;
SCODE sc = 0;
ULONG cbSubject = 0;
LPTSTR lpszSubject = NULL;
LPTSTR lpszReplySubject = NULL;
DEBUGPUBLIC("HrCreateReplySubject()\n");
hr = CHK_HrCreateReplySubject(lpMessage);
if (FAILED(hr))
RETURN(hr);
hr = HrMAPIGetPropString(
(LPMAPIPROP)lpMessage,
PR_SUBJECT,
&cbSubject,
(void **)&lpszSubject);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cbSubject =
(lstrlen(lpszSubject) + lstrlen(REPLY_PREFIX) + 1) * sizeof(TCHAR);
sc = MAPIAllocateBuffer(
cbSubject,
(void **)&lpszReplySubject);
if(FAILED(sc))
{
hr = HR_LOG(E_OUTOFMEMORY);
goto cleanup;
}
lstrcpy(lpszReplySubject, REPLY_PREFIX);
lstrcat(lpszReplySubject, lpszSubject);
hr = HrMAPISetPropString(
(LPMAPIPROP)lpMessage,
PR_SUBJECT,
lpszReplySubject);
MAPIFREEBUFFER(lpszReplySubject);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
RETURN(hr);
}
//$--HrCreateReplyRecipients----------------------------------------------------
// Create reply recipients
// -----------------------------------------------------------------------------
HRESULT HrCreateReplyRecipients( // RETURNS: HRESULT
IN MSG_T msgType, // message type
IN OUT LPMESSAGE lpMessage) // pointer to message
{
HRESULT hr = NOERROR;
HRESULT hrT = NOERROR;
LPADRLIST lpAdrList = NULL;
ULONG cValues = 0;
LPSPropValue lpProps = NULL;
LPSPropTagArray lpPropTags = NULL;
SizedSPropTagArray(6, rgEnvPropTags) =
{
6,
{
PR_ORIGINATOR_NAME,
PR_ORIGINATOR_ADDRTYPE,
PR_ORIGINATOR_ADDR,
PR_ORIGINATOR_ENTRYID,
// The next two properties won't exist on the envelope, but
// are place holders so that we can add them to the resulting
// structure without having to re-allocate memory.
PR_RECIPIENT_TYPE,
PR_RECIPIENT_NUMBER,
}
};
SizedSPropTagArray(5, rgMsgPropTags) =
{
5,
{
PR_SENDER_NAME,
PR_SENDER_ADDRTYPE,
PR_SENDER_EMAIL_ADDRESS,
PR_SENDER_ENTRYID,
// The next property won't exist on the message, but
// is a place holder so that we can add it to the resulting
// structure without having to re-allocate memory.
PR_RECIPIENT_TYPE
}
};
DEBUGPUBLIC("HrCreateReplyRecipients()\n");
hr = CHK_HrCreateReplyRecipients(msgType, lpMessage);
if(FAILED(hr))
RETURN(hr);
switch(msgType)
{
case MSG_ENVELOPE:
lpPropTags = (LPSPropTagArray)&rgEnvPropTags;
break;
case MSG_CONTENT:
lpPropTags = (LPSPropTagArray)&rgMsgPropTags;
break;
default:
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hrT = MAPICALL(lpMessage)->GetProps(
lpMessage,
lpPropTags,
fMapiUnicode,
&cValues,
&lpProps);
// If as expected, there were errors returned make sure they aren't
// in the first four properties. The last one(s) are just placeholders.
if (hrT == MAPI_W_ERRORS_RETURNED)
{
int i = 0;
for (i = 0; i < 4; i++)
{
if (PROP_TYPE(lpProps[i].ulPropTag) == PT_ERROR)
{
MAPIFREEBUFFER(lpProps);
hr = HR_LOG(E_FAIL);
goto cleanup;
}
}
hrT = NOERROR;
}
if (FAILED(hrT))
{
lpProps = NULL;
hr = HR_LOG(E_FAIL);
goto cleanup;
}
lpProps[0].ulPropTag = PR_DISPLAY_NAME;
lpProps[1].ulPropTag = PR_ADDRTYPE;
lpProps[2].ulPropTag = PR_EMAIL_ADDRESS;
lpProps[3].ulPropTag = PR_ENTRYID;
lpProps[4].ulPropTag = PR_RECIPIENT_TYPE;
lpProps[4].Value.l = MAPI_TO;
if(cValues == 6)
{
lpProps[5].ulPropTag = PR_RECIPIENT_NUMBER;
lpProps[5].Value.l = 1;
}
hr = HrMAPICreateSizedAddressList(
1,
&lpAdrList);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hr = HrMAPISetAddressList(
0,
cValues,
lpProps,
lpAdrList);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hrT = MAPICALL(lpMessage)->ModifyRecipients(lpMessage, (ULONG)0, lpAdrList);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
MAPIFREEBUFFER(lpProps);
FREEPADRLIST(lpAdrList);
RETURN(hr);
}
//$--HrSetDeleteAfterSubmit-----------------------------------------------------
// Set PR_DELETE_AFTER_SUBMIT to TRUE.
// -----------------------------------------------------------------------------
HRESULT HrSetDeleteAfterSubmit( // RETURNS: HRESULT
IN OUT LPMESSAGE lpMessage) // pointer to message
{
HRESULT hr = NOERROR;
DEBUGPUBLIC("HrSetDeleteAfterSubmit()\n");
hr = CHK_HrSetDeleteAfterSubmit(lpMessage);
if (FAILED(hr))
RETURN(hr);
hr = HrMAPISetPropBoolean(
(LPMAPIPROP)lpMessage,
PR_DELETE_AFTER_SUBMIT,
TRUE);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
RETURN(hr);
}
//$--Process--------------------------------------------------------------------
// Process messages arriving at MTS-OUT.
// -----------------------------------------------------------------------------
DWORD Process(
LPVOID lpParameter)
{
HRESULT hr = NOERROR;
HRESULT hrT = 0;
ULONG i = 0;
ULONG cRows = 0;
ULONG cValues = 0;
ULONG ulObjType = 0;
LPADRBOOK lpAdrBook = NULL;
LPMESSAGE lpMessage = NULL;
LPMESSAGE lpEnvelope = NULL;
LPATTACH lpAttach = NULL;
ULONG cbeid = 0;
LPENTRYID lpeid = NULL;
LPSPropValue lpProps = NULL;
ULONG ulSize = 0;
cRows = GetGWSRowSet(lpParameter)->cRows;
DEBUGPUBLIC("Process()\n");
// Open the Address Book
hrT = MAPICALL(lpSession)->OpenAddressBook(
lpSession,
0,
NULL,
AB_NO_DIALOG,
&lpAdrBook);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
for(i = 0; i < cRows; i++)
{
cValues = GetGWSRowSet(lpParameter)->aRow[i].cValues;
lpProps = GetGWSRowSet(lpParameter)->aRow[i].lpProps;
cbeid = lpProps[0].Value.bin.cb;
lpeid = (LPENTRYID)lpProps[0].Value.bin.lpb;
// Get the message in the MTS-OUT folder
hrT = MAPICALL(lpMtsOutFolder)->OpenEntry(
lpMtsOutFolder,
cbeid,
lpeid,
NULL,
MAPI_MODIFY|MAPI_DEFERRED_ERRORS,
&ulObjType,
(LPUNKNOWN FAR *)&lpEnvelope);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if(ulObjType != MAPI_MESSAGE)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Get the attachment in the envelope
hrT = MAPICALL(lpEnvelope)->OpenAttach(
lpEnvelope,
0,
NULL,
MAPI_MODIFY|MAPI_DEFERRED_ERRORS,
&lpAttach);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Open a message interface on the attachment
hrT = MAPICALL(lpAttach)->OpenProperty(
lpAttach,
PR_ATTACH_DATA_OBJ,
(LPIID)&IID_IMessage,
0,
MAPI_MODIFY|MAPI_DEFERRED_ERRORS,
(LPUNKNOWN *)&lpMessage);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// ---------------------------------------------------------------------
//
// Collect size data to sumbit to performance monitor after message
// has been successfully sent.
//
hr = HrMAPIGetPropLong(
(LPMAPIPROP)lpMessage,
PR_MESSAGE_SIZE,
&ulSize);
if(hr == MAPI_E_NOT_FOUND)
{
ulSize = 0;
}
else if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// Modify the subject.
//
hr = HrCreateReplySubject(
lpEnvelope);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hr = HrCreateReplySubject(
lpMessage);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// Address the message to the originator.
//
hr = HrCreateReplyRecipients(
MSG_ENVELOPE,
lpEnvelope);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hr = HrCreateReplyRecipients(
MSG_CONTENT,
lpMessage);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// Delete the message after it has been submitted.
//
hr = HrSetDeleteAfterSubmit(
lpEnvelope);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
hr = HrSetDeleteAfterSubmit(
lpMessage);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// ---------------------------------------------------------------------
//
// Save changes to the message.
//
hrT = MAPICALL(lpMessage)->SaveChanges(lpMessage, KEEP_OPEN_READWRITE);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// Save changes to attachment object.
//
hrT = MAPICALL(lpAttach)->SaveChanges(lpAttach, KEEP_OPEN_READWRITE);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// Save changes to the envelope.
//
hrT = MAPICALL(lpEnvelope)->SaveChanges(lpEnvelope, KEEP_OPEN_READWRITE);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// ---------------------------------------------------------------------
//
// Submit message
//
hrT = MAPICALL(lpEnvelope)->SubmitMessage(lpEnvelope, FORCE_SUBMIT);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// ---------------------------------------------------------------------
//
// Submit size data to performance monitor
//
if(fMonitorRunning)
{
// Report the message as transferred out.
hrT = HrMonCollectMessageXferStats(
1,
ulSize,
DIRECTIONTYPE_OUT);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Now report the same message as transferred in, since this
// "gateway" just bounces the message back to the sender.
hrT = HrMonCollectMessageXferStats(
1,
ulSize,
DIRECTIONTYPE_IN);
if(FAILED(hrT))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
}
ULRELEASE(lpMessage);
ULRELEASE(lpAttach);
ULRELEASE(lpEnvelope);
// ---------------------------------------------------------------------
}
cleanup:
ULRELEASE(lpAttach);
ULRELEASE(lpMessage);
ULRELEASE(lpEnvelope);
ULRELEASE(lpAdrBook);
return(0);
}
//$--GWMain----------------------------------------------------------------
// Start threads.
// -----------------------------------------------------------------------------
void GWMain(
void)
{
HRESULT hr = NOERROR;
EDK_SERVICE_CONTROL_T sc = 0;
ULONG icd = 0;
DEBUGPUBLIC("GWMain()\n");
hr = HrServiceGetName(
szServiceName);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
//
// Start performance monitoring
//
// Replace any placeholders in rgcdCounters with a pointer
// to the actual MAPI folder.
for (icd = 0; icd < ARRAY_CNT(rgcdCounters); icd++)
{
if (rgcdCounters[icd].lpFolder == PLACEHOLDER_MTS_OUT)
{
rgcdCounters[icd].lpFolder = lpMtsOutFolder;
}
}
// Initialize event logging.
hr = HrMonInit(
0,
NULL,
szServiceName,
OBJECT_EDK_PERFTEST,
PERF_DETAIL_NOVICE,
COUNTER_MESSAGES_OUT,
ARRAY_CNT(rgcdCounters),
rgcdCounters);
if(FAILED(hr))
{
fMonitorRunning = FALSE;
}
else
{
fMonitorRunning = TRUE;
}
hr = HrGWStartNewMailHandler(
1000,
(ULONG)-1,
1,
1,
EXCHANGE_ADDRTYPE,// Currently "EX"
getenv("TEMP"),
(LPTHREAD_START_ROUTINE)Process);
if(FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
cleanup:
if(FAILED(hr))
{
ServiceStop();
}
//
// Wait for a request for the service to stop.
//
hr = HR_LOG(HrServiceWaitForStop(INFINITE, &sc));
return;
}
//$--HrGWLogon-------------------------------------------------------------
// Logon to the gateway.
// -----------------------------------------------------------------------------
HRESULT HrGWLogon(void)
{
HRESULT hr = NOERROR;
DEBUGPUBLIC("HrGWLogon()\n");
lpSession = GetGWSession();
lpStore = GetGWDefaultStore();
lpRootFolder = GetGWRootFolder();
lpMtsInFolder = GetGWMtsInFolder();
lpMtsOutFolder = GetGWMtsOutFolder();
cbGalEid = GetGWGALEntryIdSize();
lpGalEid = GetGWGALEntryId();
RETURN(hr);
}
//$--HrGWLogoff------------------------------------------------------------
// Logoff of the gateway.
// -----------------------------------------------------------------------------
HRESULT HrGWLogoff(void)
{
HRESULT hr = NOERROR;
DEBUGPUBLIC("HrGWLogoff()\n");
if(fMonitorRunning == TRUE)
{
hr = HrMonUninit();
fMonitorRunning = FALSE;
}
RETURN(hr);
}