2025-04-27 07:49:33 -04:00

618 lines
18 KiB
C++

/*++
Copyright (C) 1997-2001 Microsoft Corporation
Module Name:
PIPEOPN.CPP
Abstract:
Declares the abstract and generic (to proxy and stub) pipe operation classes
History:
alanbos 18-Dec-97 Created.
--*/
#include "precomp.h"
#include "wmishared.h"
// Used as a placeholder in the encode stream
static PACKET_HEADER gDummyPacketHeader (0,0,0);
// IOperation_LPipe
bool IOperation_LPipe::DecodeCallHeader (CTransportStream& decodeStream,
OUT DWORD& dwStubAddr, OUT DWORD& dwStubType,
OUT DWORD& dwStubFunc)
{
// Decode the stub address, type and method call id
DWORD dwInSt = CTransportStream::no_error;
dwInSt |= decodeStream.ReadDWORD (&dwStubAddr);
dwInSt |= decodeStream.ReadDWORD (&dwStubType);
dwInSt |= decodeStream.ReadDWORD (&dwStubFunc);
return (CTransportStream::no_error == dwInSt);
}
// IBasicOperation_LPipe
void IBasicOperation_LPipe::EncodePacketHeader (CTransportStream& encodeStream,
DWORD msgType)
{
#if 0
// TODO - this is gross as we have to copy the current contents twice!
// What we need is either (1) WriteBytes should not reset the end of stream,
// or (2) introduce a Prepend operation.
// Copy the current encoded stream contents - this is the data minus the
// header
CTransportStream dataStream (encodeStream);
// Determine the data length and set in the header
PACKET_HEADER ph (msgType, dataStream.Size () - PHSIZE, GetRequestId ());
// Serialize the header into the stream - note this will squelch the original
// data hence the copy above.
encodeStream.Reset ();
encodeStream.WriteBytes (&ph, PHSIZE);
// Add the original data contents again
encodeStream.Append (&dataStream);
#else
PACKET_HEADER ph (msgType, encodeStream.Size () - PHSIZE, GetRequestId ());
DWORD curPos = encodeStream.GetCurrentPos ();
encodeStream.Reset ();
encodeStream.WriteBytes (&ph, PHSIZE);
encodeStream.SetCurrentPos (curPos);
#endif
}
bool IBasicOperation_LPipe::DecodeHeader (BYTE *pByte, DWORD numBytes, PACKET_HEADER& header)
{
if (PHSIZE != numBytes)
return FALSE;
memcpy ((void *) &header, pByte, PHSIZE);
return TRUE;
}
void IBasicOperation_LPipe::DecodeResult (CTransportStream& decodeStream)
{
DWORD dwCallRet = WBEM_E_FAILED; // Just in case
decodeStream.ReadDWORD(&dwCallRet);
SetStatus (dwCallRet);
}
bool IBasicOperation_LPipe::EncodeRequest
(CTransportStream& encodeStream, ISecurityHelper& secHelp)
{
#if 0
#else
// Put a dummy header in for now.
encodeStream.WriteBytes ((LPVOID) &gDummyPacketHeader, PHSIZE);
#endif
// Encode the per-operation data
EncodeOperationReq (encodeStream);
// Encode header now because we finally know the data length
EncodePacketHeader (encodeStream, GetMessageType ());
return true;
}
bool IBasicOperation_LPipe::DecodeRequest
(CTransportStream& encodeStream, ISecurityHelper& secHelp)
{
// Note: the packet header has already been removed
DecodeOperationReq (encodeStream);
return true;
}
bool IBasicOperation_LPipe::EncodeResponse
(CTransportStream& encodeStream, ISecurityHelper& secHelp)
{
#if 0
#else
// Put a dummy header in for now
encodeStream.WriteBytes ((LPVOID) &gDummyPacketHeader, PHSIZE);
#endif
// Encode the per-operation data
EncodeOperationRsp (encodeStream);
// Encode header now because we finally know the data length
EncodePacketHeader (encodeStream, GetResponseType ());
return true;
}
bool IBasicOperation_LPipe::DecodeResponse
(CTransportStream& encodeStream, ISecurityHelper& secHelp)
{
// Note: the packet header has already been removed
DecodeOperationRsp (encodeStream);
return true;
}
// Given a PH and decodeStream, create an IOperation of the right type
bool IBasicOperation_LPipe::Decode (PACKET_HEADER& header, CTransportStream& decodeStream,
IOperation** ppOpn)
{
*ppOpn = NULL;
/*
* We only deal with incoming call request messages. If this isn't one
* we can go no further.
*/
if (COMLINK_MSG_CALL != header.GetType ())
return false;
/*
* Decode the call message header
*/
DWORD dwStubAddr = 0;
DWORD dwStubType = 0;
DWORD dwStubFunc = 0;
/*
* If we cannot decode the call header, discard the message.
*/
if (!IOperation_LPipe::DecodeCallHeader (decodeStream, dwStubAddr,
dwStubType, dwStubFunc))
return false;
bool isAsync = false;
CStubAddress_WinMgmt stubAddr (dwStubAddr);
switch (dwStubType)
{
case OBJECTSINK:
switch (dwStubFunc)
{
case RELEASE:
*ppOpn = new CStubOperation_LPipe_Release (stubAddr, dwStubType);
break;
case INDICATE:
*ppOpn = new CStubOperation_LPipe_Indicate (stubAddr);
break;
case SETSTATUS:
*ppOpn = new CStubOperation_LPipe_SetStatus (stubAddr);
break;
}
break;
// The remaining messages would only be handled by the server stub
#ifdef MARSHALER_STUB
case PROVIDER:
switch (dwStubFunc)
{
case RELEASE:
*ppOpn = new CStubOperation_LPipe_Release (stubAddr, dwStubType);
break;
case WBEM_METHOD_CancelAsyncCall:
*ppOpn = new CStubOperation_LPipe_CancelAsyncCall (stubAddr);
break;
case WBEM_METHOD_CreateClassEnumAsync:
case WBEM_METHOD_CreateInstanceEnumAsync:
isAsync = true;
case WBEM_METHOD_CreateClassEnum:
case WBEM_METHOD_CreateInstanceEnum:
*ppOpn = new CStubOperation_LPipe_CreateEnum (stubAddr, dwStubFunc, isAsync);
break;
case WBEM_METHOD_DeleteClassAsync:
case WBEM_METHOD_DeleteInstanceAsync:
isAsync = true;
case WBEM_METHOD_DeleteClass:
case WBEM_METHOD_DeleteInstance:
*ppOpn = new CStubOperation_LPipe_Delete (stubAddr, dwStubFunc, isAsync);
break;
case WBEM_METHOD_ExecMethodAsync:
isAsync = true;
case WBEM_METHOD_ExecMethod:
*ppOpn = new CStubOperation_LPipe_ExecMethod (stubAddr, dwStubFunc, isAsync);
break;
case WBEM_METHOD_ExecNotificationQueryAsync:
case WBEM_METHOD_ExecQueryAsync:
isAsync = true;
case WBEM_METHOD_ExecNotificationQuery:
case WBEM_METHOD_ExecQuery:
*ppOpn = new CStubOperation_LPipe_ExecQuery (stubAddr, dwStubFunc, isAsync);
break;
case WBEM_METHOD_GetObjectAsync:
isAsync = true;
case WBEM_METHOD_GetObject:
*ppOpn = new CStubOperation_LPipe_GetObject (stubAddr, dwStubFunc, isAsync);
break;
case WBEM_METHOD_OpenNamespace:
*ppOpn = new CStubOperation_LPipe_OpenNamespace (stubAddr);
break;
case WBEM_METHOD_PutClassAsync:
case WBEM_METHOD_PutInstanceAsync:
isAsync = true;
case WBEM_METHOD_PutClass:
case WBEM_METHOD_PutInstance:
*ppOpn = new CStubOperation_LPipe_Put (stubAddr, dwStubFunc, isAsync);
break;
case WBEM_METHOD_QueryObjectSink:
*ppOpn = new CStubOperation_LPipe_QueryObjectSink (stubAddr);
break;
}
break;
case CALLRESULT:
switch (dwStubFunc)
{
case RELEASE:
*ppOpn = new CStubOperation_LPipe_Release (stubAddr, dwStubType);
break;
case GETRESULTOBJECT:
case GETRESULTSTRING:
case GETCALLSTATUS:
case GETSERVICES:
*ppOpn = new CStubOperation_LPipe_CallResult (stubAddr, dwStubFunc);
break;
}
break;
case ENUMERATOR:
switch (dwStubFunc)
{
case RELEASE:
*ppOpn = new CStubOperation_LPipe_Release (stubAddr, dwStubType);
break;
case NEXT:
*ppOpn = new CStubOperation_LPipe_Next (stubAddr);
break;
case RESET:
*ppOpn = new CStubOperation_LPipe_Reset (stubAddr);
break;
case CLONE:
*ppOpn = new CStubOperation_LPipe_Clone (stubAddr);
break;
case SKIP:
*ppOpn = new CStubOperation_LPipe_Skip (stubAddr);
break;
case NEXTASYNC:
*ppOpn = new CStubOperation_LPipe_NextAsync (stubAddr);
break;
}
break;
case LOGIN:
switch (dwStubFunc)
{
case RELEASE:
*ppOpn = new CStubOperation_LPipe_Release (stubAddr, dwStubType);
break;
case REQUESTCHALLENGE:
*ppOpn = new CStubOperation_LPipe_RequestChallenge (stubAddr);
break;
case ESTABLISHPOSITION:
*ppOpn = new CStubOperation_LPipe_EstablishPosition (stubAddr);
break;
case SSPIPRELOGIN:
*ppOpn = new CStubOperation_LPipe_SspiPreLogin (stubAddr);
break;
case LOGINBYTOKEN:
*ppOpn = new CStubOperation_LPipe_Login (stubAddr);
break;
case WBEMLOGIN:
*ppOpn = new CStubOperation_LPipe_WBEMLogin (stubAddr);
break;
}
break;
#endif
}
if (!(*ppOpn))
{
// We could not recognize the message type or function. In this
// case we make a NotSupported message to send back.
*ppOpn = new COperation_LPipe_NotSupported ();
}
// Set the correct request id into operation. It is taken from the
// incoming header so as to ensure the response id matches the request.
(*ppOpn)->SetRequestId (header.GetRequestId ());
DEBUGTRACE((LOG,"\nDecode Request [Func = %d, RequestId = %d]", dwStubFunc, (*ppOpn)->GetRequestId ()));
return true;
}
// IProxyOperation_LPipe
void IProxyOperation_LPipe::DecodeStubAddress (ObjType ot, CTransportStream& decodeStream,
bool checkValid)
{
CStubAddress_WinMgmt stubAddr;
stubAddr.Deserialize (decodeStream);
if ((checkValid && !stubAddr.IsValid ()) ||
(decodeStream.Status () != CTransportStream::no_error))
SetStatus (WBEM_E_INVALID_STREAM);
else
SetProxyAddress (ot, stubAddr);
}
void IProxyOperation_LPipe::EncodeContext (CTransportStream& encodeStream)
{
bool setContext = FALSE;
IWbemContext *pContext = GetContext ();
if (pContext)
{
IStream *pStr = NULL; // This is released when the write stream is deleted
IUnknown *pUnk = NULL; // This is released below
if ((SUCCEEDED (encodeStream.QueryInterface (IID_IStream, (void **) &pStr)))
&& (SUCCEEDED (pContext->QueryInterface (IID_IUnknown, (void **) &pUnk))))
{
setContext = TRUE;
encodeStream.WriteDWORD (1);
CoMarshalInterface (pStr, IID_IWbemContext, pUnk, MSHCTX_LOCAL, NULL,
MSHLFLAGS_NORMAL);
pUnk->Release ();
}
}
if (!setContext)
encodeStream.WriteDWORD (0);
}
void IProxyOperation_LPipe::EncodeCallHeader (CTransportStream& encodeStream)
{
// Encode the stub address, type and method call id
encodeStream.WriteDWORD (m_stubAddr);
encodeStream.WriteDWORD (m_stubType);
encodeStream.WriteDWORD (m_stubFunc);
}
void IProxyOperation_LPipe::DecodeErrorObject (CTransportStream& decodeStream)
{
if(decodeStream.NextType() != VT_UI4)
{
// Got an error object to deserialize
IErrorInfo* pInfo = NULL;
IStream* pStr = NULL;
HRESULT t_Result ;
if ((S_OK == ( t_Result = decodeStream.QueryInterface(IID_IStream, (void**)&pStr))) )
{
if ((S_OK == ( t_Result = CoUnmarshalInterface(pStr, IID_IErrorInfo, (void**)&pInfo))) && pInfo)
{
SetErrorInfoIntoObject (pInfo);
pInfo->Release ();
}
}
}
}
// IStubOperation_LPipe
void IStubOperation_LPipe::EncodeStubAddress (ObjType ot, CTransportStream& encodeStream)
{
CStubAddress_WinMgmt *pStubAddr = (CStubAddress_WinMgmt *) GetProxyAddress (ot);
if (pStubAddr && pStubAddr->IsValid ())
pStubAddr->Serialize (encodeStream);
else
encodeStream.WriteDWORD (0);
}
void IStubOperation_LPipe::EncodeErrorObject (CTransportStream& encodeStream)
{
IErrorInfo* pInfo = GetErrorInfoFromObject ();
if (pInfo)
{
IStream * pStr = NULL;
HRESULT t_Result ;
if(S_OK == ( t_Result = encodeStream.QueryInterface(IID_IStream, (void**)&pStr)))
{
t_Result = CoMarshalInterface(pStr, IID_IWbemClassObject, pInfo,
MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
}
pInfo->Release ();
}
}
void IStubOperation_LPipe::DecodeContext (CTransportStream& decodeStream)
{
DWORD gotContext;
if (CTransportStream::no_error != decodeStream.ReadDWORD (&gotContext))
SetStatus (WBEM_E_INVALID_STREAM);
else if (1 == gotContext)
{
IStream *pStr = NULL; // This is released when the read stream is deleted
IWbemContext* pContext = NULL;
if ((SUCCEEDED (decodeStream.QueryInterface (IID_IStream, (void **) &pStr)))
&& pStr
&& (SUCCEEDED (CoUnmarshalInterface (pStr, IID_IWbemContext,
(void **) &pContext))))
{
SetContext (pContext);
pContext->Release ();
}
else
SetStatus (WBEM_E_INVALID_STREAM);
}
}
void IStubOperation_LPipe::HandleCall (CComLink& comLink)
{
DEBUGTRACE((LOG,"\nHandle Call [Func = %d, RequestId = %d]", m_stubFunc, GetRequestId ()));
// Always protect our stub; if the following call succeeds then we will have AddRef'd
// the stub we are about to use in this operation.
IUnknown *pStub = comLink.GetStub (m_stubAddr, m_stubType);
if (!pStub)
SetStatus (WBEM_E_FAILED);
if (WBEM_NO_ERROR == GetStatus ())
{
Execute (comLink, pStub);
SetErrorInfoIntoObject ();
}
// Now release the stub as this operation is done with it.
if ( pStub )
pStub->Release ();
else
{
ERRORTRACE((LOG,"\nHANDLE CALL FAILED[Func = %d, RequestId = %d]", m_stubFunc, GetRequestId ()));
}
}
// CProxyOperation_LPipe_Indicate
void CProxyOperation_LPipe_Indicate::EncodeOp (CTransportStream& encodeStream)
{
encodeStream.WriteLong(m_objectCount);
for(long lCnt = 0; lCnt < m_objectCount; lCnt++)
((CWbemObject *)m_pObjArray[lCnt])->WriteToStream(&encodeStream);
}
// CProxyOperation_LPipe::SetStatus
void CProxyOperation_LPipe_SetStatus::EncodeOp (CTransportStream& encodeStream)
{
encodeStream.WriteLong(m_flags);
encodeStream.WriteLong(m_param);
encodeStream.WriteBSTR(m_strParam);
if (m_pObjParam)
{
encodeStream.WriteLong (1);
((CWbemObject *)m_pObjParam)->WriteToStream(&encodeStream);
}
else
encodeStream.WriteLong (0);
}
// CStubOperation_LPipe_Indicate
void CStubOperation_LPipe_Indicate::DecodeOp (CTransportStream& decodeStream)
{
if ((CTransportStream::no_error == decodeStream.ReadLong (&m_objectCount))
&& (0 < m_objectCount))
{
m_pObjArray = (IWbemClassObject **) (new CWbemObject * [m_objectCount]);
if (!m_pObjArray)
SetStatus (WBEM_E_OUT_OF_MEMORY);
else
{
long lCnt;
for (lCnt = 0; lCnt < m_objectCount; lCnt++)
{
m_pObjArray [lCnt] = CreateClassObject (&decodeStream);
if (!bVerifyPointer (m_pObjArray [lCnt]))
break;
m_pObjArray [lCnt]->Release (); // Reduce ref count back to 1
}
if (lCnt < m_objectCount)
{
// We terminated prematurely
SetStatus (WBEM_E_FAILED);
long lDelTo = lCnt;
for (lCnt = 0; lCnt < lDelTo; lCnt++)
delete m_pObjArray [lCnt];
}
}
}
}
void CStubOperation_LPipe_Indicate::Execute (CComLink& comLink, IUnknown *pStub)
{
IWbemObjectSink* pObj = (IWbemObjectSink *) pStub;
DEBUGTRACE((LOG,"\nCalling Indicate into stub = %X", pObj));
SetStatus (pObj->Indicate (m_objectCount, m_pObjArray));
// Drop the reference count
for (long lCnt = 0; lCnt < m_objectCount; lCnt++)
m_pObjArray [lCnt]->Release ();
}
// CStubOperation_LPipe::SetStatus
void CStubOperation_LPipe_SetStatus::DecodeOp (CTransportStream& decodeStream)
{
DWORD dwInSt = CTransportStream::no_error;
long lGotObj= 0;
dwInSt |= decodeStream.ReadLong (&m_flags);
dwInSt |= decodeStream.ReadLong (&m_param);
dwInSt |= decodeStream.ReadBSTR (&m_strParam);
dwInSt |= decodeStream.ReadLong (&lGotObj);
if (lGotObj)
{
m_pObjParam = CreateClassObject (&decodeStream);
if (!bVerifyPointer (m_pObjParam))
{
m_pObjParam = NULL;
SetStatus (WBEM_E_FAILED);
}
else
m_pObjParam->Release (); // Bumped up by bVerifyPointer
}
}
void CStubOperation_LPipe_SetStatus::Execute (CComLink& comLink, IUnknown *pStub)
{
IWbemObjectSink* pObj = (IWbemObjectSink *) pStub;
DEBUGTRACE((LOG,"\nCalling SetStatus into stub = %X", pObj));
SetStatus (pObj->SetStatus (m_flags, m_param, m_strParam,
m_pObjParam));
}
// CStubOperation_LPipe_Release
void CStubOperation_LPipe_Release::Execute (CComLink& comLink, IUnknown *pStub)
{
switch (m_stubType)
{
case LOGIN:
case ENUMERATOR:
case PROVIDER:
case OBJECTSINK:
case CALLRESULT:
comLink.Release2 ((void *) pStub, (enum ObjType) m_stubType);
SetStatus (pStub->Release ());
break;
default:
SetStatus (WBEM_E_FAILED);
return;
}
}