⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srmpsend.cxx

📁 Windows CE 6.0 Server 源码
💻 CXX
📖 第 1 页 / 共 3 页
字号:

	// Initially allocate a large buffer to hopefully eliminate need for reallocs in most cases.
	if (pUserHeader->SoapIsIncluded())
		cbAlloc += pSoapBodySection->GetDataLengthInWCHARs();

	if (!xmlEncode.AllocMem(cbAlloc))
		return NULL;

	xmlEncode.Append((CHAR*)cszXMLHeader,SVSUTIL_CONSTSTRLEN(cszXMLHeader)*sizeof(WCHAR));
	xmlEncode.Append((CHAR*)cszEnvelopeStartNS,SVSUTIL_CONSTSTRLEN(cszEnvelopeStartNS)*sizeof(WCHAR));
	xmlEncode.StartTag(cszHeaderNS);

	// <HEADER> section
	if (! SendPath(&xmlEncode,pImage))
		return NULL;

	if (! SendProps(&xmlEncode,pImage))
		return NULL;

	if (! SendServices(&xmlEncode,pImage))
		return NULL;

	if (! SendStream(&xmlEncode,pImage))
		return NULL;

	if (! SendStreamRcpt(&xmlEncode,pImage))
		return NULL;

	if (! SendDeliveryRcpt(&xmlEncode,pImage))
		return NULL;

	if (! SendCommitRcpt(&xmlEncode,pImage))
		return NULL;

	if (! SendMsmq(&xmlEncode,pImage))
		return NULL;

	if (! SendUserHeader(&xmlEncode,pImage))
		return NULL;

	if (! xmlEncode.EndTag(cszHeaderNS))
		return NULL;

	// <BODY> section
	if (! xmlEncode.StartTag(cszBodyNS))
		return NULL;

	if (pUserHeader->SoapIsIncluded()) {
		if (pSoapBodySection->GetPointerToData()) {
			if (!xmlEncode.Encode(pSoapBodySection->GetPointerToData()))
				return NULL;
		}
	}
	if (! xmlEncode.EndTag(cszBodyNS))
		return NULL;

	if (! xmlEncode.EndTag(cszEnvelopeNS))
		return NULL;

	if (! xmlEncode.Append((char*)L"\0",sizeof(WCHAR)))
		return NULL;

#if defined (DEBUG) || defined (_DEBUG)
	svsutil_validateXML((BSTR)xmlEncode.pBuffer);
#endif

	// covert SOAP Envelope to UTF8
	DWORD cp = CP_UTF8;

	if (0 == (*pccSendBuffer = WideCharToMultiByte(cp, 0, (WCHAR*)xmlEncode.pBuffer, -1, NULL, 0, 0, 0))) {
		cp = CP_ACP;
		if (0 == (*pccSendBuffer = WideCharToMultiByte(cp, 0, (WCHAR*)xmlEncode.pBuffer, -1, NULL, 0, 0, 0)))
			return NULL;
	}

	if (NULL == (szSendBuffer = (CHAR*) g_funcAlloc(*pccSendBuffer,g_pvAllocData)))
		return NULL;

	WideCharToMultiByte(cp, 0, (WCHAR*)xmlEncode.pBuffer, -1, szSendBuffer, *pccSendBuffer, 0, 0);
	*pccSendBuffer -= 1;
	return szSendBuffer;
}


BOOL IsBodyIncluded(ScPacketImage *pImage) {
	CUserHeader            *pUserHeader             = pImage->sect.pUserHeader;
	CCompoundMessageHeader *pCompoundMessageHeader  = pImage->sect.pCompoundMessageHeader;
	CPropertyHeader        *pPropHeader             = pImage->sect.pPropHeader;

	if (pUserHeader->SrmpIsIncluded())
		return (pCompoundMessageHeader && pCompoundMessageHeader->GetBodySizeInBytes() != 0);
	return (pPropHeader->GetBodySize() != 0);
}


#define BOUNDARY_VALUE "MSMQ - SOAP boundary, %d"
const char cszApplicationContentType[]  = "application/octet-stream";
const char cszMultipartContentType[]    = "multipart/related";
#define MIME_ID_FMT_A		"%.*s" GUID_FORMAT_A

// MIME_ID_FMT_A

int BuildHttpHeadersAndMimeBody(ScPacketImage *pImage, CHAR *szSoapEnv, DWORD ccSoapEnv, BOOL fSecure, PSrmpIOCTLPacket pIOPacket, DWORD ccHeaders, SVSSimpleBuffer &cBodyBuf) {
	CUserHeader     *pUserHeader = pImage->sect.pUserHeader;
	CPropertyHeader *pPropHeader = pImage->sect.pPropHeader;
	const UCHAR* szBody = NULL;
	DWORD        cbBody = 0;
	const UCHAR* szExtension = NULL;
	DWORD        cbExtension = 0;
	PSTR         szLastWritten;

	pIOPacket->fSSL = fSecure;
	SVSUTIL_ASSERT(pIOPacket->pszHeaders); // write buffer passed into us by caller

	if (IsBodyIncluded(pImage)) {
		CCompoundMessageHeader *pCompoundMessageHeader  = pImage->sect.pCompoundMessageHeader;
		szBody = pUserHeader->SrmpIsIncluded() ? pCompoundMessageHeader->GetPointerToBody()   : pPropHeader->GetBodyPtr();
		cbBody = pUserHeader->SrmpIsIncluded() ? pCompoundMessageHeader->GetBodySizeInBytes() : pPropHeader->GetBodySize();
	}

	if (pPropHeader->GetMsgExtensionSize()) {
		szExtension = pPropHeader->GetMsgExtensionPtr();
		cbExtension = pPropHeader->GetMsgExtensionSize();
	}

	if (szBody || szExtension) {  // complex data type
		srand (GetTickCount());

		DWORD  dwBoundaryId = rand();
		DWORD  cbAlloc = ccSoapEnv + cbBody + cbExtension + 2048;

		// Get all we need at once so there's no chance of needing to realloc.
		// For this reason we also don't check return values from StringCch functions.
		if (! cBodyBuf.AllocMem(cbAlloc))
			return FALSE;

		// MIME Body
		StringCchPrintfExA((CHAR*)cBodyBuf.pBuffer,cBodyBuf.BufferRemaining(),&szLastWritten,NULL,0,
		                      BOUNDARY_HYPHEN BOUNDARY_VALUE "\r\n"
		                      "Content-Type: %s; charset=UTF-8\r\nContent-Length: %d\r\n\r\n",
		                      dwBoundaryId,cszTextXML,ccSoapEnv);

		cBodyBuf.uiNextIn = (UCHAR*)szLastWritten - cBodyBuf.pBuffer;
		cBodyBuf.Append(szSoapEnv,ccSoapEnv);

		if (szBody) {
			StringCchPrintfExA((CHAR*)cBodyBuf.pBuffer + cBodyBuf.uiNextIn,
			                    cBodyBuf.BufferRemaining(),&szLastWritten,NULL,0,
			                    BOUNDARY_HYPHEN BOUNDARY_VALUE "\r\n"
  			                    "Content-Type: %s\r\n"
			                    "Content-Length: %d\r\n"
			                    "Content-Id: " MIME_ID_FMT_A "\r\n\r\n",
			                    dwBoundaryId,cszApplicationContentType,
			                    cbBody,
			                    ccMimeBodyIdLen, cszMimeBodyId,
			                    GUID_ELEMENTS((&gMachine->guid)));

			cBodyBuf.uiNextIn = (UCHAR*)szLastWritten - cBodyBuf.pBuffer;
			memcpy(cBodyBuf.pBuffer+cBodyBuf.uiNextIn,szBody,cbBody);
			cBodyBuf.uiNextIn += cbBody;
		}

		if (szExtension) {
			StringCchPrintfExA((CHAR*)cBodyBuf.pBuffer + cBodyBuf.uiNextIn,
			                   cBodyBuf.BufferRemaining(),&szLastWritten,NULL,0,
			                   BOUNDARY_HYPHEN BOUNDARY_VALUE "\r\n"
  			                   "Content-Type: %s\r\n"
			                   "Content-Length: %d\r\n"
			                   "Content-Id: " MIME_ID_FMT_A "\r\n\r\n",
			                   dwBoundaryId,cszApplicationContentType,
			                   cbExtension,
			                   ccMimeExtensionIdLen,cszMimeExtensionId,
			                   GUID_ELEMENTS((&gMachine->guid)));

			cBodyBuf.uiNextIn = (UCHAR*)szLastWritten - cBodyBuf.pBuffer;
			memcpy(cBodyBuf.pBuffer+cBodyBuf.uiNextIn,szExtension,cbExtension);
			cBodyBuf.uiNextIn += cbExtension;
		}

		StringCchPrintfExA((CHAR*)cBodyBuf.pBuffer + cBodyBuf.uiNextIn,
                           cBodyBuf.BufferRemaining(),&szLastWritten,NULL,0,
		                   BOUNDARY_HYPHEN BOUNDARY_VALUE BOUNDARY_HYPHEN "\r\n",dwBoundaryId);

		cBodyBuf.uiNextIn = (UCHAR*)szLastWritten - cBodyBuf.pBuffer;

		// HTTP headers
		StringCchPrintfExA(pIOPacket->pszHeaders,ccHeaders,&szLastWritten,NULL,0,
		                    "Content-Type: %s; boundary=\"" BOUNDARY_VALUE "\"; type=text/xml\r\n"
		                    "SOAPAction: \"MSMQMessage\"\r\n"
		                    "Proxy-Accept: NonInteractiveClient\r\n",
		                    cszMultipartContentType,dwBoundaryId
		                    );

		pIOPacket->cbHeaders   = szLastWritten - pIOPacket->pszHeaders;
		pIOPacket->pszPost     = (CHAR*)cBodyBuf.pBuffer;
		pIOPacket->cbPost      = cBodyBuf.uiNextIn;
		pIOPacket->contentType = CONTENT_TYPE_MIME;
	}
	else { // simple type
		StringCchPrintfExA(pIOPacket->pszHeaders,ccHeaders,&szLastWritten,NULL,0,
		                   "Content-Type: %s\r\n"
		                   "SOAPAction: \"MSMQMessage\"\r\n" 
		                   "Proxy-Accept: NonInteractiveClient\r\n",
		                   cszTextXML
		                   );

		pIOPacket->cbHeaders   = szLastWritten - pIOPacket->pszHeaders;
		pIOPacket->pszPost     = szSoapEnv;
		pIOPacket->cbPost      = ccSoapEnv;
		pIOPacket->contentType = CONTENT_TYPE_XML;
	}
	return TRUE;
}

int ScSession::SendHttpMsg(CHAR *szURL, BOOL fSecure, PSrmpIOCTLPacket pIOPacket) {
	HANDLE hRequest;
	DWORD  dwFlags    = 0;
	int    iStatusCode=500;

	CSrmpCallBack openCallback;

	dwFlags  =  (g_fUseWininet ? INTERNET_FLAG_KEEP_CONNECTION : 0);
	dwFlags  |= (fSecure       ? INTERNET_FLAG_SECURE          : 0);

	gMem->Lock();
	if (glServiceState != SERVICE_STATE_ON) {
		openCallback.Failed();
		gMem->Unlock();
		return 503;
	}
	hRequest = HttpOpenRequestA(hInternetConnect,"POST",szURL,NULL,NULL,NULL,dwFlags,(DWORD)&openCallback);

	if (!hRequest) {
		openCallback.Failed();
		scerror_DebugOutM(VERBOSE_MASK_SRMP,(L"HttpOpenRequest fails, GLE=0x%08x\r\n",GetLastError()));
	}
	gMem->Unlock();

	if (hRequest) {
		DWORD cbStatus = sizeof(iStatusCode);
		
		if (!HttpSendRequestA(hRequest,pIOPacket->pszHeaders,pIOPacket->cbHeaders,pIOPacket->pszPost,pIOPacket->cbPost))
			openCallback.Wait(30000);

		if (openCallback.dwError == 0)  {
			if (!HttpQueryInfo(hRequest,HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &iStatusCode,&cbStatus,NULL))
				iStatusCode = 500;
		}
#if defined (SC_VERBOSE)
		else 
			scerror_DebugOut(VERBOSE_MASK_SRMP,L"HttpSendRequest fails, openCallback.dwResult=%d, GLE=0x%08x\r\n",openCallback.dwResult,openCallback.dwError);
#endif
		gMem->Lock();
		InternetCloseHandle(hRequest);
		hRequest = 0;
		gMem->Unlock();
	}

	return iStatusCode;
}


void CALLBACK SrmpCallback(HINTERNET hInternet,DWORD_PTR dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation,DWORD dwStatusInformationLength) {
	CSrmpCallBack* pThis = (CSrmpCallBack*)(dwContext);

	switch(dwInternetStatus) {
		case INTERNET_STATUS_REQUEST_COMPLETE: 	{
			INTERNET_ASYNC_RESULT* pAsyncResult = reinterpret_cast<INTERNET_ASYNC_RESULT*>(lpvStatusInformation);

			pThis->dwError  = pAsyncResult->dwError;
			pThis->dwResult = pAsyncResult->dwResult;
			SetEvent(pThis->hEventComplete);
		}
		break;

		case INTERNET_STATUS_HANDLE_CLOSING:
			SetEvent(pThis->hEventClosed);
		break;
	}
}

BOOL IsDirectHttpFormatName(const QUEUE_FORMAT* pQueueFormat) {
	DIRECT_TOKEN_TYPE ddt;

	if (pQueueFormat->GetType() == QUEUE_FORMAT_TYPE_DIRECT && 
	    ParseDirectTokenString(pQueueFormat->DirectID(),ddt)) {
		return (ddt == DT_HTTP || ddt == DT_HTTPS);
	}

	return FALSE;
}



BOOL QueueFormatToUri(SVSXMLEncode *pXmlEncode, QUEUE_FORMAT *pqf) {
	WCHAR szBuf[MAX_PATH];
	WCHAR *pszTrav = szBuf;
	WCHAR *szURI   = NULL;
	WCHAR *szFormatName = NULL;
	BOOL  fRet = FALSE;

	switch (pqf->GetType()) {
		case QUEUE_FORMAT_TYPE_DIRECT : {
			DWORD ccFormatName = SCUTIL_DIRECT_PREFIX_SZ + wcslen(pqf->DirectID()) + 1;
			if (ccFormatName > SVSUTIL_CONSTSTRLEN(szBuf)) {
				if (NULL == (szFormatName = (WCHAR*) g_funcAlloc(sizeof(WCHAR)*ccFormatName,g_pvAllocData)))
					goto done;
			}
			else
				szFormatName = szBuf;

			wcscpy(szFormatName,SCUTIL_DIRECT_PREFIX);
			wcscpy(szFormatName+SCUTIL_DIRECT_PREFIX_SZ,pqf->DirectID());
		}
		break;

		case QUEUE_FORMAT_TYPE_PUBLIC : {
			wcscpy(szBuf,MSMQ_SC_FORMAT_PUBLIC);
			const GUID *pGuid = &pqf->PublicID();
			wsprintf (szBuf+wcslen(MSMQ_SC_FORMAT_PUBLIC),GUID_FORMAT,GUID_ELEMENTS(pGuid));
			szFormatName = szBuf;
		}
		break;

		case QUEUE_FORMAT_TYPE_PRIVATE: {
			wcscpy(szBuf,MSMQ_SC_FORMAT_PRIVATE);
			pszTrav += wcslen(MSMQ_SC_FORMAT_PRIVATE);

			const OBJECTID *pObj = &pqf->PrivateID();
			const GUID *pGuid = &pObj->Lineage;
			pszTrav += wsprintf (pszTrav,GUID_FORMAT FN_PRIVATE_SEPERATOR,GUID_ELEMENTS(pGuid));

			wsprintf(pszTrav,L"%x",pObj->Uniquifier);
			szFormatName = szBuf;
		}
		break;

		default:
			SVSUTIL_ASSERT(0);
	}

	gMem->Lock();
	if (gMachine->RouteLocalReverseLookup(szFormatName,&szURI)) {
		// if we've hit a reverse in lookup table then we originally received
		// message as a free-form URI.  Send it out like this too.
		gMem->Unlock();
		fRet = pXmlEncode->Encode(szURI);
		goto done;
	}
	gMem->Unlock();

	// send direct HTTP without modifications.
	if (IsDirectHttpFormatName(pqf)) 
		fRet = pXmlEncode->Encode(pqf->DirectID());
	// append MSMQ: in front of remaining types.
	else if (pXmlEncode->Encode(cszMSMQPrefix,ccMSMQPrefix))
		fRet = pXmlEncode->Encode(szBuf);
done:
	SVSUTIL_ASSERT(! gMem->IsLocked());

	if (szFormatName != szBuf)
		g_funcFree(szFormatName,g_pvFreeData);
	
	return fRet;
}


BOOL CreateViaList(SVSXMLEncode *pXmlEncode, CDataHeader *pViaHeader, BOOL fSkipFirstElement) {
	int   iLen      = pViaHeader->GetDataLengthInWCHARs();
	WCHAR *szStart  = (WCHAR*) pViaHeader->GetData();
	WCHAR *pszTrav;

	if (fSkipFirstElement) {
		// skip past 1st entry, which is current machine (not forwarded along) in some cases.
		int ccFirstElement = wcslen(szStart) + 1;
		szStart += ccFirstElement;
		iLen    -= ccFirstElement;

		SVSUTIL_ASSERT(iLen > 0); // if there's only one element in fwd list, this function shouldn't have been called.
	}
	pszTrav  = szStart;

	// VIA list is stored as a NULL separated multi-string.  Elements
	// may be set to \0 to indicate an empty tag.
	while (pszTrav - szStart < iLen) {
		if (*pszTrav) {
			if (! pXmlEncode->SetElement(cszVia,pszTrav))
				return FALSE;
		}
		else if (! pXmlEncode->SetEmptyElement(cszVia))
			return FALSE;

		pszTrav += wcslen(pszTrav)+1;
	}
	SVSUTIL_ASSERT(pszTrav-szStart == iLen);
	return TRUE;
}


DWORD GetExpiresFromPacketImage(ScPacketImage *pImage) {
	DWORD dwDelta;
	DWORD dwTimeout;
	CBaseHeader     *pBaseHeader = pImage->sect.pBaseHeader;
	CUserHeader     *pUserHeader = pImage->sect.pUserHeader;

	dwDelta = pUserHeader->GetTimeToLiveDelta();
	if (dwDelta == INFINITE)
		dwTimeout = INFINITE;
	else
		dwTimeout = dwDelta + pBaseHeader->GetAbsoluteTimeToQueue();

	return min(dwTimeout, LONG_MAX);
}

//
// <Path> Section.
//
BOOL SendPath(SVSXMLEncode *pXmlEncode, ScPacketImage *pImage) {
	CPropertyHeader *pPropHeader = pImage->sect.pPropHeader;
	CUserHeader     *pUserHeader = pImage->sect.pUserHeader;
	QUEUE_FORMAT    qf;
	OBJECTID MessageId;

	if (! pXmlEncode->Append((CHAR*)cszPathNS,SVSUTIL_CONSTSTRLEN(cszPathNS)*sizeof(WCHAR)) ||
	    ! pXmlEncode->Append((CHAR*)cszMustUnderstandNS,SVSUTIL_CONSTSTRLEN(cszMustUnderstandNS)*sizeof(WCHAR)))
		return FALSE;

	// <action>
	if (! pXmlEncode->StartTag(cszAction))
		return FALSE;

	// even if there's no title we put <action>MSMQ:</action>, required since <action> is a required field.  Like XP.
	if (! pXmlEncode->Encode(cszMSMQPrefix))
		return FALSE;

	if (pPropHeader->GetTitleLength()) {
		if (! pXmlEncode->Encode(pPropHeader->GetTitlePtr()))
			return FALSE;
	}

	if (! pXmlEncode->EndTag(cszAction))
		return FALSE;

	//<to>
	pUserHeader->GetDestinationQueue(&qf);
	if (! pXmlEncode->StartTag(cszTo))
		return FALSE;

	if (!QueueFormatToUri(pXmlEncode,&qf))
		return FALSE;

	if (! pXmlEncode->EndTag(cszTo))
		return FALSE;

	// <id>
	pUserHeader->GetMessageID(&MessageId);
	if (! SetMsgID(pXmlEncode,&MessageId))
		return FALSE;


	if (pImage->flags.fSoapExtIncluded) {
		CSoapExtSection *pSoapExt = pImage->sect.pSoapExtHeaderSection;

		if (pSoapExt->GetFromLengthInWCHARs()) {
			if (! pXmlEncode->SetElement(cszFrom,pSoapExt->GetFrom(),pSoapExt->GetFromLengthInWCHARs()))
				return FALSE;
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -