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