Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. Process.hxx
  5. Abstract:
  6. Process objects represent local clients and servers. These
  7. objects live as context handles.
  8. There are relativly few of these objects in the universe.
  9. Author:
  10. Mario Goertzel [MarioGo]
  11. Revision History:
  12. MarioGo 02-11-95 Bits 'n pieces
  13. MarioGo 01-06-96 Based on CReferencedObject
  14. Ronans 01-20-97 Added custom protseq array entries to CProcess
  15. TarunA 10-30-98 Added PID of the client process to CProcess
  16. --*/
  17. #ifndef __PROCESS_HXX
  18. #define __PROCESS_HXX
  19. typedef struct tagScmProcessRegistration {
  20. GUID ProcessGUID;
  21. DWORD RegistrationToken;
  22. DWORD ReadinessStatus;
  23. CTime TimeOfLastPing;
  24. } ScmProcessReg;
  25. void
  26. SCMRemoveRegistration(
  27. CProcess * pProcess,
  28. GUID & Guid,
  29. DWORD Reg
  30. );
  31. void
  32. SCMRemoveRegistration(
  33. ScmProcessReg * pScmProcessReg
  34. );
  35. void
  36. SCMProcessCleanup(
  37. const CProcess *pProcess
  38. );
  39. void
  40. SCMCleanupROTEntries(
  41. void *pvFirstEntry
  42. );
  43. void DragDropRunDown(
  44. void *creator
  45. );
  46. // forward decls
  47. class CClassReg;
  48. class CSCMProcessControl;
  49. // bit flags for _dwFlags of CProcess
  50. typedef enum tagPROCESSFLAGS
  51. {
  52. PROCESS_SUSPENDED = 0x0000001, // process is suspended for all activations
  53. PROCESS_RETIRED = 0x0000002, // process is retired (til it dies) for all activations
  54. PROCESS_SPI_DIRTY = 0x0000004, // process state has changed since last SCMProcessInfo was cached
  55. PROCESS_RUNDOWN = 0x0000008, // process has been rundown
  56. PROCESS_PAUSED = 0x0000010, // process has been paused
  57. PROCESS_NEEDSBINDINGS = 0x0000020, // process needs current OR bindings at first opportunity
  58. PROCESS_INITIALIZING = 0x0000040 // process is currently running long-running init code
  59. } PROCESSFLAGS;
  60. // Note on above flags: PROCESS_SUSPENDED and PROCESS_PAUSED look suspiciously identical; why
  61. // keep both? The basic reason is that the a process may only be suspended by a custom activator
  62. // (or the SCM itself, if it so decides), and that a process may only be paused by the process
  63. // itself (which in current usage means in response to a user action). We keep both flags in
  64. // order to tell the difference; certain scenarios (com+ process pooling/recycling) need the
  65. // ability to discriminate between the two cases.
  66. class CProcess : public CReferencedObject
  67. /*++
  68. Class Description:
  69. An instance of this class is created for each process
  70. using the OR as either a client or server.
  71. The process object is referenced by server OXIDs and has
  72. one implicit reference by the actual process (which is
  73. dereferenced during the context rundown). Instances of
  74. these objects are managed by the RPC runtime as context
  75. handles.
  76. Members:
  77. _pToken - A pointer to the CToken instance of the process.
  78. _csCallbackLock - use to serialize callback to LazyUseProtseq
  79. _hProcess - An RPC binding handle back to the process.
  80. _pdsaLocalBindings - The string bindings of the process, including
  81. local only protseqs
  82. _pdsaRemoteBindings - A subset of _pdsaLocalBindings not containing
  83. any local-only protseqs
  84. _blistOxids - A CBList containing pointers to the CServerOxid's
  85. owned by this process, if any.
  86. _blistOids - A CBList of pointers to CClientOid's which this
  87. process is using and referencing, if any.
  88. _listClasses - A CBList of registration handles for classes that
  89. a server process has registered.
  90. _fReadCustomProtseqs - a flag to indicate if the server has been queried
  91. for custom protseq and endpoints (specific to the server)
  92. _pcpaCustomProtseqs - a pointer to a counted array of custom protseqs
  93. _dwFlags -- state bits for this process
  94. _pSCMProcessInfo -- pointer to the current SCMProcessInfo struct for ourself
  95. _ftCreated - the filetime that this object was created.
  96. --*/
  97. {
  98. friend CSCMProcessControl;
  99. private:
  100. DWORD _cClientReferences;
  101. CToken *_pToken;
  102. WCHAR *_pwszWinstaDesktop;
  103. RPC_BINDING_HANDLE _hProcess;
  104. BOOL _fCacheFree;
  105. DUALSTRINGARRAY *_pdsaLocalBindings;
  106. DUALSTRINGARRAY *_pdsaRemoteBindings;
  107. ULONG _ulClasses;
  108. ScmProcessReg *_pScmProcessReg;
  109. DUALSTRINGARRAY *_pdsaCustomProtseqs;
  110. void *_pvRunAsHandle;
  111. DWORD _procID;
  112. volatile DWORD _dwFlags;
  113. void* _pSCMProcessInfo;
  114. GUID _guidProcessIdentifier;
  115. HANDLE _hProcHandle;
  116. FILETIME _ftCreated;
  117. DWORD64 _dwCurrentBindingsID;
  118. DWORD _dwAsyncUpdatesOutstanding; // for debug purposes?
  119. void *_pvFirstROTEntry;
  120. BOOL _fReadCustomProtseqs;
  121. CBList _blistOxids;
  122. CBList _blistOids;
  123. CList _listClasses;
  124. DWORD _cDropTargets;
  125. #if DBG
  126. // Debug members used to monitor and track rundown callbacks
  127. ULONG _cRundowns;
  128. CTime _timeFirstRundown;
  129. #endif
  130. RPC_BINDING_HANDLE CreateBindingHandle(void);
  131. BOOL EnsureBindingHandle();
  132. // These two functions should be used in tandem.
  133. RPC_BINDING_HANDLE AllocateBinding();
  134. void FreeBinding(RPC_BINDING_HANDLE);
  135. static
  136. void RPC_ENTRY AsyncRpcNotification(RPC_ASYNC_STATE* pAsync,
  137. void* pContext,
  138. RPC_ASYNC_EVENT Event);
  139. void BindingsUpdateNotify(RPC_BINDING_HANDLE hBinding,
  140. DWORD64 dwBindingsID,
  141. DUALSTRINGARRAY* pdsaNewBindings,
  142. DUALSTRINGARRAY* pdsaSecBindings,
  143. HRESULT hrReturn);
  144. static
  145. void RPC_ENTRY AsyncRundownReturnNotification(RPC_ASYNC_STATE* pAsync,
  146. void* pContext,
  147. RPC_ASYNC_EVENT Event);
  148. void RundownOidNotify(CServerOxid* pOwningOxid,
  149. ULONG cOids,
  150. CServerOid* aOids[],
  151. BYTE aRundownStatus[],
  152. HRESULT hrReturn);
  153. static
  154. void ExamineRpcAsyncCompleteCallReturnCode(RPC_STATUS status);
  155. void FlagsOn(DWORD dwOn);
  156. void FlagsOff(DWORD dwOff);
  157. public:
  158. CProcess(IN CToken*& pToken,
  159. IN WCHAR *pwszWinstaDesktop,
  160. IN DWORD procID,
  161. OUT ORSTATUS &status);
  162. ~CProcess();
  163. RPC_STATUS ProcessBindings(DUALSTRINGARRAY *,
  164. DUALSTRINGARRAY *);
  165. DUALSTRINGARRAY *GetLocalBindings(void);
  166. DUALSTRINGARRAY *GetRemoteBindings(void);
  167. RPC_BINDING_HANDLE GetBindingHandle();
  168. ORSTATUS AddOxid(CServerOxid *);
  169. BOOL RemoveOxid(CServerOxid *);
  170. ORSTATUS AddRemoteOxid(CClientOxid *);
  171. void RemoveRemoteOxid(CClientOxid *);
  172. BOOL IsOwner(CServerOxid *);
  173. ORSTATUS AddOid(CClientOid *);
  174. CClientOid *RemoveOid(CClientOid *);
  175. // These are methods to record per-class SCM registrations
  176. // in traditional local servers and services
  177. void AddClassReg(GUID & Guid, DWORD Reg);
  178. void RemoveClassReg(DWORD Reg);
  179. void RevokeClassRegs();
  180. // These are methods to record per-process SCM registration info
  181. // for the new COM+ unified surrogate for startup, shutdown and rundown
  182. void SetProcessReg(ScmProcessReg *pProcessReg);
  183. ScmProcessReg* GetProcessReg();
  184. ScmProcessReg* RemoveProcessReg();
  185. void RevokeProcessReg();
  186. void SetProcessReadyState(DWORD dwState);
  187. RPC_STATUS RundownOids(RPC_BINDING_HANDLE hRpc,
  188. CServerOxid* pOwningOxid,
  189. ULONG cOids,
  190. CServerOid* aOids[]);
  191. ORSTATUS UseProtseqIfNeeded(USHORT cClientProtseqs, USHORT aProtseqs[]);
  192. ORSTATUS UpdateResolverBindings(DWORD64 dwBindingsID, DUALSTRINGARRAY* pdsaResolverBindings);
  193. void Rundown();
  194. BOOL HasBeenRundown() { return (_dwFlags & PROCESS_RUNDOWN); };
  195. void NotifyRPCRundown() { FlagsOn(PROCESS_RUNDOWN); };
  196. CToken *GetToken() {
  197. return(_pToken);
  198. }
  199. WCHAR *WinstaDesktop() {
  200. return(_pwszWinstaDesktop);
  201. }
  202. void ClientReference() {
  203. InterlockedIncrement((PLONG)&_cClientReferences);
  204. }
  205. DWORD ClientRelease()
  206. {
  207. return InterlockedDecrement((PLONG)&_cClientReferences);
  208. }
  209. DWORD GetPID() { return _procID; }
  210. void SetRunAsHandle(void *pvRunAsHandle);
  211. HANDLE GetProcessHandle()
  212. {
  213. return _hProcHandle;
  214. }
  215. BOOL SetProcessHandle(HANDLE hProcHandle, DWORD dwLaunchedPID);
  216. GUID* GetGuidProcessIdentifier() { return &_guidProcessIdentifier; };
  217. void Cleanup();
  218. // Not sure yet if (un)suspending an already (un)suspended process
  219. // is a valid or possible thing to do. Assert on these two cases.
  220. void Suspend() { ASSERT(!IsSuspended()); FlagsOn(PROCESS_SUSPENDED | PROCESS_SPI_DIRTY); }
  221. void Unsuspend() { ASSERT(IsSuspended()); FlagsOff(PROCESS_SUSPENDED); FlagsOn(PROCESS_SPI_DIRTY); }
  222. BOOL IsSuspended() { return (_dwFlags & PROCESS_SUSPENDED); }
  223. // Note: no accessor method provided to "un-retire" a process.
  224. void Retire();
  225. BOOL IsRetired() { return (_dwFlags & PROCESS_RETIRED); }
  226. void Pause() { ASSERT(!IsPaused()); FlagsOn(PROCESS_PAUSED | PROCESS_SPI_DIRTY); }
  227. void Resume() { ASSERT(IsPaused()); FlagsOff(PROCESS_PAUSED); FlagsOn(PROCESS_SPI_DIRTY); }
  228. BOOL IsPaused() { return (_dwFlags & PROCESS_PAUSED); }
  229. void BeginInit() { FlagsOn(PROCESS_INITIALIZING | PROCESS_SPI_DIRTY); }
  230. void EndInit() { FlagsOff(PROCESS_INITIALIZING); FlagsOn(PROCESS_SPI_DIRTY); }
  231. BOOL IsInitializing() { return (_dwFlags & PROCESS_INITIALIZING); }
  232. // Although we track the paused bit for the benefit of any custom activators that might care about
  233. // it, it does not influence our choice of servers. So if two potential servers are running, and
  234. // one is paused, then to the scm both appear equally suitable. We have to do it this way to
  235. // support various com+ scenarios.
  236. BOOL AvailableForActivations() { return !(_dwFlags & (PROCESS_SUSPENDED | PROCESS_RETIRED)); }
  237. // Returns TRUE if this process needs updated bindings.
  238. BOOL NeedsORBindings() { return _dwFlags & PROCESS_NEEDSBINDINGS; };
  239. void BindingsUpdated() { FlagsOff(PROCESS_NEEDSBINDINGS); };
  240. const FILETIME* GetFileTimeCreated() { return &_ftCreated; }
  241. BOOL SPIDirty() { return _dwFlags & PROCESS_SPI_DIRTY; }
  242. HRESULT SetSCMProcessInfo(void* pSPI);
  243. void* GetSCMProcessInfo()
  244. {
  245. //ASSERT(gpServerLock->HeldSharedOrExclusive();
  246. // should not be called unless we are not not dirty
  247. ASSERT(_pSCMProcessInfo && !(_dwFlags & (PROCESS_SPI_DIRTY | PROCESS_RUNDOWN)));
  248. return _pSCMProcessInfo;
  249. };
  250. void SetFirstROTEntry(void *pvFirstROTEntry)
  251. {
  252. ASSERT(gpServerLock->HeldExclusive());
  253. _pvFirstROTEntry = pvFirstROTEntry;
  254. }
  255. void* GetFirstROTEntry()
  256. {
  257. return _pvFirstROTEntry;
  258. }
  259. void IncDropTargets() { InterlockedIncrement((PLONG)&_cDropTargets); }
  260. void DecDropTargets() { ASSERT (_cDropTargets>0); InterlockedDecrement((PLONG)&_cDropTargets); }
  261. };
  262. class CClassReg : public CListElement
  263. {
  264. public :
  265. GUID _Guid;
  266. DWORD _Reg;
  267. CClassReg( GUID & Guid, DWORD reg ) : _Guid(Guid), _Reg(reg) {}
  268. };
  269. extern CRITICAL_SECTION gcsFastProcessLock;
  270. extern CBList *gpProcessList;
  271. extern CSharedLock* gpProcessListLock;
  272. CProcess *ReferenceProcess(PVOID key, BOOL fNotContext);
  273. void ReleaseProcess(CProcess *pProcess);
  274. BOOL VerifyNewProcess(DWORD dwPID);
  275. #endif // __PROCESS_HXX