📄 srmpmsg.cxx
字号:
//
// 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.
//
/*++
Module Name:
SrmpMsg.cxx
Abstract:
After SAX interpretter is through with an item, calls into
this function to process it.
--*/
#include <msxml2.h>
#include <winsock.h>
#include "SrmpAccept.hxx"
#include "SrmpParse.hxx"
#include "sc.hxx"
#include "MqProps.h"
#include "ph.h"
#include "scqman.hxx"
#include "scqueue.hxx"
#include "fntoken.h"
#include <service.h>
//
// Interface functions.
//
BOOL BreakMsmqStreamId(const WCHAR *szBuffer, LONGLONG *pSeqId);
// Make sure an end node is visited one and only one time, mark it off as visited.
#define PathCheckAndSet(state) CheckAndSet(cMsgProps.dwPathSet, (state))
#define ServiceCheckAndSet(state) CheckAndSet(cMsgProps.dwServiceSet,(state))
#define PropsCheckAndSet(state) CheckAndSet(cMsgProps.dwPropertiesSet,(state))
#define StreamCheckAndSet(state) CheckAndSet(cMsgProps.dwStreamSet,(state))
#define StreamRcptCheckAndSet(state) CheckAndSet(cMsgProps.dwStreamRcptSet,(state))
#define DeliveryRcptCheckAndSet(state) CheckAndSet(cMsgProps.dwDeliveryRcptSet,(state))
#define CommitRcptCheckAndSet(state) CheckAndSet(cMsgProps.dwCommitRcptSet,(state))
#define MsmqRcptCheckAndSet(state) CheckAndSet(cMsgProps.dwMsmqSet,(state))
CSrmpMessageProperties::CSrmpMessageProperties(PSrmpIOCTLPacket pIOCTL) {
pHttpParams = pIOCTL;
SVSUTIL_ASSERT(pHttpParams->contentType == CONTENT_TYPE_XML || pHttpParams->contentType == CONTENT_TYPE_MIME);
absoluteTimeToLive = INFINITE;
absoluteTimeToQueue = INFINITE;
priority = DEFAULT_M_PRIORITY;
acknowledgeType = DEFAULT_M_ACKNOWLEDGE;
EodSeqId = i64NoneMSMQSeqId;
szAdminQueue = szResponseQueue = szDestQueue = szOrderQueue = szStreamIdBuf = szTitle = NULL;
bstrEnvelope = NULL;
fTrace = fLast = fFirst = auditing = delivery = 0;
sentTime = 0;
classValue = 0;
bodyType = applicationTag = 0;
pCorrelationID = 0;
EodStreamId = 0;
EodPrevSeqNo = EodSeqNo = 0;
EodAckStreamId = 0;
EodAckSeqId = EodAckSeqNo = 0;
szFrom = szRelatesTo = 0;
ccRelatesTo = ccFrom = 0;
// Keep track of what vars have been set already during SAX processing.
dwHeaderSet = dwPathSet = dwServiceSet = dwPropertiesSet = dwStreamSet = dwStreamRcptSet =
dwDeliveryRcptSet = dwCommitRcptSet = dwMsmqSet = 0;
memset(&messageId,0,sizeof(messageId));
memset(&connectorType,0,sizeof(connectorType));
memset(&connectorId,0,sizeof(connectorId));
memset(&SourceQmGuid,0,sizeof(SourceQmGuid));
memset(&destQueue,0,sizeof(destQueue));
memset(&adminQueue,0,sizeof(adminQueue));
memset(&responseQueue,0,sizeof(responseQueue));
}
CSrmpMessageProperties::~CSrmpMessageProperties() {
if (szTitle)
g_funcFree(szTitle, g_pvFreeData);
if (szStreamIdBuf)
g_funcFree(szStreamIdBuf,g_pvFreeData);
if (szOrderQueue)
g_funcFree(szOrderQueue,g_pvFreeData);
// if (EodStreamId) Do not free! Points into szStreamIdBuf!
// g_funcFree(EodStreamId,g_pvFreeData);
if (pCorrelationID)
g_funcFree(pCorrelationID,g_pvFreeData);
if (EodAckStreamId)
g_funcFree(EodAckStreamId,g_pvFreeData);
if (szRelatesTo)
g_funcFree(szRelatesTo,g_pvFreeData);
if (szFrom)
g_funcFree(szFrom,g_pvFreeData);
if (bstrEnvelope)
SysFreeString(bstrEnvelope);
if (szDestQueue)
g_funcFree(szDestQueue,g_pvFreeData);
if (szResponseQueue)
g_funcFree(szResponseQueue,g_pvFreeData);
if (szAdminQueue)
g_funcFree(szAdminQueue,g_pvFreeData);
//if (szProviderName)
// g_funcFree(szProviderName,g_pvFreeData);
}
//
// <path>
//
HRESULT CSrmpToMsmq::HandlePath(void) {
if (IsHeaderSet(SRMP_ST_PATH))
return E_FAIL;
SetHeader(SRMP_ST_PATH);
if (! IsSetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_ID) ||
! IsSetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_ACTION)) {
return E_FAIL;
}
// if <to> isn't set, spec says 'ultimate destination is indicated by the last "via" in the "fwd" element'
if (! IsSetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_TO)) {
if (! cMsgProps.fwdViaBuf.pBuffer)
return E_FAIL;
WCHAR *szStart = (WCHAR*) cMsgProps.fwdViaBuf.pBuffer;
int ccChars = cMsgProps.fwdViaBuf.uiNextIn / sizeof(WCHAR);
WCHAR *pszTrav = szStart;
WCHAR *pszLastVisited;
while (pszTrav - szStart <= ccChars) {
pszLastVisited = pszTrav;
pszTrav += wcslen(pszTrav)+1;
}
SVSUTIL_ASSERT(pszTrav-1-szStart == ccChars);
if (! UriToQueueFormat(pszLastVisited,pszLastVisited-pszTrav-1,&cMsgProps.destQueue,&cMsgProps.szDestQueue))
return E_FAIL;
SetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_TO);
}
return S_OK;
}
// Converts <path><id>uuid:XXXXX</id></path>
HRESULT CSrmpToMsmq::HandlePathId(void) {
PathCheckAndSet(SRMP_ST_PATH_ID);
WCHAR *szBuf = GetBuffer();
if (IsEmpty())
return E_FAIL;
DWORD nscan;
int n = swscanf(szBuf,UUIDREFERENCE_PREFIX L"%d" UUIDREFERENCE_SEPERATOR L"%n",
&cMsgProps.messageId.Uniquifier,&nscan);
if (n == 1) {
if (! StringToGuid(szBuf + nscan,&cMsgProps.messageId.Lineage))
return E_FAIL;
return S_OK;
}
const GUID xNonMSMQMessageIdGuid = {0x75d1aae4,0x8e23,0x400a,0x8c,0x33,0x99,0x64,0x8e,0x35,0xe7,0xb9};
const ULONG xNonMSMQMessageIdIndex = 1;
cMsgProps.messageId.Uniquifier = xNonMSMQMessageIdIndex;
cMsgProps.messageId.Lineage = xNonMSMQMessageIdGuid;
return S_OK;
}
HRESULT CSrmpToMsmq::HandlePathTo(void) {
PathCheckAndSet(SRMP_ST_PATH_TO);
if (IsEmpty())
return E_FAIL;
return UriToQueueFormat(GetBuffer(),GetNumChars(),&cMsgProps.destQueue,&cMsgProps.szDestQueue) ? S_OK : E_FAIL;
}
HRESULT CSrmpToMsmq::HandlePathRev(void) {
PathCheckAndSet(SRMP_ST_PATH_REV);
return S_OK;
}
const WCHAR szEmpty[] = L"";
HRESULT CSrmpToMsmq::HandlePathRevVia(void) {
// It is acceptable to have multiple VIA entries
SetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_REV_VIA);
const WCHAR *szVia = GetBuffer();
DWORD ccVia = GetNumChars();
// 1st element in <rev><via> list has special meaning in desktop MSMQ, preserve this while at same time store in revViaBuf.
if (! IsEmpty() && (NULL == cMsgProps.revViaBuf.pBuffer)) {
if (!UriToQueueFormat(GetBuffer(),GetNumChars(),&cMsgProps.responseQueue,&cMsgProps.szResponseQueue))
return E_FAIL;
}
// +1 makes sure \0 is included.
return cMsgProps.revViaBuf.AppendWSTR(szVia,ccVia+1) ? S_OK : E_FAIL;
}
HRESULT CSrmpToMsmq::HandlePathFrom(void) {
PathCheckAndSet(SRMP_ST_PATH_FROM);
if (IsEmpty())
return E_FAIL;
if (NULL == (cMsgProps.szFrom = AllocCharData()))
return E_FAIL;
cMsgProps.ccFrom = GetNumChars() + 1;
return S_OK;
}
HRESULT CSrmpToMsmq::HandlePathAction(void) {
PathCheckAndSet(SRMP_ST_PATH_ACTION);
// Like XP: We require action to begin with "MSMQ:", if it doesn't we
// won't save it but we won't halt parsing, either.
if (GetNumChars() <= ccMSMQPrefix)
return S_OK;
if (wcsncmp(GetBuffer(),cszMSMQPrefix,ccMSMQPrefix) != 0)
return S_OK;
if (NULL == (cMsgProps.szTitle = AllocCharData(ccMSMQPrefix)))
return E_FAIL;
return S_OK;
}
HRESULT CSrmpToMsmq::HandlePathRelatesTo(void) {
PathCheckAndSet(SRMP_ST_PATH_RELATESTO);
if (IsEmpty())
return E_FAIL;
if (NULL == (cMsgProps.szRelatesTo = AllocCharData()))
return E_FAIL;
cMsgProps.ccRelatesTo = GetNumChars() + 1;
return S_OK;
}
HRESULT CSrmpToMsmq::HandlePathFixed(void) {
PathCheckAndSet(SRMP_ST_PATH_FIXED);
return S_OK;
}
HRESULT CSrmpToMsmq::HandlePathFwd(void) {
PathCheckAndSet(SRMP_ST_PATH_FWD);
return S_OK;
}
// need to have a URL and a FORMAT version of this...
//int IsURLLocalMachine(const WCHAR *szURL, BOOL fGeneratedLocally) {
// if (0 == wcsicmp(gMachine->lpszHostName,szURL))
// return TRUE;
//
// if (fGeneratedLocally && (0==wcsicmp(gMachine->lpszHostName,L"localhost")))
// return TRUE;
//
// return FALSE;
//}
HRESULT CSrmpToMsmq::HandlePathFwdVia(void) {
// It is acceptable to have multiple VIA entries
// BOOL fFirst = ! (IsSetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_FWD_VIA));
const WCHAR *szVia = GetBuffer();
DWORD ccVia = GetNumChars();
SetSrmp(cMsgProps.dwPathSet,SRMP_ST_PATH_FWD_VIA);
/* if (fFirst) {
// check that 1st element is local device or is empty.
// if (!IsEmpty() && !IsURLLocalMachine(szVia))
// return E_FAIL;
// first <via> element is discarded, return immediatly.
return S_OK;
}
*/
// +1 to make sure NULL is included.
return cMsgProps.fwdViaBuf.AppendWSTR(szVia,ccVia+1) ? S_OK : E_FAIL;
}
HRESULT CSrmpToMsmq::HandlePathFault(void) {
PathCheckAndSet(SRMP_ST_PATH_FAULT);
return S_OK;
}
//
// <services>
//
HRESULT CSrmpToMsmq::HandleServices(void) {
if (IsHeaderSet(SRMP_ST_SERVICES))
return E_FAIL;
SetHeader(SRMP_ST_SERVICES);
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesDurable(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_DURABLE);
cMsgProps.delivery = MQMSG_DELIVERY_RECOVERABLE;
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesFilterDups(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_FILTERDUPLICATES);
return S_OK;
}
//
// <services><commitmentReceiptRequest>
//
HRESULT CSrmpToMsmq::HandleServicesCommitRcpt(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_COMMITMENTRECEIPTREQUEST);
if (! IsSetSrmp(cMsgProps.dwServiceSet,SRMP_ST_SERVICES_COMMITMENTRECEIPTREQUEST_SENDTO))
return E_FAIL;
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesCommitRcptPositevOnly(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_COMMITMENTRECEIPTREQUEST_POSITIVEONLY);
cMsgProps.acknowledgeType |= MQMSG_ACKNOWLEDGMENT_POS_RECEIVE;
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesCommitRcptNegativeOnly(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_COMMITMENTRECEIPTREQUEST_NEGATIVEONLY);
cMsgProps.acknowledgeType |= MQMSG_ACKNOWLEDGMENT_NEG_RECEIVE;
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesCommitRcptSendBy(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_COMMITMENTRECEIPTREQUEST_SENDBY);
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesCommitRcptSendTo(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_COMMITMENTRECEIPTREQUEST_SENDTO);
if (!UriToQueueFormat(GetBuffer(),GetNumChars(),&cMsgProps.adminQueue,&cMsgProps.szAdminQueue))
return E_FAIL;
return S_OK;
}
//
// <services><deliveryReceiptRequest>
//
HRESULT CSrmpToMsmq::HandleServicesDelRcptRequest(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_DELIVERYRECEIPTREQUEST);
if (! IsSetSrmp(cMsgProps.dwServiceSet,SRMP_ST_SERVICES_DELIVERYRECEIPTREQUEST_SENDTO))
return E_FAIL;
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesDelRcptRequestSendTo(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_DELIVERYRECEIPTREQUEST_SENDTO);
cMsgProps.acknowledgeType |= MQMSG_ACKNOWLEDGMENT_POS_ARRIVAL;
if (!UriToQueueFormat(GetBuffer(),GetNumChars(),&cMsgProps.adminQueue,&cMsgProps.szAdminQueue))
return E_FAIL;
return S_OK;
}
HRESULT CSrmpToMsmq::HandleServicesDelRcptRequestSendBy(void) {
ServiceCheckAndSet(SRMP_ST_SERVICES_DELIVERYRECEIPTREQUEST_SENDBY);
return S_OK;
}
//
// <Properties>
//
HRESULT CSrmpToMsmq::HandleProps(void) {
if (IsHeaderSet(SRMP_ST_PROPERTIES))
return E_FAIL;
SetHeader(SRMP_ST_PROPERTIES);
// Note: XP MSMQ router does not check for expiresAt, but latest version of spec requires it.
if (! IsSetSrmp(cMsgProps.dwPropertiesSet,SRMP_ST_PROPERTIES_EXPIRESAT))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -