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.
 
 
 
 
 
 

1535 lines
45 KiB

*********************************************************************
THIS FILE IS NO LONGER PART OF THE BUILD.
IT IS BEING LEFT IN THE SLM ENLISTMENT FOR catsrc USAGE.
SEE resolver.cxx in dcomrem or remote\chicago\resolver.hxx.
*********************************************************************
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: dcoscm.cxx
//
// Contents: Files relating to compobj communication with the SCM
// for the DCOM version of OLE remoting.
//
// Functions: CCoScm::CCoScm
// CCoScm::~CCoScm
// CCoScm::BindToSCM
// CCoScm::NotifyStarted
// CCoScm::NotifyStopped
//
// History: 19-May-92 Ricksa Created
// 20-May-95 AlexMit Use object interfaces
//
//--------------------------------------------------------------------------
#include <ole2int.h>
#include <coscm.hxx>
#include <service.hxx> // GetLocalStringBinding
#include <objerror.h>
#include <sobjact.hxx>
// mutex to guard binding to the SCM.
extern COleStaticMutexSem g_mxsSingleThreadOle;
// String arrays for the SCM process. These are used to tell the interface
// marshaling code the protocol and endpoint of the SCM process.
#ifdef _CHICAGO_
typedef struct tagSCMSA
{
unsigned short wNumEntries; // Number of entries in array.
unsigned short wSecurityOffset; // Offset of security info.
WCHAR awszStringArray[26];
} SCMSA;
SCMSA saSCM = {26, 25, L"mswmsg:[endpoint mapper]\0" };
#else
typedef struct tagSCMSA
{
unsigned short wNumEntries; // Number of entries in array.
unsigned short wSecurityOffset; // Offset of security info.
WCHAR awszStringArray[60];
} SCMSA;
// The last 4 characters in the string define the security bindings.
// \0xA is RPC_C_AUTHN_WINNT
// \0xFFFF is COM_C_AUTHZ_NONE
// \0 is an empty principle name
SCMSA saSCM = {57, 56, L"ncalrpc:[epmapper,Security=Impersonation Dynamic False]\0\xA\xFFFF\0"};
#endif
// Static data members of CCoScm
#ifndef _CHICAGO_
#define INVALID_VALUE -1
handle_t CCoScm::_hRPC = NULL;
IOSCM * CCoScm::_pSCMSTA = NULL;
IOSCM * CCoScm::_pSCMMTA = NULL;
IDSCM * CCoScm::_pNewSCMSTA = NULL;
IDSCM * CCoScm::_pNewSCMMTA = NULL;
LONG CCoScm::_fInteractiveUser = INVALID_VALUE;
LPWSTR CCoScm::_lpDesktop = NULL;
enum CCoScm::_HandleState CCoScm::_HandleState = SCM_HSTATE_NOT_YET_RUNNING;
COleStaticMutexSem CCoScm::_mHRpcLock;
#endif
//+-------------------------------------------------------------------------
//
// Class: GetObjectClientDesktop
//
// Purpose: Get the string representing the desktop which the object
// client runs on.
//
// Returns: A string representing the desktop or NULL.
//
// History: 11-Nov-93 Ricksa Created
//
//--------------------------------------------------------------------------
#ifdef _CHICAGO_
inline LPWSTR GetObjectClientDesktop (void)
{
return NULL;
}
#else // not _CHICAGO_
LPWSTR GetObjectClientDesktop (void)
{
LPWSTR lpDesktop = NULL;
HDESK hDesk = GetThreadDesktop (GetCurrentThreadId());
if (hDesk)
{
DWORD cbDesktop;
if (!GetUserObjectInformation (hDesk, UOI_NAME, NULL, 0, &cbDesktop)
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
lpDesktop = (WCHAR *) PrivMemAlloc (cbDesktop);
if (lpDesktop != NULL)
{
GetUserObjectInformation(hDesk, UOI_NAME,
lpDesktop, cbDesktop, &cbDesktop);
}
}
}
return lpDesktop;
}
#endif // _CHICAGO_
//+-------------------------------------------------------------------------
//
// Member: CCoScm::CleanUp
//
// Synopsis: Release the RPC connection with the SCM
//
// History: 24-Jun-94 DonnaLi Created
//
//--------------------------------------------------------------------------
void CCoScm::CleanUp(void)
{
// Just close the RPC handle if it has been set
if (_hRPC != NULL)
{
// make sure we don't try to reconnect
_HandleState = SCM_HSTATE_TERMINATING;
RpcBindingFree(&_hRPC);
_hRPC = NULL;
}
if (_pSCMSTA != NULL)
{
_pSCMSTA->Release();
_pSCMSTA = NULL;
}
if (_pSCMMTA != NULL)
{
_pSCMMTA->Release();
_pSCMMTA = NULL;
}
if (_pNewSCMSTA != NULL)
{
_pNewSCMSTA->Release();
_pNewSCMSTA = NULL;
}
if (_pNewSCMMTA != NULL)
{
_pNewSCMMTA->Release();
_pNewSCMMTA = NULL;
}
if (_lpDesktop != NULL)
{
PrivMemFree(_lpDesktop);
_lpDesktop = NULL;
}
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::CleanUp
//
// Synopsis: Release the RPC connection with the SCM
//
// History: 24-Jun-94 DonnaLi Created
//
//--------------------------------------------------------------------------
void CCoScm::ShutDown(void)
{
// Just close the RPC handle if it has been set
if (_HandleState != SCM_HSTATE_TERMINATING)
{
// Don't do the shutdown unless we have done the cleanup
CleanUp;
}
_HandleState = SCM_HSTATE_NOT_YET_RUNNING;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::BindToSCMBody
//
// Synopsis: Get a connection to the SCM
//
// Algorithm: The well known address is built for the SCM. Then we bind
// to the address and release the string that we created.
//
// History: 19-May-92 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::BindToSCMBody(void)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::BindToSCM");
ComDebOut((DEB_SCM, "CCoScm::BindToSCM\n"));
HRESULT hr = S_OK;
if ( _HandleState == SCM_HSTATE_RUNNING )
return hr;
// if the connection to the SCM is anything other than uninitialized,
// we are cleaning up, and we aren't going to ever give it out again.
// BUGBUG: find the right return code here...
if ( _HandleState != SCM_HSTATE_NOT_YET_RUNNING )
return E_FAIL;
// must single thread access to this code.
// WARNING: we cant use the SingleThreadOle lock since we could
// be called by the ORPC code in BindToSCMProxy below on another thread.
COleStaticLock lck(_mHRpcLock);
// Don't do anything if we already have a binding handle.
if (_hRPC == NULL)
{
RPC_STATUS sc = RpcBindingFromStringBinding(saSCM.awszStringArray,
&_hRPC);
if (sc != RPC_S_OK)
{
hr = HRESULT_FROM_WIN32(sc);
}
#ifdef DCOM
// Determine if we're the interactive user
if (_fInteractiveUser == INVALID_VALUE)
{
HWINSTA hWinSta = OpenWindowStation(L"winsta0",
FALSE,
MAXIMUM_ALLOWED);
if (hWinSta == NULL)
{
_fInteractiveUser = FALSE;
}
else
{
_fInteractiveUser = TRUE;
CloseWindowStation(hWinSta);
}
}
#endif // DCOM
if (_lpDesktop == NULL)
{
_lpDesktop = GetObjectClientDesktop();
}
_HandleState == SCM_HSTATE_RUNNING;
}
ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
"CCoScm::BindToSCM returns:%x _hRPC:%x\n", hr, _hRPC));
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::BindToSCMProxy
//
// Synopsis: Get a proxy to the SCM Activation interface.
//
// History: 19-May-95 Rickhi Created
//
// Notes: The SCM activation interface is an ORPC interface so that
// apartment model apps can receive callbacks and do cancels
// while activating object servers.
//
// The reason we have 2 differnt BindToSCM routines is that
// IrotGetUniqueProcessID is called during CoInitializeEx, before
// we are initialized enough to be able to build a proxy, so for
// all the routines that are RAW RPC and only require an Rpc
// handle, we call BindToSCM, while the activation routines which
// require a proxy, must call BindToSCMProxy.
//
//--------------------------------------------------------------------------
HRESULT CCoScm::BindToSCMProxy(void)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::BindToSCMProxy");
ComDebOut((DEB_SCM, "CCoScm::BindToSCMProxy\n"));
// since we are calling out on this thread, we have to ensure that the
// call control is set up for this thread.
HRESULT hr = InitChannelIfNecessary();
// must single thread access to this code since we are creating just
// one proxy to the SCM usable by all threads, and multiple threads
// can try to simultaneously use it.
COleStaticLock lck(g_mxsSingleThreadOle);
if (IsSTAThread())
{
if (_pSCMSTA == NULL)
{
// Make a proxy to the SCM
hr = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IOSCM, (void **) &_pSCMSTA);
}
ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
"CCoScm::BindToSCMProxy returns:%x _pSCMSTA:%x\n", hr, _pSCMSTA));
if (_pNewSCMSTA == NULL)
{
HRESULT hr2;
// Make a proxy to the SCM
hr2 = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IDSCM, (void **) &_pNewSCMSTA);
ComDebOut((SUCCEEDED(hr2) ? DEB_SCM : DEB_ERROR,
"CCoScm::BindToSCMProxy for IDSCM returns %x.\n", hr2));
// make sure we set hr to the first failure here...
if (SUCCEEDED(hr) && FAILED(hr2))
hr = hr2;
}
}
else
{
if (_pSCMMTA == NULL)
{
// Make a proxy to the SCM
hr = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IOSCM, (void **) &_pSCMMTA);
}
ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
"CCoScm::BindToSCMProxy returns:%x _pSCMSTA:%x\n", hr, _pSCMMTA));
if (_pNewSCMMTA == NULL)
{
HRESULT hr2;
// Make a proxy to the SCM
hr2 = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IDSCM, (void **) &_pNewSCMMTA);
ComDebOut((SUCCEEDED(hr2) ? DEB_SCM : DEB_ERROR,
"CCoScm::BindToSCMProxy for IDSCM returns %x.\n", hr2));
// make sure we set hr to the first failure here...
if (SUCCEEDED(hr) && FAILED(hr2))
hr = hr2;
}
}
// Determine if we're the interactive user
if (_fInteractiveUser == INVALID_VALUE)
{
HWINSTA hWinSta = OpenWindowStation(L"winsta0",
FALSE,
MAXIMUM_ALLOWED);
if (hWinSta == NULL)
{
_fInteractiveUser = FALSE;
}
else
{
_fInteractiveUser = TRUE;
CloseWindowStation(hWinSta);
}
}
if (_lpDesktop == NULL)
{
_lpDesktop = GetObjectClientDesktop();
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::NotifyStarted
//
// Synopsis: Notify the SCM that a class has been started
//
// Arguments: [rclsid] - class started
// [dwFlags] - whether class is multiple use or not.
//
// Algorithm: MISSING pending move to new marshal model.
//
// History: 19-May-92 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::NotifyStarted(
REFCLSID rclsid,
DWORD dwFlags,
DWORD& dwAtStorage,
DWORD& dwReg)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::NotifyStarted");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
// Dig our local binding string out of the list of endpoints.
// Remember we are always local to our SCM so we don't have to
// send the entire set of endpoints. Just the one they need
// to call us.
LPWSTR pwszBindString = GetLocalStringBinding();
if (pwszBindString == NULL)
{
return E_OUTOFMEMORY;
}
// Tell SCM that we are started
error_status_t rpcstat;
// for now, we only register one class at a time...
const DWORD OLE_CLASS_COUNT = 1;
RegOutput *pregout = NULL;
CObjServer *pobjserver = GetObjServer();
RegInput *pRegin = (RegInput*) new char[ sizeof(RegInput) + (OLE_CLASS_COUNT-1)*sizeof(RegInputEntry)];
pRegin->dwSize = OLE_CLASS_COUNT;
pRegin->rginent[0].clsid = rclsid;
pRegin->rginent[0].pwszEndPoint = pwszBindString;
pRegin->rginent[0].dwFlags = dwFlags;
pRegin->rginent[0].ipid = pobjserver->GetIPID();
do
{
hr = ObjectServerStarted(
_hRPC,
_lpDesktop,
pRegin,
&pregout,
&rpcstat
);
} while (RetryRPC(rpcstat));
PrivMemFree( pwszBindString );
ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
"Class Registration returned %x", hr));
if (rpcstat != RPC_S_OK)
{
return HRESULT_FROM_WIN32(rpcstat);
}
else if (SUCCEEDED(hr))
{
Win4Assert((pregout->dwSize <= 2) &&
"CCoScm::NotifyStarted Invalid regout");
dwAtStorage = pregout->regoutent[0].dwAtStorage;
dwReg = pregout->regoutent[0].dwReg;
// Free memory from RPC
MIDL_user_free(pregout);
}
delete[] pRegin;
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::NotifyStopped
//
// Synopsis: Notify the SCM that the server is stopped.
//
// History: 19-May-92 Ricksa Created
//
//--------------------------------------------------------------------------
void CCoScm::NotifyStopped(REFCLSID rclsid, DWORD dwReg)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::NotifyStopped");
error_status_t rpcstat;
RevokeClasses revcls;
revcls.dwSize = 1;
revcls.revent[0].clsid = rclsid;
revcls.revent[0].dwReg = dwReg;
do
{
StopServer(_hRPC, &revcls, &rpcstat);
} while (RetryRPC(rpcstat));
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::GetClassObject
//
// Synopsis: Send a get object request to the SCM
//
// Arguments: [rclsid] - class id for class object
// [dwCtrl] - type of server required
// [ppIFDClassObj] - marshaled buffer for class object
// [ppwszDllToLoad] - DLL name to use for server
//
// Returns: S_OK
//
// History: 20-May-93 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::OldGetClassObject(
REFCLSID rclsid,
DWORD dwContext,
WCHAR *pwszServer,
InterfaceData **ppIFDClassObj,
DWORD *pdwDllServerType,
WCHAR **ppwszDllToLoad)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::GetClassObject");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::GetClassObject Invalid Requested Thread Model");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
// determine the class context to use for this call. We should
// not allow a CoGetClassObject of a local server inside of an
// input sync call, but we have to allow inproc server because
// we may be unmarshalling an interface and need the proxy dll.
if (dwContext & CLSCTX_PS_DLL)
{
hr = GetSCM()->InputSyncStartObjectService(_lpDesktop,
&rclsid,
dwContext,
pwszServer,
ppIFDClassObj,
pdwDllServerType,
ppwszDllToLoad );
}
else
{
hr = GetSCM()->SyncStartObjectService( _lpDesktop,
&rclsid,
dwContext,
pwszServer,
ppIFDClassObj,
pdwDllServerType,
ppwszDllToLoad );
}
return hr;
}
#ifdef DCOM
//+-------------------------------------------------------------------------
//
// Member: CCoScm::GetClassObject
//
// Synopsis: Send a get object request to the SCM
//
// Arguments: [rclsid] - class id for class object
// [dwCtrl] - type of server required
// [ppIFDClassObj] - marshaled buffer for class object
// [ppwszDllToLoad] - DLL name to use for server
//
// Returns: S_OK
//
// History: 20-May-93 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::GetClassObject(
REFCLSID rclsid,
DWORD dwContext,
COSERVERINFO *pServerInfo,
MInterfacePointer **ppIFDClassObj,
DWORD *pdwDllServerType,
WCHAR **ppwszDllToLoad)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::GetClassObject");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::GetClassObject Invalid Requested Thread Model");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
WCHAR * pServerName = NULL;
// extract the server information
if ( pServerInfo )
{
pServerName = pServerInfo->pszName;
}
// determine the class context to use for this call. We should
// not allow a CoGetClassObject of a local server inside of an
// input sync call, but we have to allow inproc server because
// we may be unmarshalling an interface and need the proxy dll.
/*
HRESULT SCMGetClassObject(
COM_HANDLE
[in] const GUID * Clsid,
[in, string, unique] WCHAR * pwszServer,
[in, string, unique] WCHAR * pwszDesktop,
[in] DWORD ClsContext,
[in, out] DWORD * pDllServerType,
[out, string] WCHAR ** ppwszDllToLoad,
[out] InterfaceData ** ppIDClassFactory
);
*/
if (dwContext & CLSCTX_PS_DLL)
{
hr = GetNewSCM()->InputSyncSCMGetClassObject(&rclsid,
pServerName,
_lpDesktop,
_fInteractiveUser,
dwContext,
pdwDllServerType,
ppwszDllToLoad,
ppIFDClassObj );
}
else
{
hr = GetNewSCM()->SCMGetClassObject( &rclsid,
pServerName,
_lpDesktop,
_fInteractiveUser,
dwContext,
pdwDllServerType,
ppwszDllToLoad,
ppIFDClassObj );
}
return hr;
}
#endif
//+-------------------------------------------------------------------------
//
// Member: CCoScm::CreateObject
//
// Synopsis: Ask SCM to tell a server to create and activate an object
//
// Arguments: [rclsid] - class id for object to create
// [dwOptions] - type of server required
// [dwMode] - mode to open file if file name supplied
// [pwszPath] - path to use for creating the file
// [ppIFDstg] - istorage to use as a template for the file
// [pwszNewName] - name of object to create.
// [ppIFDunk] - marshaled interface to newly created object
// [ppwszDllPath] - path to DLL for server or handler
//
// Returns: S_OK
//
// History: 20-May-93 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::CreateObject(
REFCLSID rclsid,
DWORD dwOptions,
DWORD dwMode,
WCHAR *pwszPath,
InterfaceData *pIFDstg,
WCHAR *pwszNewName,
InterfaceData **ppIFDunk,
DWORD *pdwDllServerType,
WCHAR **ppwszDllPath,
WCHAR *pwszServer)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::CreateObject");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::CreateObject Invalid Requested Thread Model");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
hr = GetSCM()->SvcCreateActivateObject(
_lpDesktop,
NULL,
&rclsid,
dwOptions,
dwMode,
pwszPath,
pIFDstg,
pwszNewName,
ppIFDunk,
pdwDllServerType,
ppwszDllPath,
pwszServer );
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::ActivateObject
//
// Synopsis: Activate an already existing object
//
// Arguments: [rclsid] - class id for object to create
// [dwOptions] - type of server required
// [grfMode] - mode to open file if file name supplied
// [pwszPath] - path to use for the file
// [ppIFDstg] - istorage to use for the file
// [ppIFDunk] - marshaled interface to newly created object
// [pdwDllServerType] -
// [ppwszDllPath] - path to DLL for server or handler
// [pwszServer] -
//
// Returns: S_OK
//
// History: 20-May-93 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::ActivateObject(
REFCLSID rclsid,
DWORD dwOptions,
DWORD grfMode,
WCHAR *pwszPath,
InterfaceData *pIFDstg,
InterfaceData **ppIFDunk,
DWORD *pdwDllServerType,
WCHAR **ppwszDllPath,
WCHAR *pwszServer)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::ActivateObject");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::ActivateObject Invalid Requested Thread Model");
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
hr = GetSCM()->SvcActivateObject(
_lpDesktop,
NULL,
&rclsid,
dwOptions,
grfMode,
0,
pwszPath,
pIFDstg,
ppIFDunk,
pdwDllServerType,
ppwszDllPath,
pwszServer );
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::GetPersistentInstance
//
// Synopsis: Send a get object request to the SCM
//
//GAJGAJ - fix this comment block
// Arguments: [rclsid] - class id for class object
// [dwCtrl] - type of server required
// [ppIFDClassObj] - marshaled buffer for class object
// [ppwszDllToLoad] - DLL name to use for server
//
// Returns: S_OK
//
// History: 20-May-93 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::GetPersistentInstance(
COSERVERINFO * pServerInfo,
CLSID * pClsid,
DWORD dwClsCtx,
DWORD grfMode,
OLECHAR * pwszName,
MInterfacePointer * pstg,
DWORD dwCount,
IID * pIIDs,
MInterfacePointer ** pRetdItfs,
HRESULT * pRetdHrs,
DWORD * pdwDllServerType,
OLECHAR ** ppwszDllToLoad )
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::GetPersistentInstance");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::GetPersistentInstance Invalid Requested Thread Model");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
/*
[in] const GUID * Clsid,
[in, string, unique] WCHAR * pwszServer,
[in, string, unique] WCHAR * pwszDesktop,
[in, string, unique] WCHAR * pwszObjectName,
[in, unique] InterfaceData * pObjectStorage,
[in] DWORD ClsContext,
[in] DWORD FileMode,
[in] DWORD Interfaces,
[in,size_is(Interfaces)] IID * pIIDs,
[in, out] DWORD * pdwDllServerType,
[out, string] WCHAR ** ppwszDllToLoad,
[out,size_is(Interfaces)] PInterfaceData * ppInterfaceData,
[out,size_is(Interfaces)] HRESULT * pResults
*/
hr = GetNewSCM()->SCMGetPersistentInstance(
pClsid,
pServerInfo ? pServerInfo->pszName : 0,
_lpDesktop,
_fInteractiveUser,
pwszName,
pstg,
dwClsCtx,
grfMode,
dwCount,
pIIDs,
pdwDllServerType,
ppwszDllToLoad,
pRetdItfs,
pRetdHrs);
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::CreateInstance
//
// Synopsis: Send a get object request to the SCM
//
//GAJGAJ - fix this comment block
// Arguments: [rclsid] - class id for class object
// [dwCtrl] - type of server required
// [ppIFDClassObj] - marshaled buffer for class object
// [ppwszDllToLoad] - DLL name to use for server
//
// Returns: S_OK
//
// History: 20-May-93 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::CreateInstance(
COSERVERINFO * pServerInfo,
CLSID * pClsid,
DWORD dwClsCtx,
DWORD dwCount,
IID * pIIDs,
MInterfacePointer ** pRetdItfs,
HRESULT * pRetdHrs,
DWORD * pdwDllServerType,
OLECHAR ** ppwszDllToLoad )
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::CreateInstance");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::GetPersistentInstance Invalid Requested Thread Model");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
/*
[in] const GUID * Clsid,
[in, string, unique] WCHAR * pwszServer,
[in, string, unique] WCHAR * pwszDesktop,
[in] DWORD ClsContext,
[in] DWORD Interfaces,
[in,size_is(Interfaces)] IID * pIIDs,
[in, out] DWORD * pDllServerType,
[out, string] WCHAR ** ppwszDllToLoad,
[out,size_is(Interfaces)] PInterfaceData * ppInterfaceData,
[out,size_is(Interfaces)] HRESULT * pResults
*/
hr = GetNewSCM()->SCMCreateInstance(
pClsid,
pServerInfo ? pServerInfo->pszName : 0,
_lpDesktop,
_fInteractiveUser,
dwClsCtx,
dwCount,
pIIDs,
pdwDllServerType,
ppwszDllToLoad,
pRetdItfs,
pRetdHrs);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CCoScm::CreateInstanceWithHandler
//
// Synopsis: Calls scm which will launch the application for given class id
// and instanciate a class object with a severhandler object.
//
// Arguments: [pServerInfo] --
// [pClsid] --
// [dwClsCtx] --
// [dwCount] --
// [pIIDs] --
// [pRetdItfs] --
// [pRetdHrs] --
// [pdwDllServerType] --
// [ppwszDllToLoad] --
// [pClsidHandler] --
// [ppIFPServerHandler] --
// [pIFPClientSiteHandler] --
//
// Returns:
//
// History: 11-11-95 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CCoScm::CreateInstanceWithHandler(
COSERVERINFO * pServerInfo,
CLSID * pClsid,
DWORD dwClsCtx,
DWORD dwCount,
IID * pIIDs,
MInterfacePointer ** pRetdItfs,
HRESULT * pRetdHrs,
DWORD * pdwDllServerType,
OLECHAR ** ppwszDllToLoad,
CLSID * pClsidHandler,
MInterfacePointer ** ppIFPServerHandler,
MInterfacePointer * pIFPClientSiteHandler
)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::CreateInstanceWithHandler");
Win4Assert(((*pdwDllServerType == APT_THREADED)
|| (*pdwDllServerType == FREE_THREADED))
&& "CCoScm::GetPersistentInstance Invalid Requested Thread Model");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCMProxy();
if (FAILED(hr))
return hr;
/*
[in] const GUID * Clsid,
[in, string, unique] WCHAR * pwszServer,
[in, string, unique] WCHAR * pwszDesktop,
[in] DWORD ClsContext,
[in] DWORD Interfaces,
[in,size_is(Interfaces)] IID * pIIDs,
[in, out] DWORD * pDllServerType,
[out, string] WCHAR ** ppwszDllToLoad,
[out,size_is(Interfaces)] PInterfaceData * ppInterfaceData,
[out,size_is(Interfaces)] HRESULT * pResults
[in] CLSID * pClsidHandler,
[out] MInterfacePointer ** ppIFPServerHandler,
[in] MInterfacePointer * pIFPClientSiteHandler
*/
hr = GetNewSCM()->SCMCreateInstanceWithHandler(
pClsid,
pServerInfo ? pServerInfo->pszName : 0,
_lpDesktop,
_fInteractiveUser,
dwClsCtx,
dwCount,
pIIDs,
pdwDllServerType,
ppwszDllToLoad,
pRetdItfs,
pRetdHrs,
pClsidHandler,
ppIFPServerHandler,
pIFPClientSiteHandler);
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotRegister
//
// Synopsis: Register an object in the ROT
//
// Arguments: [pmkeqbuf] - moniker compare buffer
// [pifdObject] - marshaled interface for object
// [pifdObjectName] - marshaled moniker
// [pfiletime] - file time of last change
// [dwProcessID] -
// [psrkRegister] - output of registration
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotRegister(
MNKEQBUF *pmkeqbuf,
InterfaceData *pifdObject,
InterfaceData *pifdObjectName,
FILETIME *pfiletime,
DWORD dwProcessID,
SCMREGKEY *psrkRegister)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotRegister(
_hRPC,
pmkeqbuf,
pifdObject,
pifdObjectName,
pfiletime,
dwProcessID,
psrkRegister,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotRevoke
//
// Synopsis: Call to SCM to revoke object from the ROT
//
// Arguments: [psrkRegister] - moniker compare buffer
// [fServerRevoke] - whether server for object is revoking
// [pifdObject] - where to put marshaled object
// [pifdName] - where to put marshaled moniker
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotRevoke(
SCMREGKEY *psrkRegister,
BOOL fServerRevoke,
InterfaceData **ppifdObject,
InterfaceData **ppifdName)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotRevoke(
_hRPC,
psrkRegister,
fServerRevoke,
ppifdObject,
ppifdName,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotIsRunning
//
// Synopsis: Call to SCM to determine if object is in the ROT
//
// Arguments: [pmkeqbuf] - moniker compare buffer
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotIsRunning(MNKEQBUF *pmkeqbuf)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotIsRunning(
_hRPC,
pmkeqbuf,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotGetObject
//
// Synopsis: Call to SCM to determine if object is in the ROT
//
// Arguments: [dwProcessID] - process ID for object we want
// [pmkeqbuf] - moniker compare buffer
// [psrkRegister] - registration ID in SCM
// [pifdObject] - marshaled interface for the object
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotGetObject(
DWORD dwProcessID,
MNKEQBUF *pmkeqbuf,
SCMREGKEY *psrkRegister,
InterfaceData **pifdObject)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotGetObject(
_hRPC,
dwProcessID,
pmkeqbuf,
psrkRegister,
pifdObject,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotNoteChangeTime
//
// Synopsis: Call to SCM to set time of change for object in the ROT
//
// Arguments: [psrkRegister] - SCM registration ID
// [pfiletime] - time of change
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotNoteChangeTime(
SCMREGKEY *psrkRegister,
FILETIME *pfiletime)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotNoteChangeTime(
_hRPC,
psrkRegister,
pfiletime,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotGetTimeOfLastChange
//
// Synopsis: Call to SCM to get time changed of object in the ROT
//
// Arguments: [pmkeqbuf] - moniker compare buffer
// [pfiletime] - where to put time of last change
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotGetTimeOfLastChange(
MNKEQBUF *pmkeqbuf,
FILETIME *pfiletime)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotGetTimeOfLastChange(
_hRPC,
pmkeqbuf,
pfiletime,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotEnumRunning
//
// Synopsis: Call to SCM to enumerate running objects in the ROT
//
// Arguments: [ppMkIFList] - output pointer to array of marshaled monikers
//
// Returns: S_OK
//
// History: 28-Jan-95 Ricksa Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotEnumRunning(MkInterfaceList **ppMkIFList)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotEnumRunning(
_hRPC,
ppMkIFList,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
#ifndef _CHICAGO_
//+-------------------------------------------------------------------------
//
// Member: CCoScm::IrotGetUniqueProcessID
//
// Synopsis: Call to SCM to generate a unique process ID
//
// Arguments: [pdwProcessID] - Returns a process ID
//
// Returns: S_OK - dwProcessID is valid
// other - dwProcessID is undefined
//
// History: 28-Mar-95 KevinRo Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::IrotGetUniqueProcessID(DWORD *pdwProcessID,
DWORD *pdwScmProcessID)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr ))
return hr;
error_status_t rpcstat = RPC_S_OK;
do
{
hr = ::IrotGetUniqueProcessID(
_hRPC,
pdwProcessID,
pdwScmProcessID,
&rpcstat);
} while (RetryRPC(rpcstat));
if (rpcstat != RPC_S_OK)
{
hr = CO_E_SCM_RPC_FAILURE;
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::UpdateShrdTbls
//
// Synopsis: Ask the SCM to update the shared memory tables.
//
// Arguments: none
//
// History: 11-July-94 Rickhi Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::UpdateShrdTbls(void)
{
TRACECALL(TRACE_ACTIVATION, "CCoScm::UpdateShrdTbls");
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat;
do
{
hr = ::UpdateShrdTbls(_hRPC, &rpcstat);
} while (RetryRPC(rpcstat));
ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
"UpdateShrdTbls returned %x\n", hr));
if (rpcstat != RPC_S_OK)
{
return HRESULT_FROM_WIN32(rpcstat);
}
return hr;
}
#endif // _CHICAGO_
#ifdef DCOM
//+-------------------------------------------------------------------------
//
// Member: CCoScm::RegisterWindowPropInterface
//
// Synopsis: Register window property interface with the SCM
//
// Arguments:
//
// History: 22-Jan-96 Rickhi Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::RegisterWindowPropInterface(HWND hWnd, STDOBJREF *pStd,
OXID_INFO *pOxidInfo,
DWORD *pdwCookie)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat;
do
{
hr = ::RegisterWindowPropInterface(_hRPC, (DWORD) hWnd,
pStd, pOxidInfo, pdwCookie, &rpcstat);
} while (RetryRPC(rpcstat));
ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
"RegisterWindowPropInterface returned %x\n", hr));
if (rpcstat != RPC_S_OK)
{
return HRESULT_FROM_WIN32(rpcstat);
}
return hr;
}
//+-------------------------------------------------------------------------
//
// Member: CCoScm::RegisterWindowPropInterface
//
// Synopsis: Get (and possibly Revoke) window property interface
// registration with the SCM.
//
// Arguments:
//
// History: 22-Jan-96 Rickhi Created
//
//--------------------------------------------------------------------------
HRESULT CCoScm::GetWindowPropInterface(HWND hWnd, DWORD dwCookie, BOOL fRevoke,
STDOBJREF *pStd, OXID_INFO *pOxidInfo)
{
// Bind to the SCM if that hasn't already happened
HRESULT hr = BindToSCM();
if (FAILED(hr))
return hr;
error_status_t rpcstat;
do
{
hr = ::GetWindowPropInterface(_hRPC, (DWORD) hWnd, dwCookie, fRevoke,
pStd, pOxidInfo, &rpcstat);
} while (RetryRPC(rpcstat));
ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
"GetWindowPropInterface returned %x\n", hr));
if (rpcstat != RPC_S_OK)
{
return HRESULT_FROM_WIN32(rpcstat);
}
return hr;
}
#endif // DCOM
//+-------------------------------------------------------------------------
//
// Member: CCoScm::RetryRPC
//
// Synopsis: Determines whether RPC to SCM should be retried.
//
// Arguments: [rpcstat] - status of the operation
//
// Returns: TRUE - retry the operation
// FALSE - do not retry the operation
//
// History: 06-Jun-93 Ricksa Created
//
//--------------------------------------------------------------------------
BOOL CCoScm::RetryRPC(error_status_t rpcstat)
{
if (rpcstat == S_OK)
{
return FALSE;
}
TRACECALL(TRACE_ACTIVATION, "CCoScm::RetryRpc");
// Special server error that means the server will probably
// recover.
if (rpcstat == RPC_S_SERVER_TOO_BUSY)
{
CairoleDebugOut(( DEB_ITRACE|DEB_SCM,
"CCoScm::RetryRPC is sleeping\n"));
// If the SCM is too busy to talk with us, take a break
Sleep(3000);
// We will try again
// BUGBUG: this is currently an infinite loop. Should
// there be a retry limit?
return TRUE;
}
return FALSE;
}