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.

612 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. apool.h
  5. Abstract:
  6. The public definition of app pool interfaces.
  7. Author:
  8. Paul McDaniel (paulmcd) 28-Jan-1999
  9. Revision History:
  10. --*/
  11. #ifndef _APOOL_H_
  12. #define _APOOL_H_
  13. //
  14. // Kernel mode mappings to the user mode set defined in ulapi.h
  15. //
  16. //
  17. // Constants.
  18. //
  19. #define UL_MAX_APP_POOL_NAME_SIZE (MAX_PATH*sizeof(WCHAR))
  20. #define UL_MAX_REQUESTS_QUEUED 0xFFFF
  21. #define UL_MIN_REQUESTS_QUEUED 10
  22. //
  23. // Forwarders.
  24. //
  25. typedef struct _UL_INTERNAL_REQUEST *PUL_INTERNAL_REQUEST;
  26. typedef struct _UL_HTTP_CONNECTION *PUL_HTTP_CONNECTION;
  27. typedef struct _UL_CONFIG_GROUP_OBJECT *PUL_CONFIG_GROUP_OBJECT;
  28. //
  29. // This structure represents an internal app pool object
  30. //
  31. #define IS_VALID_AP_OBJECT(pObject) \
  32. (HAS_VALID_SIGNATURE(pObject, UL_APP_POOL_OBJECT_POOL_TAG) \
  33. && ((pObject)->RefCount > 0))
  34. typedef struct _UL_APP_POOL_OBJECT
  35. {
  36. //
  37. // NonPagedPool
  38. //
  39. //
  40. // Lock that protects NewRequestQueue and PendingRequestQueue
  41. // for each attached process and queue state of the request
  42. //
  43. // ensure it on cache-line and use InStackQueuedSpinLock for
  44. // better performance
  45. //
  46. UL_SPIN_LOCK SpinLock;
  47. //
  48. // UL_APP_POOL_OBJECT_POOL_TAG
  49. //
  50. ULONG Signature;
  51. //
  52. // Ref count for this app pool
  53. //
  54. LONG RefCount;
  55. //
  56. // links all apool objects, anchored by g_AppPoolListHead
  57. //
  58. LIST_ENTRY ListEntry;
  59. //
  60. // A apool wide new request list (when no irps are available)
  61. //
  62. LIST_ENTRY NewRequestHead;
  63. ULONG RequestCount;
  64. ULONG MaxRequests;
  65. //
  66. // the demand start irp (OPTIONAL)
  67. //
  68. PIRP pDemandStartIrp;
  69. PEPROCESS pDemandStartProcess;
  70. //
  71. // the control channel associated with this app pool
  72. //
  73. PUL_CONTROL_CHANNEL pControlChannel;
  74. //
  75. // the list of processes bound to this app pool
  76. //
  77. LIST_ENTRY ProcessListHead;
  78. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  79. //
  80. // the length of pName
  81. //
  82. USHORT NameLength;
  83. //
  84. // number of active processes in the AppPool, used to decide if binding
  85. // is necessary
  86. //
  87. ULONG NumberActiveProcesses;
  88. //
  89. // Only route requests to this AppPool if it's marked active
  90. //
  91. HTTP_APP_POOL_ENABLED_STATE State;
  92. //
  93. // How sophisticated is the load balancer routing requests to the apppool?
  94. //
  95. HTTP_LOAD_BALANCER_CAPABILITIES LoadBalancerCapability;
  96. //
  97. // the apool's name
  98. //
  99. WCHAR pName[0];
  100. } UL_APP_POOL_OBJECT, *PUL_APP_POOL_OBJECT;
  101. //
  102. // The structure representing a process bound to an app pool.
  103. //
  104. #define IS_VALID_AP_PROCESS(pObject) \
  105. HAS_VALID_SIGNATURE(pObject, UL_APP_POOL_PROCESS_POOL_TAG)
  106. typedef struct _UL_APP_POOL_PROCESS
  107. {
  108. //
  109. // NonPagedPool
  110. //
  111. //
  112. // UL_APP_POOL_PROCESS_POOL_TAG
  113. //
  114. ULONG Signature;
  115. //
  116. // Ref count for this app pool process. This is more like an outstanding
  117. // io count rather than the refcount. The process is still get cleaned
  118. // with ULClose call. But completion for the cleanup delays until all
  119. // send io exhaust on the process.
  120. //
  121. LONG RefCount;
  122. //
  123. // CleanUpIrp will be completed when all the IO exhaust on
  124. // the cleanup pending process.
  125. //
  126. PIRP pCleanupIrp;
  127. //
  128. // set if we are in cleanup. You must check this flag before attaching
  129. // any IRPs to the process.
  130. //
  131. ULONG InCleanup : 1;
  132. //
  133. // set if process is attached with the HTTP_OPTION_CONTROLLER option
  134. //
  135. ULONG Controller : 1;
  136. //
  137. // used to link into the apool object
  138. //
  139. LIST_ENTRY ListEntry;
  140. //
  141. // points to the app pool this process belongs
  142. //
  143. PUL_APP_POOL_OBJECT pAppPool;
  144. //
  145. // a list of pending IRP(s) waiting to receive new requests
  146. //
  147. LIST_ENTRY NewIrpHead;
  148. //
  149. // links requests that would not fit in a irp buffer and need to wait for
  150. // the larger buffer
  151. //
  152. // and
  153. //
  154. // requests that this process is working on and need
  155. // i/o cancellation if the process detaches from the apool
  156. //
  157. LIST_ENTRY PendingRequestHead;
  158. //
  159. // Pointer to the actual process.
  160. //
  161. PEPROCESS pProcess;
  162. //
  163. // List of pending "wait for disconnect" IRPs.
  164. //
  165. UL_NOTIFY_HEAD WaitForDisconnectHead;
  166. } UL_APP_POOL_PROCESS, *PUL_APP_POOL_PROCESS;
  167. // IRQL == PASSIVE_LEVEL
  168. //
  169. NTSTATUS
  170. UlAttachProcessToAppPool(
  171. IN PWCHAR pName OPTIONAL,
  172. IN USHORT NameLength,
  173. IN BOOLEAN Create,
  174. IN PACCESS_STATE pAccessState,
  175. IN ACCESS_MASK DesiredAccess,
  176. IN KPROCESSOR_MODE RequestorMode,
  177. OUT PUL_APP_POOL_PROCESS * ppProcess
  178. );
  179. // IRQL == PASSIVE_LEVEL
  180. //
  181. NTSTATUS
  182. UlDetachProcessFromAppPool(
  183. IN PIRP pCleanupIrp,
  184. IN PIO_STACK_LOCATION pCleanupIrpSp
  185. );
  186. VOID
  187. UlShutdownAppPoolProcess(
  188. IN PUL_APP_POOL_PROCESS pProcess
  189. );
  190. // IRQL == PASSIVE_LEVEL
  191. //
  192. #if REFERENCE_DEBUG
  193. VOID
  194. UlReferenceAppPool(
  195. IN PUL_APP_POOL_OBJECT pAppPool
  196. REFERENCE_DEBUG_FORMAL_PARAMS
  197. );
  198. #else
  199. __inline
  200. VOID
  201. UlReferenceAppPool(
  202. IN PUL_APP_POOL_OBJECT pAppPool
  203. )
  204. {
  205. InterlockedIncrement(&pAppPool->RefCount);
  206. }
  207. #endif
  208. #define REFERENCE_APP_POOL( papp ) \
  209. UlReferenceAppPool( \
  210. (papp) \
  211. REFERENCE_DEBUG_ACTUAL_PARAMS \
  212. )
  213. // IRQL == PASSIVE_LEVEL
  214. //
  215. VOID
  216. UlDeleteAppPool(
  217. IN PUL_APP_POOL_OBJECT pAppPool
  218. REFERENCE_DEBUG_FORMAL_PARAMS
  219. );
  220. #define DELETE_APP_POOL( papp ) \
  221. UlDeleteAppPool( \
  222. (papp) \
  223. REFERENCE_DEBUG_ACTUAL_PARAMS \
  224. )
  225. #if REFERENCE_DEBUG
  226. VOID
  227. UlDereferenceAppPool(
  228. IN PUL_APP_POOL_OBJECT pAppPool
  229. REFERENCE_DEBUG_FORMAL_PARAMS
  230. );
  231. #else
  232. __inline
  233. VOID
  234. UlDereferenceAppPool(
  235. IN PUL_APP_POOL_OBJECT pAppPool
  236. )
  237. {
  238. if (InterlockedDecrement(&pAppPool->RefCount) == 0)
  239. {
  240. UlDeleteAppPool(pAppPool);
  241. }
  242. }
  243. #endif
  244. #define DEREFERENCE_APP_POOL( papp ) \
  245. UlDereferenceAppPool( \
  246. (papp) \
  247. REFERENCE_DEBUG_ACTUAL_PARAMS \
  248. )
  249. VOID
  250. UlpCleanUpAppoolProcess(
  251. IN PUL_APP_POOL_PROCESS pAppPoolProcess
  252. );
  253. #if REFERENCE_DEBUG
  254. VOID
  255. UlReferenceAppPoolProcess(
  256. IN PUL_APP_POOL_PROCESS pAppPoolProcess
  257. REFERENCE_DEBUG_FORMAL_PARAMS
  258. );
  259. VOID
  260. UlDereferenceAppPoolProcess(
  261. IN PUL_APP_POOL_PROCESS pAppPoolProcess
  262. REFERENCE_DEBUG_FORMAL_PARAMS
  263. );
  264. #else
  265. __inline
  266. VOID
  267. UlReferenceAppPoolProcess(
  268. IN PUL_APP_POOL_PROCESS pAppPoolProcess
  269. )
  270. {
  271. InterlockedIncrement(&pAppPoolProcess->RefCount);
  272. }
  273. __inline
  274. VOID
  275. UlDereferenceAppPoolProcess(
  276. IN PUL_APP_POOL_PROCESS pAppPoolProcess
  277. )
  278. {
  279. if (InterlockedDecrement(&pAppPoolProcess->RefCount) == 0)
  280. {
  281. UlpCleanUpAppoolProcess(pAppPoolProcess);
  282. }
  283. }
  284. #endif
  285. #define REFERENCE_APP_POOL_PROCESS( papp ) \
  286. UlReferenceAppPoolProcess( \
  287. (papp) \
  288. REFERENCE_DEBUG_ACTUAL_PARAMS \
  289. )
  290. #define DEREFERENCE_APP_POOL_PROCESS( papp ) \
  291. UlDereferenceAppPoolProcess( \
  292. (papp) \
  293. REFERENCE_DEBUG_ACTUAL_PARAMS \
  294. )
  295. // IRQL == PASSIVE_LEVEL
  296. //
  297. NTSTATUS
  298. UlQueryAppPoolInformation(
  299. IN PUL_APP_POOL_PROCESS pProcess,
  300. IN HTTP_APP_POOL_INFORMATION_CLASS InformationClass,
  301. OUT PVOID pAppPoolInformation,
  302. IN ULONG Length,
  303. OUT PULONG pReturnLength
  304. );
  305. // IRQL == PASSIVE_LEVEL
  306. //
  307. NTSTATUS
  308. UlSetAppPoolInformation(
  309. IN PUL_APP_POOL_PROCESS pProcess,
  310. IN HTTP_APP_POOL_INFORMATION_CLASS InformationClass,
  311. IN PVOID pAppPoolInformation,
  312. IN ULONG Length
  313. );
  314. // IRQL == PASSIVE_LEVEL
  315. //
  316. NTSTATUS
  317. UlWaitForDemandStart(
  318. IN PUL_APP_POOL_PROCESS pProcess,
  319. IN PIRP pIrp
  320. );
  321. // IRQL == PASSIVE_LEVEL
  322. //
  323. NTSTATUS
  324. UlReceiveHttpRequest(
  325. IN HTTP_REQUEST_ID RequestId,
  326. IN ULONG Flags,
  327. IN PUL_APP_POOL_PROCESS pProcess,
  328. IN PIRP pIrp
  329. );
  330. // IRQL == PASSIVE_LEVEL
  331. //
  332. NTSTATUS
  333. UlDeliverRequestToProcess(
  334. IN PUL_APP_POOL_OBJECT pAppPool,
  335. IN PUL_INTERNAL_REQUEST pRequest,
  336. OUT PIRP *pIrpToComplete OPTIONAL
  337. );
  338. /***************************************************************************++
  339. Routine Description:
  340. Gets the current app pool queue state of the request.
  341. Arguments:
  342. pProcess - Request object
  343. return value - The current appool queue state of the request
  344. --***************************************************************************/
  345. __inline
  346. BOOLEAN
  347. UlCheckAppPoolState(
  348. IN PUL_INTERNAL_REQUEST pRequest
  349. )
  350. {
  351. PUL_APP_POOL_PROCESS pProcess;
  352. //
  353. // Check the AppPool queue state of the request.
  354. //
  355. if (QueueCopiedState != pRequest->AppPool.QueueState)
  356. {
  357. return FALSE;
  358. }
  359. //
  360. // Check if the process has been detached. Since we never unset
  361. // pRequest->AppPool.pProcess until the reference of the request
  362. // drops to 0, it is safe to use pProcess this way here.
  363. //
  364. pProcess = pRequest->AppPool.pProcess;
  365. ASSERT(!pProcess || IS_VALID_AP_PROCESS(pProcess));
  366. if (!pProcess || pProcess->InCleanup)
  367. {
  368. return FALSE;
  369. }
  370. return TRUE;
  371. }
  372. VOID
  373. UlUnlinkRequestFromProcess(
  374. IN PUL_APP_POOL_OBJECT pAppPool,
  375. IN PUL_INTERNAL_REQUEST pRequest
  376. );
  377. // IRQL == PASSIVE_LEVEL
  378. //
  379. NTSTATUS
  380. UlGetPoolFromHandle(
  381. IN HANDLE hAppPool,
  382. IN KPROCESSOR_MODE AccessMode,
  383. OUT PUL_APP_POOL_OBJECT * ppAppPool
  384. );
  385. NTSTATUS
  386. UlInitializeAP(
  387. VOID
  388. );
  389. VOID
  390. UlTerminateAP(
  391. VOID
  392. );
  393. PUL_APP_POOL_PROCESS
  394. UlCreateAppPoolProcess(
  395. PUL_APP_POOL_OBJECT pObject
  396. );
  397. VOID
  398. UlCloseAppPoolProcess(
  399. PUL_APP_POOL_PROCESS pProcess
  400. );
  401. NTSTATUS
  402. UlWaitForDisconnect(
  403. IN PUL_APP_POOL_PROCESS pProcess,
  404. IN PUL_HTTP_CONNECTION pHttpConn,
  405. IN PIRP pIrp
  406. );
  407. VOID
  408. UlCompleteAllWaitForDisconnect(
  409. IN PUL_HTTP_CONNECTION pHttpConnection
  410. );
  411. VOID
  412. UlCopyRequestToIrp(
  413. IN PUL_INTERNAL_REQUEST pRequest,
  414. IN PIRP pIrp,
  415. IN BOOLEAN CompleteIrp,
  416. IN BOOLEAN LockAcquired
  417. );
  418. NTSTATUS
  419. UlCopyRequestToBuffer(
  420. IN PUL_INTERNAL_REQUEST pRequest,
  421. IN PUCHAR pKernelBuffer,
  422. IN PVOID pUserBuffer,
  423. IN ULONG BufferLength,
  424. IN ULONG Flags,
  425. IN BOOLEAN LockAcquired,
  426. OUT PULONG pBytesCopied
  427. );
  428. NTSTATUS
  429. UlDequeueNewRequest(
  430. IN PUL_APP_POOL_PROCESS pProcess,
  431. IN ULONG RequestBufferLength,
  432. OUT PUL_INTERNAL_REQUEST * pRequest
  433. );
  434. VOID
  435. UlRequeuePendingRequest(
  436. IN PUL_APP_POOL_PROCESS pProcess,
  437. IN PUL_INTERNAL_REQUEST pRequest
  438. );
  439. __inline
  440. NTSTATUS
  441. UlComputeRequestBytesNeeded(
  442. IN PUL_INTERNAL_REQUEST pRequest,
  443. IN PULONG pBytesNeeded
  444. )
  445. {
  446. NTSTATUS Status;
  447. ULONG SslInfoSize;
  448. C_ASSERT(SOCKADDR_ADDRESS_LENGTH_IP6 >= SOCKADDR_ADDRESS_LENGTH_IP);
  449. //
  450. // Calculate the size needed for the request, we'll need it below.
  451. //
  452. *pBytesNeeded =
  453. sizeof(HTTP_REQUEST) +
  454. pRequest->TotalRequestSize +
  455. (pRequest->UnknownHeaderCount * sizeof(HTTP_UNKNOWN_HEADER));
  456. //
  457. // Include additional space for the local and remote addresses.
  458. //
  459. *pBytesNeeded += 2 * ALIGN_UP(SOCKADDR_ADDRESS_LENGTH_IP6, PVOID);
  460. //
  461. // Include space for any SSL information.
  462. //
  463. if (pRequest->pHttpConn->SecureConnection)
  464. {
  465. Status = UlGetSslInfo(
  466. &pRequest->pHttpConn->pConnection->FilterInfo,
  467. 0, // BufferSize
  468. NULL, // pUserBuffer
  469. NULL, // pProcess (WP)
  470. NULL, // pBuffer
  471. NULL, // pMappedToken
  472. &SslInfoSize // pBytesNeeded
  473. );
  474. if (NT_SUCCESS(Status))
  475. {
  476. //
  477. // Struct must be aligned; add some slop space
  478. //
  479. *pBytesNeeded = ALIGN_UP(*pBytesNeeded, PVOID);
  480. *pBytesNeeded += SslInfoSize;
  481. }
  482. else
  483. {
  484. return Status;
  485. }
  486. }
  487. return STATUS_SUCCESS;
  488. } // UlComputeRequestBytesNeeded
  489. #endif // _APOOL_H_