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.
353 lines
7.4 KiB
353 lines
7.4 KiB
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
vststmsgclient.cxx
|
|
|
|
Abstract:
|
|
|
|
Implementation of test message classes for the client and holder of
|
|
shared methods and variables shared between client and server.
|
|
|
|
|
|
Brian Berkowitz [brianb] 05/22/2000
|
|
|
|
TBD:
|
|
|
|
Revision History:
|
|
|
|
Name Date Comments
|
|
brianb 05/22/2000 Created
|
|
ssteiner 06/07/2000 Split client and server portions into
|
|
two files. vststmsg.cxx contains
|
|
the server portion.
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
#include "vststmsgclient.hxx"
|
|
|
|
void LogUnexpectedFailure(LPCWSTR wsz, ...);
|
|
|
|
VSTST_MSG_TYPE_TABLE g_msgTypes[VSTST_MT_MAXMSGTYPE];
|
|
|
|
void AddMessageType
|
|
(
|
|
VSTST_MSG_TYPE type,
|
|
UINT cbFixed,
|
|
UINT cVarPtr,
|
|
VSTST_MSG_PRIORITY priority,
|
|
VSTST_MSG_HANDLER pfnHandler,
|
|
VSTST_VARPTR_TYPE ptype1 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype2 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype3 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype4 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype5 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype6 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype7 = VSTST_VPT_UNDEFINED,
|
|
VSTST_VARPTR_TYPE ptype8 = VSTST_VPT_UNDEFINED
|
|
)
|
|
{
|
|
VSTST_MSG_TYPE_TABLE *pEntry = &g_msgTypes[type];
|
|
pEntry->cbFixed = cbFixed;
|
|
pEntry->cVarPtr = cVarPtr;
|
|
pEntry->priority = priority;
|
|
pEntry->pfnHandler = pfnHandler;
|
|
pEntry->pointerTypes[0] = (BYTE) ptype1;
|
|
pEntry->pointerTypes[1] = (BYTE) ptype2;
|
|
pEntry->pointerTypes[2] = (BYTE) ptype3;
|
|
pEntry->pointerTypes[3] = (BYTE) ptype4;
|
|
pEntry->pointerTypes[4] = (BYTE) ptype5;
|
|
pEntry->pointerTypes[5] = (BYTE) ptype6;
|
|
pEntry->pointerTypes[6] = (BYTE) ptype7;
|
|
pEntry->pointerTypes[7] = (BYTE) ptype8;
|
|
};
|
|
|
|
|
|
void InitMsgTypes()
|
|
{
|
|
AddMessageType
|
|
(
|
|
VSTST_MT_TEXT,
|
|
FIELD_OFFSET(VSTST_TEXTMSG, pch),
|
|
1,
|
|
VSTST_MP_QUEUED,
|
|
NULL, // Not needed by client, server will fill in
|
|
VSTST_VPT_ANSI
|
|
);
|
|
|
|
AddMessageType
|
|
(
|
|
VSTST_MT_IMMEDIATETEXT,
|
|
FIELD_OFFSET(VSTST_TEXTMSG, pch),
|
|
1,
|
|
VSTST_MP_IMMEDIATE,
|
|
NULL,
|
|
VSTST_VPT_ANSI
|
|
);
|
|
|
|
AddMessageType
|
|
(
|
|
VSTST_MT_FAILURE,
|
|
FIELD_OFFSET(VSTST_FAILUREMSG, szFailure),
|
|
1,
|
|
VSTST_MP_QUEUED,
|
|
NULL,
|
|
VSTST_VPT_ANSI
|
|
);
|
|
|
|
AddMessageType
|
|
(
|
|
VSTST_MT_OPERATIONFAILURE,
|
|
FIELD_OFFSET(VSTST_OPERATIONFAILUREMSG, szFailedOperation),
|
|
1,
|
|
VSTST_MP_QUEUED,
|
|
NULL,
|
|
VSTST_VPT_ANSI
|
|
);
|
|
|
|
AddMessageType
|
|
(
|
|
VSTST_MT_UNEXPECTEDEXCEPTION,
|
|
FIELD_OFFSET(VSTST_UNEXPECTEDEXCEPTIONMSG, szFailedRoutine),
|
|
1,
|
|
VSTST_MP_QUEUED,
|
|
NULL,
|
|
VSTST_VPT_ANSI
|
|
);
|
|
|
|
AddMessageType
|
|
(
|
|
VSTST_MT_SUCCESS,
|
|
FIELD_OFFSET(VSTST_SUCCESSMSG, szMsg),
|
|
1,
|
|
VSTST_MP_QUEUED,
|
|
NULL,
|
|
VSTST_VPT_ANSI
|
|
);
|
|
|
|
}
|
|
|
|
|
|
CVsTstClientMsg::CVsTstClientMsg() :
|
|
m_bcsInitialized(false),
|
|
m_rgbMsg(NULL),
|
|
m_hPipe(INVALID_HANDLE_VALUE),
|
|
m_bSkipWrites(false),
|
|
m_seqQueued(0),
|
|
m_seqImmediate(0)
|
|
{
|
|
}
|
|
|
|
CVsTstClientMsg::~CVsTstClientMsg()
|
|
{
|
|
delete m_rgbMsg;
|
|
if (m_bcsInitialized)
|
|
m_cs.Term();
|
|
|
|
if (m_hPipe != INVALID_HANDLE_VALUE)
|
|
CloseHandle(m_hPipe);
|
|
}
|
|
|
|
// initialize messaging to test controller
|
|
HRESULT CVsTstClientMsg::Init
|
|
(
|
|
LONGLONG processId,
|
|
UINT cbMaxMsg,
|
|
bool bIgnorePipeCreationFailure
|
|
)
|
|
{
|
|
m_processId = processId;
|
|
try
|
|
{
|
|
m_cs.Init();
|
|
m_bcsInitialized = true;
|
|
}
|
|
catch(...)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
m_hPipe = CreateFile
|
|
(
|
|
s_wszPipeName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
|
|
if (m_hPipe == INVALID_HANDLE_VALUE)
|
|
{
|
|
if (bIgnorePipeCreationFailure)
|
|
m_bSkipWrites = true;
|
|
else
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
else
|
|
{
|
|
m_cbMaxMsgLength = cbMaxMsg;
|
|
m_rgbMsg = new BYTE[cbMaxMsg];
|
|
if (m_rgbMsg == NULL)
|
|
{
|
|
CloseHandle(m_hPipe);
|
|
m_hPipe = INVALID_HANDLE_VALUE;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// send a message to the test controller
|
|
HRESULT CVsTstClientMsg::SendMessage(VSTST_MSG_TYPE type, void *pv)
|
|
{
|
|
m_cs.Lock();
|
|
VSTST_ASSERT(type < VSTST_MT_MAXMSGTYPE);
|
|
VSTST_MSG_TYPE_TABLE *pType = &g_msgTypes[type];
|
|
|
|
VSTST_MSG_HDR *phdr = (VSTST_MSG_HDR *) m_rgbMsg;
|
|
|
|
phdr->processId = m_processId;
|
|
phdr->type = type;
|
|
time(&phdr->time);
|
|
if (pType->priority == VSTST_MP_IMMEDIATE)
|
|
phdr->sequence = ++m_seqImmediate;
|
|
else
|
|
phdr->sequence = ++m_seqQueued;
|
|
|
|
BYTE *pbMsg = phdr->rgb;
|
|
|
|
size_t cbUsed = pType->cbFixed + FIELD_OFFSET(VSTST_MSG_HDR, rgb) +
|
|
pType->cVarPtr * sizeof(PVOID);
|
|
|
|
if (cbUsed >= m_cbMaxMsgLength)
|
|
{
|
|
m_cs.Unlock();
|
|
return HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
}
|
|
|
|
// copy in fixed portion of data structure
|
|
memcpy(pbMsg, pv, pType->cbFixed);
|
|
pbMsg += pType->cbFixed;
|
|
|
|
// reserve room for pointers
|
|
memset(pbMsg, 0, pType->cVarPtr * sizeof(PVOID));
|
|
pbMsg += pType->cVarPtr * sizeof(PVOID);
|
|
|
|
// walk and write out pointer data
|
|
VOID **ppv = (VOID **) ((BYTE *) pv + pType->cbFixed);
|
|
for(UINT iPtr = 0; iPtr < pType->cVarPtr; iPtr++, ppv++)
|
|
{
|
|
VSTST_VARPTR_TYPE type = (VSTST_VARPTR_TYPE) pType->pointerTypes[iPtr];
|
|
BYTE *pb = NULL;
|
|
size_t cb = 0;
|
|
|
|
switch(type)
|
|
{
|
|
default:
|
|
VSTST_ASSERT(FALSE);
|
|
break;
|
|
|
|
case VSTST_VPT_BYTE:
|
|
pb = *(BYTE **) ppv;
|
|
cb = *(UINT *) *pb;
|
|
break;
|
|
|
|
case VSTST_VPT_ANSI:
|
|
pb = *(BYTE **) ppv;
|
|
cb = strlen((char *) pb) + 1;
|
|
break;
|
|
|
|
case VSTST_VPT_UNICODE:
|
|
pb = *(BYTE **) ppv;
|
|
cb = (wcslen((WCHAR *) pb) + 1) * sizeof(WCHAR);
|
|
break;
|
|
}
|
|
|
|
// round up to alignment boundary
|
|
size_t cbAlign = (cb + sizeof(PVOID) - 1) & ~(sizeof(PVOID)-1);
|
|
|
|
// check for buffer overflow
|
|
if (cbAlign + cbUsed >= m_cbMaxMsgLength)
|
|
{
|
|
m_cs.Unlock();
|
|
return HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
}
|
|
|
|
memcpy(pbMsg, pb, cb);
|
|
|
|
// adjust pointer to alignment boundary
|
|
pb += cbAlign;
|
|
|
|
// adjust amount used
|
|
cbUsed += cbAlign;
|
|
}
|
|
|
|
phdr->cbMsg = cbUsed;
|
|
phdr->pmsgNext = NULL;
|
|
|
|
DWORD cbWritten;
|
|
if (!WriteFile(m_hPipe, m_rgbMsg, (UINT) cbUsed, &cbWritten, NULL) || cbUsed != cbWritten)
|
|
{
|
|
m_cs.Unlock();
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
VSTST_ASSERT(cbUsed == cbWritten);
|
|
|
|
m_cs.Unlock();
|
|
return S_OK;
|
|
}
|
|
|
|
void CVsTstClientLogger::LogFailure(LPCSTR szFailure)
|
|
{
|
|
VSTST_ASSERT(m_pClient);
|
|
VSTST_FAILUREMSG msg;
|
|
msg.szFailure = szFailure;
|
|
m_pClient->SendMessage(VSTST_MT_FAILURE, &msg);
|
|
}
|
|
|
|
void CVsTstClientLogger::LogUnexpectedException(LPCSTR szRoutine)
|
|
{
|
|
VSTST_ASSERT(m_pClient);
|
|
VSTST_UNEXPECTEDEXCEPTIONMSG msg;
|
|
msg.szFailedRoutine = szRoutine;
|
|
m_pClient->SendMessage(VSTST_MT_UNEXPECTEDEXCEPTION, &msg);
|
|
}
|
|
|
|
void CVsTstClientLogger::ValidateResult(HRESULT hr, LPCSTR szOperation)
|
|
{
|
|
VSTST_ASSERT(m_pClient);
|
|
if (FAILED(hr))
|
|
{
|
|
VSTST_OPERATIONFAILUREMSG msg;
|
|
msg.hr = hr;
|
|
msg.szFailedOperation = szOperation;
|
|
m_pClient->SendMessage(VSTST_MT_OPERATIONFAILURE, &msg);
|
|
throw hr;
|
|
}
|
|
}
|
|
|
|
void CVsTstClientLogger::LogSuccess(LPCSTR sz)
|
|
{
|
|
VSTST_ASSERT(m_pClient);
|
|
VSTST_SUCCESSMSG msg;
|
|
msg.szMsg = sz;
|
|
m_pClient->SendMessage(VSTST_MT_SUCCESS, &msg);
|
|
}
|
|
|
|
void CVsTstClientLogger::LogMessage(LPCSTR sz)
|
|
{
|
|
VSTST_ASSERT(m_pClient);
|
|
|
|
VSTST_TEXTMSG msg;
|
|
msg.pch = sz;
|
|
m_pClient->SendMessage(VSTST_MT_TEXT, &msg);
|
|
}
|
|
|