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.
386 lines
12 KiB
386 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Process.hxx
|
|
|
|
Abstract:
|
|
|
|
Process objects represent local clients and servers. These
|
|
objects live as context handles.
|
|
|
|
There are relativly few of these objects in the universe.
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 02-11-95 Bits 'n pieces
|
|
MarioGo 01-06-96 Based on CReferencedObject
|
|
Ronans 01-20-97 Added custom protseq array entries to CProcess
|
|
TarunA 10-30-98 Added PID of the client process to CProcess
|
|
|
|
--*/
|
|
|
|
#ifndef __PROCESS_HXX
|
|
#define __PROCESS_HXX
|
|
|
|
typedef struct tagScmProcessRegistration {
|
|
GUID ProcessGUID;
|
|
DWORD RegistrationToken;
|
|
DWORD ReadinessStatus;
|
|
CTime TimeOfLastPing;
|
|
} ScmProcessReg;
|
|
|
|
void
|
|
SCMRemoveRegistration(
|
|
CProcess * pProcess,
|
|
GUID & Guid,
|
|
DWORD Reg
|
|
);
|
|
|
|
void
|
|
SCMRemoveRegistration(
|
|
ScmProcessReg * pScmProcessReg
|
|
);
|
|
|
|
void
|
|
SCMProcessCleanup(
|
|
const CProcess *pProcess
|
|
);
|
|
|
|
void
|
|
SCMCleanupROTEntries(
|
|
void *pvFirstEntry
|
|
);
|
|
|
|
void DragDropRunDown(
|
|
void *creator
|
|
);
|
|
|
|
// forward decls
|
|
class CClassReg;
|
|
class CSCMProcessControl;
|
|
|
|
// bit flags for _dwFlags of CProcess
|
|
typedef enum tagPROCESSFLAGS
|
|
{
|
|
PROCESS_SUSPENDED = 0x0000001, // process is suspended for all activations
|
|
PROCESS_RETIRED = 0x0000002, // process is retired (til it dies) for all activations
|
|
PROCESS_SPI_DIRTY = 0x0000004, // process state has changed since last SCMProcessInfo was cached
|
|
PROCESS_RUNDOWN = 0x0000008, // process has been rundown
|
|
PROCESS_PAUSED = 0x0000010, // process has been paused
|
|
PROCESS_NEEDSBINDINGS = 0x0000020, // process needs current OR bindings at first opportunity
|
|
PROCESS_INITIALIZING = 0x0000040 // process is currently running long-running init code
|
|
} PROCESSFLAGS;
|
|
|
|
|
|
// Note on above flags: PROCESS_SUSPENDED and PROCESS_PAUSED look suspiciously identical; why
|
|
// keep both? The basic reason is that the a process may only be suspended by a custom activator
|
|
// (or the SCM itself, if it so decides), and that a process may only be paused by the process
|
|
// itself (which in current usage means in response to a user action). We keep both flags in
|
|
// order to tell the difference; certain scenarios (com+ process pooling/recycling) need the
|
|
// ability to discriminate between the two cases.
|
|
|
|
class CProcess : public CReferencedObject
|
|
/*++
|
|
|
|
Class Description:
|
|
|
|
An instance of this class is created for each process
|
|
using the OR as either a client or server.
|
|
|
|
The process object is referenced by server OXIDs and has
|
|
one implicit reference by the actual process (which is
|
|
dereferenced during the context rundown). Instances of
|
|
these objects are managed by the RPC runtime as context
|
|
handles.
|
|
|
|
Members:
|
|
|
|
_pToken - A pointer to the CToken instance of the process.
|
|
|
|
_csCallbackLock - use to serialize callback to LazyUseProtseq
|
|
|
|
_hProcess - An RPC binding handle back to the process.
|
|
|
|
_pdsaLocalBindings - The string bindings of the process, including
|
|
local only protseqs
|
|
|
|
_pdsaRemoteBindings - A subset of _pdsaLocalBindings not containing
|
|
any local-only protseqs
|
|
|
|
_blistOxids - A CBList containing pointers to the CServerOxid's
|
|
owned by this process, if any.
|
|
|
|
_blistOids - A CBList of pointers to CClientOid's which this
|
|
process is using and referencing, if any.
|
|
|
|
_listClasses - A CBList of registration handles for classes that
|
|
a server process has registered.
|
|
|
|
_fReadCustomProtseqs - a flag to indicate if the server has been queried
|
|
for custom protseq and endpoints (specific to the server)
|
|
|
|
_pcpaCustomProtseqs - a pointer to a counted array of custom protseqs
|
|
|
|
_dwFlags -- state bits for this process
|
|
|
|
_pSCMProcessInfo -- pointer to the current SCMProcessInfo struct for ourself
|
|
|
|
_ftCreated - the filetime that this object was created.
|
|
|
|
--*/
|
|
{
|
|
friend CSCMProcessControl;
|
|
|
|
private:
|
|
|
|
DWORD _cClientReferences;
|
|
|
|
CToken *_pToken;
|
|
WCHAR *_pwszWinstaDesktop;
|
|
RPC_BINDING_HANDLE _hProcess;
|
|
BOOL _fCacheFree;
|
|
DUALSTRINGARRAY *_pdsaLocalBindings;
|
|
DUALSTRINGARRAY *_pdsaRemoteBindings;
|
|
ULONG _ulClasses;
|
|
ScmProcessReg *_pScmProcessReg;
|
|
DUALSTRINGARRAY *_pdsaCustomProtseqs;
|
|
void *_pvRunAsHandle;
|
|
DWORD _procID;
|
|
volatile DWORD _dwFlags;
|
|
void* _pSCMProcessInfo;
|
|
GUID _guidProcessIdentifier;
|
|
HANDLE _hProcHandle;
|
|
FILETIME _ftCreated;
|
|
DWORD64 _dwCurrentBindingsID;
|
|
DWORD _dwAsyncUpdatesOutstanding; // for debug purposes?
|
|
|
|
void *_pvFirstROTEntry;
|
|
|
|
BOOL _fReadCustomProtseqs;
|
|
CBList _blistOxids;
|
|
CBList _blistOids;
|
|
CList _listClasses;
|
|
|
|
DWORD _cDropTargets;
|
|
#if DBG
|
|
// Debug members used to monitor and track rundown callbacks
|
|
ULONG _cRundowns;
|
|
CTime _timeFirstRundown;
|
|
#endif
|
|
|
|
RPC_BINDING_HANDLE CreateBindingHandle(void);
|
|
BOOL EnsureBindingHandle();
|
|
|
|
// These two functions should be used in tandem.
|
|
RPC_BINDING_HANDLE AllocateBinding();
|
|
void FreeBinding(RPC_BINDING_HANDLE);
|
|
|
|
static
|
|
void RPC_ENTRY AsyncRpcNotification(RPC_ASYNC_STATE* pAsync,
|
|
void* pContext,
|
|
RPC_ASYNC_EVENT Event);
|
|
|
|
void BindingsUpdateNotify(RPC_BINDING_HANDLE hBinding,
|
|
DWORD64 dwBindingsID,
|
|
DUALSTRINGARRAY* pdsaNewBindings,
|
|
DUALSTRINGARRAY* pdsaSecBindings,
|
|
HRESULT hrReturn);
|
|
|
|
static
|
|
void RPC_ENTRY AsyncRundownReturnNotification(RPC_ASYNC_STATE* pAsync,
|
|
void* pContext,
|
|
RPC_ASYNC_EVENT Event);
|
|
|
|
void RundownOidNotify(CServerOxid* pOwningOxid,
|
|
ULONG cOids,
|
|
CServerOid* aOids[],
|
|
BYTE aRundownStatus[],
|
|
HRESULT hrReturn);
|
|
|
|
static
|
|
void ExamineRpcAsyncCompleteCallReturnCode(RPC_STATUS status);
|
|
|
|
void FlagsOn(DWORD dwOn);
|
|
void FlagsOff(DWORD dwOff);
|
|
|
|
public:
|
|
|
|
CProcess(IN CToken*& pToken,
|
|
IN WCHAR *pwszWinstaDesktop,
|
|
IN DWORD procID,
|
|
OUT ORSTATUS &status);
|
|
|
|
~CProcess();
|
|
|
|
RPC_STATUS ProcessBindings(DUALSTRINGARRAY *,
|
|
DUALSTRINGARRAY *);
|
|
|
|
DUALSTRINGARRAY *GetLocalBindings(void);
|
|
|
|
DUALSTRINGARRAY *GetRemoteBindings(void);
|
|
|
|
RPC_BINDING_HANDLE GetBindingHandle();
|
|
|
|
ORSTATUS AddOxid(CServerOxid *);
|
|
|
|
BOOL RemoveOxid(CServerOxid *);
|
|
|
|
ORSTATUS AddRemoteOxid(CClientOxid *);
|
|
|
|
void RemoveRemoteOxid(CClientOxid *);
|
|
|
|
BOOL IsOwner(CServerOxid *);
|
|
|
|
ORSTATUS AddOid(CClientOid *);
|
|
|
|
CClientOid *RemoveOid(CClientOid *);
|
|
|
|
// These are methods to record per-class SCM registrations
|
|
// in traditional local servers and services
|
|
void AddClassReg(GUID & Guid, DWORD Reg);
|
|
|
|
void RemoveClassReg(DWORD Reg);
|
|
|
|
void RevokeClassRegs();
|
|
|
|
// These are methods to record per-process SCM registration info
|
|
// for the new COM+ unified surrogate for startup, shutdown and rundown
|
|
void SetProcessReg(ScmProcessReg *pProcessReg);
|
|
|
|
ScmProcessReg* GetProcessReg();
|
|
|
|
ScmProcessReg* RemoveProcessReg();
|
|
|
|
void RevokeProcessReg();
|
|
|
|
void SetProcessReadyState(DWORD dwState);
|
|
|
|
RPC_STATUS RundownOids(RPC_BINDING_HANDLE hRpc,
|
|
CServerOxid* pOwningOxid,
|
|
ULONG cOids,
|
|
CServerOid* aOids[]);
|
|
|
|
ORSTATUS UseProtseqIfNeeded(USHORT cClientProtseqs, USHORT aProtseqs[]);
|
|
|
|
ORSTATUS UpdateResolverBindings(DWORD64 dwBindingsID, DUALSTRINGARRAY* pdsaResolverBindings);
|
|
|
|
void Rundown();
|
|
BOOL HasBeenRundown() { return (_dwFlags & PROCESS_RUNDOWN); };
|
|
void NotifyRPCRundown() { FlagsOn(PROCESS_RUNDOWN); };
|
|
|
|
CToken *GetToken() {
|
|
return(_pToken);
|
|
}
|
|
|
|
WCHAR *WinstaDesktop() {
|
|
return(_pwszWinstaDesktop);
|
|
}
|
|
|
|
void ClientReference() {
|
|
InterlockedIncrement((PLONG)&_cClientReferences);
|
|
}
|
|
|
|
DWORD ClientRelease()
|
|
{
|
|
return InterlockedDecrement((PLONG)&_cClientReferences);
|
|
}
|
|
|
|
DWORD GetPID() { return _procID; }
|
|
|
|
void SetRunAsHandle(void *pvRunAsHandle);
|
|
HANDLE GetProcessHandle()
|
|
{
|
|
return _hProcHandle;
|
|
}
|
|
|
|
BOOL SetProcessHandle(HANDLE hProcHandle, DWORD dwLaunchedPID);
|
|
|
|
GUID* GetGuidProcessIdentifier() { return &_guidProcessIdentifier; };
|
|
|
|
void Cleanup();
|
|
|
|
// Not sure yet if (un)suspending an already (un)suspended process
|
|
// is a valid or possible thing to do. Assert on these two cases.
|
|
void Suspend() { ASSERT(!IsSuspended()); FlagsOn(PROCESS_SUSPENDED | PROCESS_SPI_DIRTY); }
|
|
void Unsuspend() { ASSERT(IsSuspended()); FlagsOff(PROCESS_SUSPENDED); FlagsOn(PROCESS_SPI_DIRTY); }
|
|
BOOL IsSuspended() { return (_dwFlags & PROCESS_SUSPENDED); }
|
|
|
|
// Note: no accessor method provided to "un-retire" a process.
|
|
void Retire();
|
|
BOOL IsRetired() { return (_dwFlags & PROCESS_RETIRED); }
|
|
|
|
void Pause() { ASSERT(!IsPaused()); FlagsOn(PROCESS_PAUSED | PROCESS_SPI_DIRTY); }
|
|
void Resume() { ASSERT(IsPaused()); FlagsOff(PROCESS_PAUSED); FlagsOn(PROCESS_SPI_DIRTY); }
|
|
BOOL IsPaused() { return (_dwFlags & PROCESS_PAUSED); }
|
|
|
|
void BeginInit() { FlagsOn(PROCESS_INITIALIZING | PROCESS_SPI_DIRTY); }
|
|
void EndInit() { FlagsOff(PROCESS_INITIALIZING); FlagsOn(PROCESS_SPI_DIRTY); }
|
|
BOOL IsInitializing() { return (_dwFlags & PROCESS_INITIALIZING); }
|
|
|
|
// Although we track the paused bit for the benefit of any custom activators that might care about
|
|
// it, it does not influence our choice of servers. So if two potential servers are running, and
|
|
// one is paused, then to the scm both appear equally suitable. We have to do it this way to
|
|
// support various com+ scenarios.
|
|
BOOL AvailableForActivations() { return !(_dwFlags & (PROCESS_SUSPENDED | PROCESS_RETIRED)); }
|
|
|
|
// Returns TRUE if this process needs updated bindings.
|
|
BOOL NeedsORBindings() { return _dwFlags & PROCESS_NEEDSBINDINGS; };
|
|
void BindingsUpdated() { FlagsOff(PROCESS_NEEDSBINDINGS); };
|
|
|
|
const FILETIME* GetFileTimeCreated() { return &_ftCreated; }
|
|
|
|
BOOL SPIDirty() { return _dwFlags & PROCESS_SPI_DIRTY; }
|
|
|
|
HRESULT SetSCMProcessInfo(void* pSPI);
|
|
|
|
void* GetSCMProcessInfo()
|
|
{
|
|
//ASSERT(gpServerLock->HeldSharedOrExclusive();
|
|
|
|
// should not be called unless we are not not dirty
|
|
ASSERT(_pSCMProcessInfo && !(_dwFlags & (PROCESS_SPI_DIRTY | PROCESS_RUNDOWN)));
|
|
return _pSCMProcessInfo;
|
|
};
|
|
|
|
void SetFirstROTEntry(void *pvFirstROTEntry)
|
|
{
|
|
ASSERT(gpServerLock->HeldExclusive());
|
|
_pvFirstROTEntry = pvFirstROTEntry;
|
|
}
|
|
|
|
void* GetFirstROTEntry()
|
|
{
|
|
return _pvFirstROTEntry;
|
|
}
|
|
|
|
void IncDropTargets() { InterlockedIncrement((PLONG)&_cDropTargets); }
|
|
void DecDropTargets() { ASSERT (_cDropTargets>0); InterlockedDecrement((PLONG)&_cDropTargets); }
|
|
|
|
};
|
|
|
|
class CClassReg : public CListElement
|
|
{
|
|
public :
|
|
GUID _Guid;
|
|
DWORD _Reg;
|
|
|
|
CClassReg( GUID & Guid, DWORD reg ) : _Guid(Guid), _Reg(reg) {}
|
|
};
|
|
|
|
extern CRITICAL_SECTION gcsFastProcessLock;
|
|
|
|
extern CBList *gpProcessList;
|
|
extern CSharedLock* gpProcessListLock;
|
|
|
|
CProcess *ReferenceProcess(PVOID key, BOOL fNotContext);
|
|
void ReleaseProcess(CProcess *pProcess);
|
|
BOOL VerifyNewProcess(DWORD dwPID);
|
|
|
|
#endif // __PROCESS_HXX
|