windows-nt/Source/XPSP1/NT/com/ole32/dcomss/olescm/macif.cxx
2020-09-26 16:20:57 +08:00

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;
}