397 lines
9.6 KiB
C++
397 lines
9.6 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
CServerTableEntry *pProcessEntry = NULL;
|
||
|
CAppidData *pAppidData = NULL;
|
||
|
ScmProcessReg *pScmProcessReg = NULL;
|
||
|
DWORD RegistrationToken = 0;
|
||
|
BOOL fCallerOK = FALSE;
|
||
|
|
||
|
DWORD AppIDFlags = 0;
|
||
|
|
||
|
// Lookup appid info from appropriate registry side
|
||
|
#if defined(_WIN64)
|
||
|
AppIDFlags = pProcess->Is64Bit() ? CAT_REG64_ONLY : CAT_REG32_ONLY;
|
||
|
#endif
|
||
|
|
||
|
hr = LookupAppidData(
|
||
|
pActToken->ProcessGUID,
|
||
|
pProcess->GetToken(),
|
||
|
AppIDFlags,
|
||
|
&pAppidData );
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
Win4Assert(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;
|
||
|
pScmProcessReg->AppIDFlags = AppIDFlags;
|
||
|
pProcess->SetProcessReg(pScmProcessReg);
|
||
|
|
||
|
hr = pProcessEntry->RegisterServer(
|
||
|
pProcess,
|
||
|
pActToken->ActivatorIPID,
|
||
|
NULL,
|
||
|
pAppidData,
|
||
|
SERVERSTATE_SUSPENDED,
|
||
|
&RegistrationToken );
|
||
|
|
||
|
pScmProcessReg->RegistrationToken = RegistrationToken;
|
||
|
|
||
|
exit:
|
||
|
|
||
|
if (pProcessEntry) pProcessEntry->Release();
|
||
|
if (pProcess) ReleaseProcess( pProcess );
|
||
|
if (pAppidData) delete pAppidData;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT ProcessActivatorInitializing(
|
||
|
IN handle_t hRpc,
|
||
|
IN PHPROCESS phProcess,
|
||
|
OUT error_status_t *prpcstat)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
ScmProcessReg *pScmProcessReg = pProcess->GetProcessReg();
|
||
|
ASSERT(pScmProcessReg);
|
||
|
if ( ! pScmProcessReg )
|
||
|
{
|
||
|
ReleaseProcess( pProcess );
|
||
|
return E_UNEXPECTED;
|
||
|
}
|
||
|
|
||
|
pScmProcessReg->TimeOfLastPing = GetTickCount();
|
||
|
|
||
|
ReleaseProcess( pProcess );
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT ProcessActivatorReady(
|
||
|
IN handle_t hRpc,
|
||
|
IN PHPROCESS phProcess,
|
||
|
OUT error_status_t *prpcstat)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
if (pProcess) ReleaseProcess( pProcess );
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT ProcessActivatorStopped(
|
||
|
IN handle_t hRpc,
|
||
|
IN PHPROCESS phProcess,
|
||
|
OUT error_status_t *prpcstat)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
|
||
|
ScmProcessReg *pScmProcessReg = pProcess->RemoveProcessReg();
|
||
|
ASSERT(pScmProcessReg);
|
||
|
if ( ! pScmProcessReg )
|
||
|
{
|
||
|
ReleaseProcess( pProcess );
|
||
|
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();
|
||
|
if (pProcess) ReleaseProcess( pProcess );
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
pProcess->Pause();
|
||
|
|
||
|
ReleaseProcess(pProcess);
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
pProcess->Resume();
|
||
|
|
||
|
ReleaseProcess(pProcess);
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
CheckLocalCall( hRpc ); // raises exception if not
|
||
|
|
||
|
*prpcstat = 0; // we got here so we are OK
|
||
|
|
||
|
CProcess *pProcess = ReferenceProcess( phProcess, TRUE );
|
||
|
|
||
|
if ( ! pProcess )
|
||
|
return E_ACCESSDENIED;
|
||
|
|
||
|
//
|
||
|
// Make this process active, but mark it as initializing so that
|
||
|
// attempts to call into it will block...
|
||
|
//
|
||
|
pProcess->BeginInit();
|
||
|
HRESULT hr = MakeProcessActive(pProcess);
|
||
|
|
||
|
ReleaseProcess( pProcess );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT MakeProcessActive(
|
||
|
IN CProcess *pProcess
|
||
|
)
|
||
|
{
|
||
|
CServerTableEntry *pProcessEntry = NULL;
|
||
|
CAppidData *pAppidData = NULL;
|
||
|
HANDLE hRegisterEvent = 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(),
|
||
|
pScmProcessReg->AppIDFlags,
|
||
|
&pAppidData);
|
||
|
if (FAILED(hr))
|
||
|
goto exit;
|
||
|
|
||
|
Win4Assert(pAppidData && "LookupAppidData returned NULL AppidData");
|
||
|
|
||
|
hRegisterEvent = pAppidData->ServerRegisterEvent();
|
||
|
if ( hRegisterEvent )
|
||
|
{
|
||
|
SetEvent( hRegisterEvent );
|
||
|
CloseHandle( hRegisterEvent );
|
||
|
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(),
|
||
|
pScmProcessReg->AppIDFlags,
|
||
|
&pAppidData );
|
||
|
if (FAILED(hr))
|
||
|
goto exit;
|
||
|
|
||
|
// Signal the initialized event.
|
||
|
HANDLE hInitializedEvent = pAppidData->ServerInitializedEvent();
|
||
|
if (!hInitializedEvent)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
// The order of the following is important:
|
||
|
//
|
||
|
// Clear the initializing flag...
|
||
|
pProcess->EndInit();
|
||
|
|
||
|
// Set the initialized event...
|
||
|
SetEvent(hInitializedEvent);
|
||
|
CloseHandle(hInitializedEvent);
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
exit:
|
||
|
delete pAppidData;
|
||
|
|
||
|
return hr;
|
||
|
}
|