Windows NT 4.0 source code leak
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.

478 lines
9.4 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. eventsel.c
  5. Abstract:
  6. This module contains routines for supporting the WinSock 2.0
  7. WSAEventSelect() and WSAEnumNetworkEvents() APIs.
  8. Author:
  9. Keith Moore (keithmo) 02-Aug-1995
  10. Revision History:
  11. --*/
  12. #include "afdp.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text( PAGE, AfdEventSelect )
  15. #pragma alloc_text( PAGE, AfdEnumNetworkEvents )
  16. #endif
  17. NTSTATUS
  18. AfdEventSelect (
  19. IN PIRP Irp,
  20. IN PIO_STACK_LOCATION IrpSp
  21. )
  22. /*++
  23. Routine Description:
  24. Associates an event object with the socket such that the event object
  25. will be signalled when any of the specified network events becomes
  26. active.
  27. Arguments:
  28. Irp - Pointer to I/O request packet.
  29. IrpSp - pointer to the IO stack location to use for this request.
  30. Return Value:
  31. NTSTATUS -- Indicates whether the APC was successfully queued.
  32. --*/
  33. {
  34. NTSTATUS status;
  35. PAFD_ENDPOINT endpoint;
  36. PAFD_EVENT_SELECT_INFO eventInfo;
  37. KIRQL oldIrql;
  38. PKEVENT eventObject;
  39. ULONG eventMask;
  40. PAGED_CODE( );
  41. //
  42. // Validate the parameters.
  43. //
  44. eventInfo = Irp->AssociatedIrp.SystemBuffer;
  45. if( eventInfo == NULL ||
  46. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  47. sizeof(*eventInfo) ||
  48. ( eventInfo->Event == NULL ^
  49. eventInfo->PollEvents == 0 ) ) {
  50. return STATUS_INVALID_PARAMETER;
  51. }
  52. //
  53. // Reference the target event object.
  54. //
  55. eventObject = NULL;
  56. if( eventInfo->Event != NULL ) {
  57. status = AfdReferenceEventObjectByHandle(
  58. eventInfo->Event,
  59. Irp->RequestorMode,
  60. (PVOID *)&eventObject
  61. );
  62. if( !NT_SUCCESS(status) ) {
  63. return status;
  64. }
  65. ASSERT( eventObject != NULL );
  66. }
  67. //
  68. // Grab the endpoint from the socket handle.
  69. //
  70. endpoint = IrpSp->FileObject->FsContext;
  71. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  72. //
  73. // Acquire the spinlock protecting the endpoint.
  74. //
  75. AfdAcquireSpinLock( &endpoint->SpinLock, &oldIrql );
  76. //
  77. // If this endpoint has an active EventSelect, dereference the
  78. // associated event object.
  79. //
  80. if( endpoint->EventObject != NULL ) {
  81. ObDereferenceObject( endpoint->EventObject );
  82. }
  83. //
  84. // Fill in the info.
  85. //
  86. endpoint->EventObject = eventObject;
  87. endpoint->EventsEnabled = eventInfo->PollEvents;
  88. if( endpoint->State == AfdEndpointStateListening ) {
  89. endpoint->EventsDisabled = AFD_DISABLED_LISTENING_POLL_EVENTS;
  90. } else {
  91. endpoint->EventsDisabled = 0;
  92. }
  93. IF_DEBUG(EVENT_SELECT) {
  94. KdPrint((
  95. "AfdEventSelect:\n"
  96. ));
  97. KdPrint((
  98. " Endpoint %08lX\n",
  99. endpoint
  100. ));
  101. KdPrint((
  102. " EventObject %08lX\n",
  103. eventObject
  104. ));
  105. KdPrint((
  106. " EventsEnabled %08lX\n",
  107. endpoint->EventsEnabled
  108. ));
  109. KdPrint((
  110. " EventsDisabled %08lX\n",
  111. endpoint->EventsDisabled
  112. ));
  113. KdPrint((
  114. " EventsActive %08lX\n",
  115. endpoint->EventsActive
  116. ));
  117. }
  118. //
  119. // While we've got the spinlock held, determine if any conditions
  120. // are met, and if so, signal the event object.
  121. //
  122. eventMask = endpoint->EventsActive & endpoint->EventsEnabled &
  123. ~endpoint->EventsDisabled;
  124. if( eventMask != 0 && eventObject != NULL ) {
  125. IF_DEBUG(EVENT_SELECT) {
  126. KdPrint((
  127. "AfdEventSelect: Setting event %08lX\n",
  128. eventObject
  129. ));
  130. }
  131. KeSetEvent(
  132. eventObject,
  133. AfdPriorityBoost,
  134. FALSE
  135. );
  136. }
  137. //
  138. // Release the spin lock and return.
  139. //
  140. AfdReleaseSpinLock( &endpoint->SpinLock, oldIrql );
  141. return STATUS_SUCCESS;
  142. } // AfdEventSelect
  143. NTSTATUS
  144. AfdEnumNetworkEvents (
  145. IN PIRP Irp,
  146. IN PIO_STACK_LOCATION IrpSp
  147. )
  148. /*++
  149. Routine Description:
  150. Retrieves event select information from the socket.
  151. Arguments:
  152. Irp - Pointer to I/O request packet.
  153. IrpSp - pointer to the IO stack location to use for this request.
  154. Return Value:
  155. NTSTATUS -- Indicates whether the APC was successfully queued.
  156. --*/
  157. {
  158. NTSTATUS status;
  159. PAFD_ENDPOINT endpoint;
  160. PAFD_ENUM_NETWORK_EVENTS_INFO eventInfo;
  161. KIRQL oldIrql;
  162. PKEVENT eventObject;
  163. ULONG pollEvents;
  164. PAGED_CODE( );
  165. //
  166. // Validate the parameters.
  167. //
  168. eventInfo = Irp->AssociatedIrp.SystemBuffer;
  169. if( eventInfo == NULL ||
  170. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  171. sizeof(*eventInfo) ||
  172. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  173. sizeof(*eventInfo) ) {
  174. return STATUS_INVALID_PARAMETER;
  175. }
  176. //
  177. // Reference the target event object.
  178. //
  179. eventObject = NULL;
  180. if( eventInfo->Event != NULL ) {
  181. status = AfdReferenceEventObjectByHandle(
  182. eventInfo->Event,
  183. Irp->RequestorMode,
  184. (PVOID *)&eventObject
  185. );
  186. if( !NT_SUCCESS(status) ) {
  187. return status;
  188. }
  189. ASSERT( eventObject != NULL );
  190. }
  191. //
  192. // Grab the endpoint from the socket handle.
  193. //
  194. endpoint = IrpSp->FileObject->FsContext;
  195. ASSERT( IS_AFD_ENDPOINT_TYPE( endpoint ) );
  196. //
  197. // Acquire the spinlock protecting the endpoint.
  198. //
  199. AfdAcquireSpinLock( &endpoint->SpinLock, &oldIrql );
  200. IF_DEBUG(EVENT_SELECT) {
  201. KdPrint((
  202. "AfdEnumNetworkEvents:\n"
  203. ));
  204. KdPrint((
  205. " Endpoint %08lX\n",
  206. endpoint
  207. ));
  208. KdPrint((
  209. " EventObject %08lX\n",
  210. eventObject
  211. ));
  212. KdPrint((
  213. " EventsEnabled %08lX\n",
  214. endpoint->EventsEnabled
  215. ));
  216. KdPrint((
  217. " EventsDisabled %08lX\n",
  218. endpoint->EventsDisabled
  219. ));
  220. KdPrint((
  221. " EventsActive %08lX\n",
  222. endpoint->EventsActive
  223. ));
  224. }
  225. //
  226. // Copy the data to the user's structure.
  227. //
  228. pollEvents = endpoint->EventsActive & endpoint->EventsEnabled &
  229. ~endpoint->EventsDisabled;
  230. eventInfo->PollEvents = pollEvents;
  231. RtlCopyMemory(
  232. eventInfo->EventStatus,
  233. endpoint->EventStatus,
  234. sizeof(endpoint->EventStatus)
  235. );
  236. //
  237. // If there was an event object handle passed in with this
  238. // request, reset and dereference it.
  239. //
  240. if( eventObject != NULL ) {
  241. IF_DEBUG(EVENT_SELECT) {
  242. KdPrint((
  243. "AfdEnumNetworkEvents: Resetting event %08lX\n",
  244. eventObject
  245. ));
  246. }
  247. KeResetEvent( eventObject );
  248. ObDereferenceObject( eventObject );
  249. }
  250. //
  251. // Release the spin lock and return.
  252. //
  253. AfdReleaseSpinLock( &endpoint->SpinLock, oldIrql );
  254. //
  255. // Before returning, tell the I/O subsystem how may bytes to copy
  256. // to the user's output buffer.
  257. //
  258. Irp->IoStatus.Information = sizeof(*eventInfo);
  259. return STATUS_SUCCESS;
  260. } // AfdEnumNetworkEvents
  261. VOID
  262. AfdIndicateEventSelectEvent (
  263. IN PAFD_ENDPOINT Endpoint,
  264. IN ULONG PollEventBit,
  265. IN NTSTATUS Status
  266. )
  267. {
  268. ULONG event;
  269. ULONG oldEventsActive;
  270. //
  271. // Sanity check.
  272. //
  273. ASSERT( IS_AFD_ENDPOINT_TYPE( Endpoint ) );
  274. ASSERT( PollEventBit < AFD_NUM_POLL_EVENTS );
  275. ASSERT( KeGetCurrentIrql() >= DISPATCH_LEVEL );
  276. //
  277. // Calculate the actual event bit.
  278. //
  279. event = 1 << PollEventBit;
  280. oldEventsActive = Endpoint->EventsActive;
  281. Endpoint->EventsActive |= event;
  282. Endpoint->EventStatus[PollEventBit] = Status;
  283. IF_DEBUG(EVENT_SELECT) {
  284. KdPrint((
  285. "AfdIndicateEventSelectEvent:\n"
  286. ));
  287. KdPrint((
  288. " Endpoint %08lX\n",
  289. Endpoint
  290. ));
  291. KdPrint((
  292. " EventObject %08lX\n",
  293. Endpoint->EventObject
  294. ));
  295. KdPrint((
  296. " EventsEnabled %08lX\n",
  297. Endpoint->EventsEnabled
  298. ));
  299. KdPrint((
  300. " EventsDisabled %08lX\n",
  301. Endpoint->EventsDisabled
  302. ));
  303. KdPrint((
  304. " EventsActive %08lX\n",
  305. Endpoint->EventsActive
  306. ));
  307. KdPrint((
  308. " Indicated Event %08lX\n",
  309. event
  310. ));
  311. }
  312. //
  313. // Only signal the endpoint's event object if the current event
  314. // is enabled, AND the current event was not already active, AND
  315. // there is an event object associated with this endpoint.
  316. //
  317. event &= Endpoint->EventsEnabled & ~Endpoint->EventsDisabled &
  318. ~oldEventsActive;
  319. if( event != 0 && Endpoint->EventObject != NULL ) {
  320. IF_DEBUG(EVENT_SELECT) {
  321. KdPrint((
  322. "AfdIndicateEventSelectEvent: Setting event %08lX\n",
  323. Endpoint->EventObject
  324. ));
  325. }
  326. KeSetEvent(
  327. Endpoint->EventObject,
  328. AfdPriorityBoost,
  329. FALSE
  330. );
  331. }
  332. } // AfdIndicateEventSelectEvent