📄 srmpfwd.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:
SrmpFwd.cxx
Abstract:
Forwards an SRMP data packet without modifying contents.
--*/
#include <windows.h>
#include <wininet.h>
#include <mq.h>
#include "sc.hxx"
#include "scsrmp.hxx"
#include "scsman.hxx"
#include "scpacket.hxx"
#include "SrmpAccept.hxx"
#include "scdefs.hxx"
#include "srmpparse.hxx"
#include "fntoken.h"
#include "scutil.hxx"
#include "scqueue.hxx"
#include "SrmpFwd.hxx"
BOOL CSrmpFwd::SetState(SRMP_TOKEN tok) {
SRMP_STATE curState = GetState();
SRMP_STATE newState = SRMP_ST_UNKNOWN;
// we only care about a very small subset, no namespace checking needed if it made it this far.
if (curState == SRMP_ST_UNINITIALIZED && tok == SRMP_TOK_ENVELOPE)
newState = SRMP_ST_ENVELOPE;
else if (curState == SRMP_ST_ENVELOPE && tok == SRMP_TOK_HEADER)
newState = SRMP_ST_HEADER;
else if (curState == SRMP_ST_HEADER && tok == SRMP_TOK_PATH)
newState = SRMP_ST_PATH;
else if (curState == SRMP_ST_PATH && tok == SRMP_TOK_FWD)
newState = SRMP_ST_PATH_FWD;
else if (curState == SRMP_ST_PATH_FWD && tok == SRMP_TOK_VIA)
newState = SRMP_ST_PATH_FWD_VIA;
else if (curState == SRMP_ST_PATH && tok == SRMP_TOK_REV)
newState = SRMP_ST_PATH_REV;
else if (curState == SRMP_ST_PATH_REV && tok == SRMP_TOK_VIA)
newState = SRMP_ST_PATH_REV_VIA;
if (! m_State.Push((void*)newState))
return FALSE;
return TRUE;
}
HRESULT STDMETHODCALLTYPE CSrmpFwd::endElement(
/* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ const wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ const wchar_t __RPC_FAR *pwchQName,
/* [in] */ int cchQName)
{
SRMP_STATE oldState = GetState();
HRESULT hr = E_FAIL;
m_State.Pop();
if (fSkipOutput) {
fSkipOutput = FALSE;
return S_OK;
}
// <rev> is present but is empty (i.e. <rev/>), then add <via>
if (oldState == SRMP_ST_PATH_REV && !fFoundRevVia) {
fFoundRevVia = TRUE;
if (S_OK != characters(0,0) ||
FAILED(hr = WriteRevEntry(TRUE)))
return hr;
}
/* If we ever break this code into public or have some other mechanism of injecting
// extra XML tags into a forwarded envelope, now would be the time to do it.
if (oldState == SRMP_ST_ENVELOPE) {
// We're about to close </envelope>. User may append whatever extra XML tags
// they desire now.
}
*/
return writeBuffer.endElement(pwchNamespaceUri,cchNamespaceUri,pwchLocalName,cchLocalName,pwchQName,cchQName);
}
void GetHttpPrefix(BOOL fSecure, WCHAR **ppszPrefix, DWORD *pccPrefix) {
if (fSecure) {
*ppszPrefix = (WCHAR*) cszHttpsPrefix;
*pccPrefix = ccHttpsPrefix;
}
else {
*ppszPrefix = (WCHAR*) cszHttpPrefix;
*pccPrefix = ccHttpPrefix;
}
}
HRESULT STDMETHODCALLTYPE CSrmpFwd::characters(
/* [in] */ const wchar_t __RPC_FAR *pwchChars,
/* [in] */ int cchChars)
{
if (! fSkipOutput)
return writeBuffer.characters(pwchChars,cchChars);
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSrmpFwd::startElement(
/* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ const wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ const wchar_t __RPC_FAR *pwchQName,
/* [in] */ int cchQName,
/* [in] */ ISAXAttributes __RPC_FAR *pAttributes)
{
SVSUTIL_ASSERT(!fSkipOutput);
SRMP_TOKEN token = GetToken(pwchLocalName,cchLocalName);
HRESULT hr;
if (! SetState(token))
return E_OUTOFMEMORY;
SRMP_STATE curState = GetState();
switch (curState) {
case SRMP_ST_PATH_FWD_VIA:
if (fwdViaState == SRMP_FWD_ONFIRST) {
// swallow first <fwd><via> element (points to this CE server), allow all others to pass through.
fwdViaState = SRMP_FWD_ONSECOND;
fSkipOutput = TRUE;
return S_OK;
}
else if (fwdViaState == SRMP_FWD_ONSECOND) {
fwdViaState = SRMP_FWD_PASTSECOND;
// the second <fwd><via> entry was used to setup the queue that we're sending to currently (will be first in this forwarded packet).
// Use szQueueName rather than the original entry in case the original entry has been routed to a new destination.
gMem->Lock();
WCHAR *szHttpPref;
DWORD ccHttpPref;
GetHttpPrefix(pSession->IsSecure(),&szHttpPref,&ccHttpPref);
// 1st call is to characters() due to way MXXMLWriter works; needs to possibly fixup element immediatly preceeding this one in buffer.
if (S_OK != characters(0,0) ||
! writeBuffer.StartTag(cszVia) ||
! writeBuffer.AppendWSTR(szHttpPref,ccHttpPref) ||
! writeBuffer.AppendWSTR(pSession->lpszHostName,wcslen(pSession->lpszHostName)) ||
! writeBuffer.AppendWSTR(L"/",1) ||
! writeBuffer.AppendWSTR(szQueueName,wcslen(szQueueName)) ||
! writeBuffer.EndTag(cszVia)) {
gMem->Unlock();
return E_OUTOFMEMORY;
}
fSkipOutput = TRUE;
gMem->Unlock();
return S_OK;
}
break;
case SRMP_ST_PATH_REV_VIA:
// put name of CE box as 1st via entry
if (!fFoundRevVia) {
fFoundRevVia = TRUE;
if ((FAILED(hr = writeBuffer.startElement(pwchNamespaceUri,cchNamespaceUri,pwchLocalName,cchLocalName,pwchQName,cchQName,pAttributes))))
return hr;
if (S_OK != characters(0,0))
return E_OUTOFMEMORY;
if (FAILED(hr = WriteRevEntry(FALSE)))
return hr;
if (FAILED(hr = writeBuffer.endElement(pwchNamespaceUri,cchNamespaceUri,pwchLocalName,cchLocalName,pwchQName,cchQName)))
return hr;
// "fall through" - add <rev><via> entry SAX has come across just like normal.
}
// fall through
default:
fSkipOutput = FALSE;
}
return writeBuffer.startElement(pwchNamespaceUri,cchNamespaceUri,pwchLocalName,cchLocalName,pwchQName,cchQName,pAttributes);
}
HRESULT CSrmpFwd::WriteRevEntry(BOOL fWriteRevTag) {
if (fWriteRevTag) {
if (! writeBuffer.StartTag(cszVia))
return E_OUTOFMEMORY;
}
if (! writeBuffer.Encode(szRevEntry))
return E_OUTOFMEMORY;
if (fWriteRevTag) {
if ( ! writeBuffer.EndTag(cszVia))
return E_OUTOFMEMORY;
}
return S_OK;
}
const char cszHostHttpHeader[] = "Host:";
const char cszTextXML[] = "text/xml";
BOOL SkipHeader(PSTR szHeader) {
if (0 == _strnicmp(szHeader,cszHostHttpHeader,SVSUTIL_CONSTSTRLEN(cszHostHttpHeader)) ||
0 == _strnicmp(szHeader,cszContentLength, ccContentLength))
return TRUE;
return FALSE;
}
int ScSession::ForwardSrmpMessage(CSrmpFwd *pSrmpFwd, ScPacketImage *pPacketImage, WCHAR *wszURL) {
CUserHeader *pUserHeader = pPacketImage->sect.pUserHeader;
CCompoundMessageHeader *pCompoundMessageHeader = pPacketImage->sect.pCompoundMessageHeader;
CPropertyHeader *pPropHeader = pPacketImage->sect.pPropHeader;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -