PERFTEST.C

// --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);
}