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.
372 lines
9.0 KiB
372 lines
9.0 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// activate.cxx
|
|
//
|
|
// Main dcom activation service routines.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "act.hxx"
|
|
|
|
HRESULT MakeProcessActive(CProcess *pProcess);
|
|
HRESULT ProcessInitializationFinished(CProcess *pProcess);
|
|
|
|
|
|
HRESULT ProcessActivatorStarted(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
IN ProcessActivatorToken *pActToken,
|
|
OUT error_status_t *prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat || !pActToken)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
HRESULT hr = S_OK;
|
|
CServerTableEntry *pProcessEntry = NULL;
|
|
CAppidData *pAppidData = NULL;
|
|
ScmProcessReg *pScmProcessReg = NULL;
|
|
DWORD RegistrationToken = 0;
|
|
BOOL fCallerOK = FALSE;
|
|
|
|
// Lookup appid info
|
|
hr = LookupAppidData(
|
|
pActToken->ProcessGUID,
|
|
pProcess->GetToken(),
|
|
&pAppidData );
|
|
if (FAILED(hr))
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
ASSERT(pAppidData && "LookupAppidData returned NULL AppidData");
|
|
|
|
//
|
|
// Check that the caller is allowed to register this CLSID.
|
|
//
|
|
fCallerOK = pAppidData->CertifyServer(pProcess);
|
|
if (!fCallerOK)
|
|
{
|
|
hr = CO_E_WRONG_SERVER_IDENTITY;
|
|
goto exit;
|
|
}
|
|
|
|
pProcessEntry = gpProcessTable->GetOrCreate( pActToken->ProcessGUID );
|
|
if (!pProcessEntry)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto exit;
|
|
}
|
|
|
|
pScmProcessReg = new ScmProcessReg;
|
|
if (!pScmProcessReg)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
pScmProcessReg->TimeOfLastPing = GetTickCount();
|
|
pScmProcessReg->ProcessGUID = pActToken->ProcessGUID;
|
|
pScmProcessReg->ReadinessStatus = SERVERSTATE_SUSPENDED;
|
|
pProcess->SetProcessReg(pScmProcessReg);
|
|
|
|
hr = pProcessEntry->RegisterServer(
|
|
pProcess,
|
|
pActToken->ActivatorIPID,
|
|
NULL,
|
|
pAppidData,
|
|
SERVERSTATE_SUSPENDED,
|
|
&RegistrationToken );
|
|
|
|
pScmProcessReg->RegistrationToken = RegistrationToken;
|
|
|
|
exit:
|
|
|
|
if (pProcessEntry) pProcessEntry->Release();
|
|
if (pAppidData) delete pAppidData;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT ProcessActivatorInitializing(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
OUT error_status_t *prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
ScmProcessReg *pScmProcessReg = pProcess->GetProcessReg();
|
|
ASSERT(pScmProcessReg);
|
|
if ( ! pScmProcessReg )
|
|
return E_UNEXPECTED;
|
|
|
|
pScmProcessReg->TimeOfLastPing = GetTickCount();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT ProcessActivatorReady(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
OUT error_status_t *prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
HRESULT hr;
|
|
if (pProcess->IsInitializing())
|
|
{
|
|
// Process was running user initializaiton code,
|
|
// so signal that we've finished with that.
|
|
hr = ProcessInitializationFinished(pProcess);
|
|
}
|
|
else
|
|
{
|
|
// Normal case-- simply mark the process as
|
|
// ready-to-go.
|
|
hr = MakeProcessActive(pProcess);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT ProcessActivatorStopped(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
OUT error_status_t *prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
ScmProcessReg *pScmProcessReg = pProcess->RemoveProcessReg();
|
|
ASSERT(pScmProcessReg);
|
|
if (!pScmProcessReg )
|
|
return E_UNEXPECTED;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CServerTableEntry *pProcessEntry
|
|
= gpProcessTable->Lookup(pScmProcessReg->ProcessGUID);
|
|
|
|
if (!pProcessEntry)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto exit;
|
|
}
|
|
|
|
pProcessEntry->RevokeServer(pScmProcessReg);
|
|
|
|
exit:
|
|
|
|
if (pScmProcessReg) delete pScmProcessReg;
|
|
if (pProcessEntry) pProcessEntry->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// ProcessActivatorPaused
|
|
//
|
|
// A process activator is telling us to turn on the "paused" bit
|
|
// for its process.
|
|
//
|
|
HRESULT ProcessActivatorPaused(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
OUT error_status_t * prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
pProcess->Pause();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// ProcessActivatorResumed
|
|
//
|
|
// A process activator is telling us to turn off the "paused" bit
|
|
// for its process.
|
|
//
|
|
HRESULT ProcessActivatorResumed(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
OUT error_status_t * prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
pProcess->Resume();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// ProcessActivatorUserInitializing
|
|
//
|
|
// A process activator is telling us that it's running long-running
|
|
// code and that we might have to wait for a long time on it.
|
|
//
|
|
HRESULT ProcessActivatorUserInitializing(
|
|
IN handle_t hRpc,
|
|
IN PHPROCESS phProcess,
|
|
OUT error_status_t * prpcstat)
|
|
{
|
|
CProcess* pProcess = CheckLocalSecurity(hRpc, phProcess);
|
|
if (!pProcess)
|
|
return E_ACCESSDENIED;
|
|
|
|
if (!prpcstat)
|
|
return E_INVALIDARG;
|
|
|
|
*prpcstat = 0;
|
|
|
|
//
|
|
// Make this process active, but mark it as initializing so that
|
|
// attempts to call into it will block...
|
|
//
|
|
pProcess->BeginInit();
|
|
HRESULT hr = MakeProcessActive(pProcess);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT MakeProcessActive(
|
|
IN CProcess *pProcess
|
|
)
|
|
{
|
|
CServerTableEntry *pProcessEntry = NULL;
|
|
CAppidData *pAppidData = NULL;
|
|
CNamedObject* pRegisterEvent = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
ScmProcessReg *pScmProcessReg = pProcess->GetProcessReg();
|
|
ASSERT(pScmProcessReg);
|
|
if (!pScmProcessReg)
|
|
return E_UNEXPECTED;
|
|
|
|
pProcessEntry = gpProcessTable->Lookup(pScmProcessReg->ProcessGUID);
|
|
if (!pProcessEntry)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto exit;
|
|
}
|
|
|
|
pProcessEntry->UnsuspendServer(pScmProcessReg->RegistrationToken);
|
|
|
|
// Lookup an appiddata, from which we will get the register event
|
|
hr = LookupAppidData(pScmProcessReg->ProcessGUID,
|
|
pProcess->GetToken(),
|
|
&pAppidData);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
ASSERT(pAppidData && "LookupAppidData returned NULL AppidData");
|
|
|
|
pRegisterEvent = pAppidData->ServerRegisterEvent();
|
|
if (pRegisterEvent)
|
|
{
|
|
SetEvent( pRegisterEvent->Handle() );
|
|
pRegisterEvent->Release();
|
|
pProcess->SetProcessReadyState(SERVERSTATE_READY);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
|
|
if ( FAILED(hr) && pProcess && pProcessEntry )
|
|
pProcessEntry->RevokeServer( pScmProcessReg );
|
|
|
|
if (pProcessEntry) pProcessEntry->Release();
|
|
if (pAppidData) delete pAppidData;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT ProcessInitializationFinished(
|
|
IN CProcess *pProcess
|
|
)
|
|
{
|
|
CAppidData *pAppidData = NULL;
|
|
|
|
ScmProcessReg *pScmProcessReg = pProcess->GetProcessReg();
|
|
ASSERT(pScmProcessReg);
|
|
if ( !pScmProcessReg )
|
|
return E_UNEXPECTED;
|
|
|
|
// Initialization is finished... set the initialization event...
|
|
HRESULT hr = LookupAppidData(pScmProcessReg->ProcessGUID,
|
|
pProcess->GetToken(),
|
|
&pAppidData );
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
// Signal the initialized event.
|
|
CNamedObject* pInitializedEvent = pAppidData->ServerInitializedEvent();
|
|
if (!pInitializedEvent)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// The order of the following is important:
|
|
//
|
|
// Clear the initializing flag...
|
|
pProcess->EndInit();
|
|
|
|
// Set the initialized event...
|
|
SetEvent(pInitializedEvent->Handle());
|
|
pInitializedEvent->Release();
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
delete pAppidData;
|
|
|
|
return hr;
|
|
}
|