Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

764 lines
24 KiB

/+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: omarshal.cxx
//
// Contents: Implementation of CNtHandleUnmarshalFactory
//
// History: 25-Oct-95 HenryLee Created
//
//----------------------------------------------------------------------------
#include <headers.cxx>
#pragma hdrstop
#include <omarshal.hxx>
#include <odocstg.hxx>
#include <odocstm.hxx>
extern const CLSID CLSID_NtHandleMarshal = {0x521a28f2,0xe40b,0x11ce,
{0xb2,0xc9,0x00,0xaa,0x00,0x68,0x09,0x37}};
// This GUID is also located in \nt\public\oak\bin\oleext.ini
//+--------------------------------------------------------------
//
// Member: ::sCNtHandleUnmarshalFactory, public static
//
// Synopsis: Overloaded allocator
//
// Returns: Memory block for CNtHandleUnmarshalFactory instance
//
// History: 25-Oct-95 HenryLee Created
//
// Notes: We only need one instance of CNtHandleUnmarshalFactory.
//
//---------------------------------------------------------------
CNtHandleUnmarshalFactory sCNtHandleUnmarshalFactory;
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::AddRef, public
//
// Synopsis: Increments the ref count
//
// Returns: Appropriate status code
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP_(ULONG) CNtHandleUnmarshalFactory::AddRef(void)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::AddRef:%p => %ld\n",
this, _AddRef()));
return _AddRef();
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::Release, public
//
// Synopsis: Releases resources
//
// Returns: Appropriate status code
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP_(ULONG) CNtHandleUnmarshalFactory::Release(void)
{
const LONG lRet = 0;
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::Release:%p => %ld\n",
this, lRet));
return lRet;
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::QueryInterface, public
//
// Synopsis: Returns an object for the requested interface
//
// Arguments: [iid] - Interface ID
// [ppv] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppv]
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::QueryInterface(REFIID riid,
void **ppv)
{
SCODE sc = S_OK;
ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalFactory::QueryInterface:%p("
"riid, %p)\n", this, ppv));
TRY
{
ssChk(Validate());
ssChk(ValidateOutPtrBuffer(ppv));
*ppv = NULL;
ssChk(ValidateIid(riid));
if (IsEqualIID(riid, IID_IClassFactory) ||
IsEqualIID(riid, IID_IUnknown))
{
_AddRef();
*ppv = (IClassFactory *)this;
}
else if (IsEqualIID(riid, IID_IMarshal))
{
_AddRef();
*ppv = (IMarshal *)this;
}
else
ssErr(EH_Err, E_NOINTERFACE);
}
CATCH(CException, e)
{
sc = e.GetErrorCode();
}
END_CATCH
ssDebugOut((DEB_TRACE, "Out CNtHandleUnmarshalFactory::QueryInterface => "
"%p\n", *ppv));
EH_Err:
return ssResult(sc);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::GetUnmarshalClass, public
//
// Synopsis: Returns the class ID
//
// Arguments: [riid] - IID of object
// [pv] - Unreferenced
// [dwDestContext] - Unreferenced
// [pvDestContext] - Unreferenced
// [mshlflags] - Unreferenced
// [pcid] - CLSID return
//
// Returns: Appropriate status code
//
// Modifies: [pcid]
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::GetUnmarshalClass(REFIID riid,
void *pv,
DWORD dwDestContext,
LPVOID pvDestContext,
DWORD mshlflags,
LPCLSID pcid)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::GetUnmarshalClass("
"%p, riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
pvDestContext, mshlflags, pcid));
return ssResult(STG_E_INVALIDFUNCTION);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::GetMarshalSizeMax, public
//
// Synopsis: Returns the size needed for the marshal buffer
//
// Arguments: [iid] - IID of object being marshaled
// [pv] - Unreferenced
// [dwDestContext] - Unreferenced
// [pvDestContext] - Unreferenced
// [mshlflags] - Unreferenced
// [pcbSize] - Size return
//
// Returns: Appropriate status code
//
// Modifies: [pcbSize]
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::GetMarshalSizeMax(REFIID iid,
void *pv,
DWORD dwDestContext,
LPVOID pvDestContext,
DWORD mshlflags,
LPDWORD pcbSize)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::GetMarshalSizeMax("
"%p, riid, %p, %lu, %p, %lu, %p)\n",
this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
return ssResult(STG_E_INVALIDFUNCTION);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::MarshalInterface, public
//
// Synopsis: Marshals a given object
//
// Arguments: [pstStm] - Stream to write marshal data into
// [iid] - Interface to marshal
// [pv] - Unreferenced
// [dwDestContext] - Unreferenced
// [pvDestContext] - Unreferenced
// [mshlflags] - Unreferenced
//
// Returns: Appropriate status code
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::MarshalInterface(IStream *pstStm,
REFIID iid,
void *pv,
DWORD dwDestContext,
LPVOID pvDestContext,
DWORD mshlflags)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::MarshalInterface("
"%p, %p, riid, %p, %lu, %p, %lu). Context == %lX\n",
this, pstStm, pv, dwDestContext, pvDestContext, mshlflags,
(ULONG)GetCurrentContextId()));
return ssResult(STG_E_INVALIDFUNCTION);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::UnmarshalInterface, public
//
// Synopsis: Calls through to DfUnmarshalInterface
//
// Arguments: [pstStm] - Marshal stream
// [riid] - IID of object to unmarshal
// [ppv] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppv]
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::UnmarshalInterface(IStream *pstStm,
REFIID iid,
void **ppvObj)
{
SCODE sc = S_OK;
ULONG cbRead;
DWORD mshlflags;
SafeIUnknown punk;
CNtHandleMarshalPacket NtHandlePacket;
HANDLE hTarget = NULL;
SafeNtHandle hSourceProcess, hTargetProcess;
NTSTATUS nts;
ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalInterface::UnmarhalInterface"
" (%p, ?, %p)\n", pstStm, ppvObj));
ssChk(ValidateOutPtrBuffer(ppvObj));
*ppvObj = NULL;
ssChk(ValidateInterface(pstStm, IID_IStream));
ssChk(ValidateIid(iid));
ssChk(pstStm->Read(&NtHandlePacket, sizeof(NtHandlePacket), &cbRead));
if (cbRead != sizeof(NtHandlePacket))
ssErr(EH_Err, STG_E_READFAULT);
if (!(IsEqualIID(NtHandlePacket.iid, iid)) &&
!(IsEqualIID(iid, IID_IUnknown)))
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
if ((hSourceProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE,
NtHandlePacket.dwPId)) == NULL)
ssErr (EH_Err, STG_E_INVALIDHANDLE);
if ((hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE,
GetCurrentProcessId())) == NULL)
ssErr (EH_Err, STG_E_INVALIDHANDLE);
// The OLE spec says that a marshaled object may be unmarshaled
// zero or more times from the same packet. We don't support this here.
// BUGBUG only 1 object can be created per marshaling packet.
if (DuplicateHandle (hSourceProcess, NtHandlePacket.hSource,
hTargetProcess, &hTarget, NULL, FALSE,
DUPLICATE_CLOSE_SOURCE |
DUPLICATE_SAME_ACCESS) == FALSE)
{
ssErr (EH_Err, WIN32_SCODE(GetLastError()));
}
switch (NtHandlePacket.dwStgfmt)
{
case STGFMT_DOCUMENT:
if (IsEqualIID(iid, IID_IStream))
{
SafeCOfsDocStream pstm;
pstm.Attach (new COfsDocStream);
ssMem ((COfsDocStream *) pstm);
ssChk (pstm->InitFromHandle(hTarget, NULL, NtHandlePacket.grfMode,
FALSE));
TRANSFER_INTERFACE(pstm, IStream, ppvObj);
}
else if (IsEqualIID(iid, IID_IStorage))
{
SafeCOfsDocStorage pstg;
pstg.Attach (new COfsDocStorage);
ssMem ((COfsDocStorage *) pstg);
ssChk (pstg->InitFromHandle (hTarget, NULL,
NtHandlePacket.grfMode, TRUE));
TRANSFER_INTERFACE(pstg, IStorage, ppvObj);
}
else
sc = E_NOINTERFACE;
break;
default:
sc = STG_E_INVALIDPARAMETER;
}
#if DBG
if (SUCCEEDED(sc))
{
void *pvCheck;
ssAssert( S_OK==((IUnknown*)*ppvObj)->QueryInterface(iid, &pvCheck));
ssAssert( pvCheck == *ppvObj );
((IUnknown*)pvCheck)->Release();
}
#endif
ssDebugOut((DEB_TRACE,"Out CNtHandleUnmarshalFactory::UnmarshalInterface "
"=> %p\n", *ppvObj));
EH_Err:
if (!SUCCEEDED(sc) && hTarget != NULL) // something went wrong
nts = NtClose (hTarget); // cleanup the duped handle
return ssResult(sc);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::ReleaseMarshalData, public
//
// Synopsis: Non-functional
//
// Arguments: [pstStm] -
//
// Returns: Appropriate status code
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::ReleaseMarshalData(IStream *pstStm)
{
SCODE sc = S_OK;
ULONG cbRead;
DWORD mshlflags;
CNtHandleMarshalPacket NtHandlePacket;
ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalFactory::ReleaseMarshalData("
"%p,%p)\n", this, pstStm));
ssChk(ValidateInterface(pstStm, IID_IStream));
ssChk(pstStm->Read(&NtHandlePacket, sizeof(NtHandlePacket), &cbRead));
if (cbRead != sizeof(NtHandlePacket))
ssErr(EH_Err, STG_E_READFAULT);
ssDebugOut((DEB_TRACE, "CNtHandleUnmarshalFactory::ReleaseMarshalData, "
" this == %p, sc == %lX\n", this, sc));
EH_Err:
return ssResult(sc);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::DisconnectObject, public
//
// Synopsis: Non-functional
//
// Arguments: [dwRevserved] -
//
// Returns: Appropriate status code
//
// History: 25-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::DisconnectObject(DWORD dwReserved)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::DisconnectObject("
" %p,%lu)\n", this, dwReserved));
return ssResult(S_OK);
}
//+---------------------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::CreateInstance, public
//
// Synopsis: Creates an instance of the NtHandle unmarshaller
//
// Arguments: [pUnkOuter] -
// [riid] - IID of object to create
// [ppv] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppv]
//
// History: 25-Oct-95 HenryLee Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::CreateInstance(IUnknown *pUnkOuter,
REFIID riid,
LPVOID *ppv)
{
SCODE sc;
ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalFactory::CreateInstance:%p("
"%p, riid, %p)\n", this, pUnkOuter, ppv));
TRY
{
ssChk(Validate());
ssChk(ValidatePtrBuffer(ppv));
*ppv = NULL;
ssChk(ValidateIid(riid));
if (pUnkOuter != NULL || !IsEqualIID(riid, IID_IMarshal))
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
_AddRef();
*ppv = (IMarshal *)this;
}
CATCH(CException, e)
{
sc = e.GetErrorCode();
}
END_CATCH
ssDebugOut((DEB_TRACE, "Out CNtHandleUnmarshalFactory::CreateInstance => "
"%p\n", ppv));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: CNtHandleUnmarshalFactory::LockServer, public
//
// Synopsis: Non-functional
//
// Arguments: [fLock] -
//
// Returns: Appropriate status code
//
// History: 25-Oct-95 HenryLee Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CNtHandleUnmarshalFactory::LockServer(BOOL fLock)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::LockServer("
" %p,%d)\n", this, fLock));
return ssResult(S_OK);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleMarshal::GetUnmarshalClass, public
//
// Synopsis: Returns the class ID
//
// Arguments: [riid] - IID of object
// [pv] - Unreferenced
// [dwDestContext] - Unreferenced
// [pvDestContext] - Unreferenced
// [mshlflags] - Unreferenced
// [pcid] - CLSID return
//
// Returns: Appropriate status code
//
// Modifies: [pcid]
//
// History: 04-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleMarshal::GetUnmarshalClass(REFIID riid,
void *pv,
DWORD dwDestContext,
LPVOID pvDestContext,
DWORD mshlflags,
LPCLSID pcid)
{
SCODE sc;
ssDebugOut((DEB_TRACE, "In CNtHandleMarshal::GetUnmarshalClass:%p("
"riid, %p, %lu, %p, %lu, %p)\n", this,
pv, dwDestContext, pvDestContext, mshlflags, pcid));
UNREFERENCED_PARM(pv);
UNREFERENCED_PARM(mshlflags);
ssChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
*pcid = CLSID_NULL;
ssChk(ValidateIid(riid));
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
{
IMarshal *pmsh;
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
dwDestContext, pvDestContext,
mshlflags, &pmsh)))
{
sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext,
pvDestContext, mshlflags,
pcid));
pmsh->Release();
}
}
else if (pvDestContext != NULL)
{
sc = STG_E_INVALIDPARAMETER;
}
else
{
*pcid = CLSID_NtHandleMarshal;
}
ssDebugOut((DEB_TRACE, "Out CNtHandle::GetUnmarshalClass\n"));
EH_Err:
return ssResult(sc);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleMarshal::GetMarshalSizeMax, public
//
// Synopsis: Returns the size needed for the marshal buffer
//
// Arguments: [riid] - IID of object being marshaled
// [pv] - Unreferenced
// [dwDestContext] - Unreferenced
// [pvDestContext] - Unreferenced
// [mshlflags] - Unreferenced
// [pcbSize] - Size return
//
// Returns: Appropriate status code
//
// Modifies: [pcbSize]
//
// History: 04-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleMarshal::GetMarshalSizeMax(REFIID riid,
void *pv,
DWORD dwDestContext,
LPVOID pvDestContext,
DWORD mshlflags,
LPDWORD pcbSize)
{
SCODE sc = S_OK;
UNREFERENCED_PARM(pv);
ssDebugOut((DEB_TRACE, "In CNtHandleMarshal::GetMarshalSizeMax:%p("
"riid, %p, %lu, %p, %lu, %p)\n", this,
pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
{
IMarshal *pmsh;
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
dwDestContext, pvDestContext,
mshlflags, &pmsh)))
{
sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
pvDestContext, mshlflags,
pcbSize));
pmsh->Release();
}
}
else if (pvDestContext != NULL)
{
ssErr (EH_Err, STG_E_INVALIDPARAMETER);
}
else
{
*pcbSize = sizeof(CNtHandleMarshalPacket);
}
ssDebugOut((DEB_TRACE, "Out CNtHandleMarshal::GetMarshalSizeMax\n"));
EH_Err:
return ssResult(sc);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleMarshal::MarshalInterface, public
//
// Synopsis: Marshals a given object
//
// Arguments: [pstStm] - Stream to write marshal data into
// [riid] - Interface to marshal
// [pv] - Unreferenced
// [dwDestContext] - Unreferenced
// [pvDestContext] - Unreferenced
// [mshlflags] - Unreferenced
//
// Returns: Appropriate status code
//
// History: 18-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleMarshal::MarshalInterface(IStream *pstStm,
REFIID riid,
void *pv,
DWORD dwDestContext,
LPVOID pvDestContext,
DWORD mshlflags)
{
SCODE sc = S_OK;
NTSTATUS nts;
HANDLE hDup = INVALID_HANDLE_VALUE;
ssDebugOut((DEB_TRACE, "In CNtHandleMarshal::MarshalInterface:%p("
"%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv,
dwDestContext, pvDestContext, mshlflags));
UNREFERENCED_PARM(pv);
ssAssert (_handle != NULL);
if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
{
IMarshal *pmsh;
if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
dwDestContext, pvDestContext,
mshlflags, &pmsh)))
{
sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
dwDestContext, pvDestContext,
mshlflags));
pmsh->Release();
}
}
else if (pvDestContext != NULL)
{
sc = STG_E_INVALIDPARAMETER;
}
else
{
ULONG cbWritten;
CNtHandleMarshalPacket NtHandlePacket;
NtHandlePacket.iid = riid;
NtHandlePacket.dwMarshFlags = mshlflags;
NtHandlePacket.dwPId = GetCurrentProcessId();
NtHandlePacket.dwTId = GetCurrentThreadId();
// The original process may close the handle before
// the unmarshaling packet is processed.
ssChk(DupNtHandle (_handle, &hDup));
NtHandlePacket.hSource = hDup;
NtHandlePacket.grfMode = _grfModeMarshal;
NtHandlePacket.dwStgfmt = _dwStgfmt;
ssChk(ValidateInterface(pstStm, IID_IStream));
ssChk(ValidateIid(riid));
ssChk(pstStm->Write((void *)&NtHandlePacket, sizeof(NtHandlePacket),
&cbWritten));
if (cbWritten != sizeof(NtHandlePacket))
ssErr(EH_Err, STG_E_WRITEFAULT);
if (SUCCEEDED(sc) && mshlflags != MSHLFLAGS_TABLEWEAK)
{
}
}
ssDebugOut((DEB_TRACE, "Out CNtHandleMarshal::MarshalInterface\n"));
EH_Err:
if (!SUCCEEDED(sc) && hDup != INVALID_HANDLE_VALUE) // cleanup on failure
NtClose(hDup);
return ssResult(sc);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleMarshal::UnmarshalInterface, public
//
// Synopsis: Non-functional
//
// Arguments: [pstStm] -
// [riid] -
// [ppvObj] -
//
// Returns: Appropriate status code
//
// Modifies: [ppvObj]
//
// History: 18-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleMarshal::UnmarshalInterface(IStream *pstStm,
REFIID riid,
void **ppvObj)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleMarshal::UnmarshalInterface(%p)\n",
this));
return ssResult(STG_E_INVALIDFUNCTION);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleMarshal::ReleaseMarshalData, public
//
// Synopsis: Non-functional
//
// Arguments: [pstStm] -
//
// Returns: Appropriate status code
//
// History: 18-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleMarshal::ReleaseMarshalData(IStream *pstStm)
{
ssDebugOut((DEB_TRACE, "Stb CNtHandleMarshal::ReleaseMarshalData(%p)\n",
this));
return ssResult(STG_E_INVALIDFUNCTION);
}
//+--------------------------------------------------------------
//
// Member: CNtHandleMarshal::DisconnectObject, public
//
// Synopsis: Non-functional
//
// Arguments: [dwRevserved] -
//
// Returns: Appropriate status code
//
// History: 18-Oct-95 HenryLee Created
//
//---------------------------------------------------------------
STDMETHODIMP CNtHandleMarshal::DisconnectObject(DWORD dwReserved)
{
ssDebugOut((DEB_TRACE,"Stb CNtHandleMarshal::DisconnectObject(%p)\n",this));
return ssResult(STG_E_INVALIDFUNCTION);
}