📄 q.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//=--------------------------------------------------------------------------=
// MSMQQueueObj.Cpp
//=--------------------------------------------------------------------------=
//
// the MSMQQueue object
//
//
#include "IPServer.H"
#include "LocalObj.H"
#include "dispids.h"
#include "oautil.h"
#include "q.H"
#include "msg.h"
#include "qinfo.h"
// #include "txdtc.h" // transaction support.
// #include "xact.h"
extern UINT OrdinalOfPropId(MQMSGPROPS *pmsgprops, MSGPROPID propid);
// extern HRESULT GetCurrentViperTransaction(ITransaction **pptransaction);
// for ASSERT and FAIL
//
SZTHISFILE
// debug...
#define new DEBUG_NEW
#if DEBUG
#define SysAllocString DebSysAllocString
#define SysReAllocString DebSysReAllocString
#define SysFreeString DebSysFreeString
#endif // DEBUG
// Used to coordinate user-thread queue ops and
// queue lookup in falcon-thread callback
//
extern CRITICAL_SECTION g_csCallback;
// Global list of MSMQQueue instances
// Used to map queue handle to queue object
//
QueueNode *CMSMQQueue::m_pqnodeFirst = NULL;
// Global list of callback params
CallbackNode *CMSMQQueue::m_pcallbacknodeFirst = NULL;
// defined in MSMQMessage
extern PROPREC g_rgmsgproprec[];
extern ULONG g_cPropRec;
#if 0
extern PROPREC g_rgproprecAsyncReceive[];
extern ULONG g_cPropRecAsyncReceive;
#endif // 0
/* helper: provided by msg.cpp
extern HRESULT GetOptionalTransaction(
VARIANT *pvarTransaction,
ITransaction **pptransaction,
BOOL *pisRealXact);
*/
//=--------------------------------------------------------------------------=
// HELPER::InitMessageProps
//=--------------------------------------------------------------------------=
// Inits MQMSGPROPS struct.
//
// Parameters:
//
// Output:
//
// Notes:
//
void InitMessageProps(MQMSGPROPS *pmsgprops)
{
pmsgprops->aPropID = NULL;
pmsgprops->aPropVar = NULL;
pmsgprops->aStatus = NULL;
}
//=--------------------------------------------------------------------------=
// CMSMQQueue::AddQueue, RemQueue, PqOfHandle
//=--------------------------------------------------------------------------=
// Static instance list manipulation methods
//
// Parameters:
// pq [in] queue to be added to list
//
// Output:
//
// Notes:
// pq is not addref'ed.
// We critsect queue closure/removal and the callback.
//
HRESULT CMSMQQueue::AddQueue(CMSMQQueue *pq)
{
QueueNode *pqnode;
HRESULT hresult = NOERROR;
pqnode = new QueueNode;
if (pqnode == NULL) {
hresult = E_OUTOFMEMORY;
}
else {
EnterCriticalSection(&g_csCallback); // synchs falcon callback queue lookup
// cons
pqnode->m_pq = pq;
pqnode->m_pqnodeNext = m_pqnodeFirst;
m_pqnodeFirst = pqnode;
LeaveCriticalSection(&g_csCallback); // synchs falcon callback queue lookup
}
return hresult;
}
HRESULT CMSMQQueue::RemQueue(CMSMQQueue *pq)
{
EnterCriticalSection(&g_csCallback); // synchs falcon callback queue lookup
QueueNode *pqnodeCur = m_pqnodeFirst;
QueueNode *pqnodePrev = NULL;
HRESULT hresult = NOERROR;
while (pqnodeCur) {
if (pqnodeCur->m_pq == pq) {
// remove
if (pqnodePrev) {
pqnodePrev->m_pqnodeNext = pqnodeCur->m_pqnodeNext;
}
else {
m_pqnodeFirst = pqnodeCur->m_pqnodeNext;
}
delete pqnodeCur;
break;
}
pqnodePrev = pqnodeCur;
pqnodeCur = pqnodeCur->m_pqnodeNext;
} // while
LeaveCriticalSection(&g_csCallback); // synchs falcon callback queue lookup
return hresult;
}
CMSMQQueue *CMSMQQueue::PqOfHandle(QUEUEHANDLE lHandle)
{
QueueNode *pqnodeCur = m_pqnodeFirst;
CMSMQQueue *pq = NULL;
while (pqnodeCur) {
if (pqnodeCur->m_pq->m_lHandle == lHandle) {
pq = pqnodeCur->m_pq;
break;
}
pqnodeCur = pqnodeCur->m_pqnodeNext;
} // while
return pq;
}
// helpers
// helper: free body buffer
void FreeBodyBuffer(
MQMSGPROPS* pmsgprops,
UINT iBody)
{
HGLOBAL hMem = NULL;
CAUB *pcau = &pmsgprops->aPropVar[iBody].caub;
if (pcau->pElems) {
hMem = GlobalHandle(pcau->pElems);
ASSERT(hMem, L"bad handle.");
GLOBALFREE(hMem);
pcau->pElems = NULL;
}
}
// helper: (re)allocate body buffer
HGLOBAL AllocateBodyBuffer(
MQMSGPROPS* pmsgprops,
UINT iBody,
DWORD dwBodySize)
{
HGLOBAL hMem = NULL;
CAUB *pcau;
//
// free current body if any
//
FreeBodyBuffer(pmsgprops, iBody);
//
// Allocating buffer
//
pmsgprops->aPropVar[iBody].caub.cElems = dwBodySize;
pcau = &pmsgprops->aPropVar[iBody].caub;
IfNullGo(hMem = GLOBALALLOC_MOVEABLE_NONDISCARD(pcau->cElems));
pcau->pElems = (UCHAR *)GlobalLock(hMem);
GLOBALUNLOCK(hMem);
// fall through...
Error:
return hMem;
}
//
// HELPER: get optional timeout param
// defaults to INFINITE
//
HRESULT GetOptionalReceiveTimeout(
VARIANT *pvarReceiveTimeout,
long *plReceiveTimeout)
{
long lReceiveTimeout = INFINITE;
HRESULT hresult = NOERROR;
if (pvarReceiveTimeout) {
if (V_VT(pvarReceiveTimeout) != VT_ERROR) {
IfFailRet(VariantChangeType(pvarReceiveTimeout,
pvarReceiveTimeout,
0,
VT_I4));
lReceiveTimeout = V_I4(pvarReceiveTimeout);
}
}
*plReceiveTimeout = lReceiveTimeout;
return hresult;
}
// forwards decls...
void APIENTRY ReceiveCallback(
HRESULT hrStatus,
QUEUEHANDLE hReceiveQueue,
DWORD dwTimeout,
DWORD dwAction,
MQMSGPROPS* pmsgprops,
LPOVERLAPPED lpOverlapped,
HANDLE hCursor);
void APIENTRY ReceiveCallbackCurrent(
HRESULT hrStatus,
QUEUEHANDLE hReceiveQueue,
DWORD dwTimeout,
DWORD dwAction,
MQMSGPROPS* pmsgprops,
LPOVERLAPPED lpOverlapped,
HANDLE hCursor);
void APIENTRY ReceiveCallbackNext(
HRESULT hrStatus,
QUEUEHANDLE hReceiveQueue,
DWORD dwTimeout,
DWORD dwAction,
MQMSGPROPS* pmsgprops,
LPOVERLAPPED lpOverlapped,
HANDLE hCursor);
//=--------------------------------------------------------------------------=
// CMSMQQueue::Create
//=--------------------------------------------------------------------------=
// creates a new MSMQQueue object.
//
// Parameters:
// IUnknown * - [in] controlling unkonwn
//
// Output:
// IUnknown * - new object.
//
// Notes:
//
IUnknown *CMSMQQueue::Create
(
IUnknown *pUnkOuter
)
{
// make sure we return the private unknown so that we support aggegation
// correctly!
//
CMSMQQueue *pNew = new CMSMQQueue(pUnkOuter);
return pNew ? pNew->PrivateUnknown() : NULL;
}
//=--------------------------------------------------------------------------=
// CMSMQQueue::CMSMQQueue
//=--------------------------------------------------------------------------=
// create the object and initialize the refcount
//
// Parameters:
// IUnknown * - [in] controlling unknown
//
// Notes:
//
#pragma warning(disable:4355) // using 'this' in constructor
CMSMQQueue::CMSMQQueue
(
IUnknown *pUnkOuter
)
: CAutomationObject(pUnkOuter, OBJECT_TYPE_OBJMQQUEUE, (void *)this)
{
// TODO: initialize anything here
m_lAccess = 0;
m_lShareMode = MQ_DENY_NONE;
m_pqinfo = NULL;
m_lHandle = INVALID_HANDLE_VALUE;
m_hCursor = 0;
m_pqevent = NULL;
m_hasActiveEventHandler = FALSE;
}
#pragma warning(default:4355) // using 'this' in constructor
//=--------------------------------------------------------------------------=
// CMSMQQueue::CMSMQQueue
//=--------------------------------------------------------------------------=
// "We all labour against our own cure, for death is the cure of all diseases"
// - Sir Thomas Browne (1605 - 82)
//
// Notes:
//
CMSMQQueue::~CMSMQQueue ()
{
// TODO: clean up anything here.
HRESULT hresult;
// remove from global instance list
RemQueue(this);
RELEASE(m_pqinfo);
RELEASE(m_pqevent);
hresult = Close();
ASSERT(SUCCEEDED(hresult), L"whoops! can't handle errors here.");
}
//=--------------------------------------------------------------------------=
// CMSMQQueue::InternalQueryInterface
//=--------------------------------------------------------------------------=
// the controlling unknown will call this for us in the case where they're
// looking for a specific interface.
//
// Parameters:
// REFIID - [in] interface they want
// void ** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CMSMQQueue::InternalQueryInterface
(
REFIID riid,
void **ppvObjOut
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -