Source code of Windows XP (NT5)
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.

5599 lines
191 KiB

  1. /*+
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. san.c
  5. Abstract:
  6. Contains routines for SAN switch support
  7. Author:
  8. Vadim Eydelman (VadimE) 1-Jul-1998
  9. Revision History:
  10. --*/
  11. #include "afdp.h"
  12. VOID
  13. AfdSanCancelConnect (
  14. IN PDEVICE_OBJECT DeviceObject,
  15. IN PIRP Irp
  16. );
  17. VOID
  18. AfdSanCancelRequest (
  19. IN PDEVICE_OBJECT DeviceObject,
  20. IN PIRP Irp
  21. );
  22. PIRP
  23. AfdSanDequeueRequest (
  24. PAFD_ENDPOINT SanEndpoint,
  25. PVOID RequestCtx
  26. );
  27. VOID
  28. AfdSanInitEndpoint (
  29. PAFD_ENDPOINT SanHlprEndpoint,
  30. PFILE_OBJECT SanFile,
  31. PAFD_SWITCH_CONTEXT SwitchContext
  32. );
  33. BOOLEAN
  34. AfdSanNotifyRequest (
  35. PAFD_ENDPOINT SanEndpoint,
  36. PVOID RequestCtx,
  37. NTSTATUS Status,
  38. ULONG_PTR Information
  39. );
  40. VOID
  41. AfdSanRestartRequestProcessing (
  42. PAFD_ENDPOINT Endpoint,
  43. NTSTATUS Status
  44. );
  45. NTSTATUS
  46. AfdSanReferenceSwitchSocketByHandle (
  47. IN HANDLE SocketHandle,
  48. IN ACCESS_MASK DesiredAccess,
  49. IN KPROCESSOR_MODE RequestorMode,
  50. IN PAFD_ENDPOINT SanHlprEndpoint,
  51. IN PAFD_SWITCH_CONTEXT SwitchContext OPTIONAL,
  52. OUT PFILE_OBJECT *FileObject
  53. );
  54. NTSTATUS
  55. AfdSanDupEndpointIntoServiceProcess (
  56. PFILE_OBJECT SanFileObject,
  57. PVOID SavedContext,
  58. ULONG ContextLength
  59. );
  60. VOID
  61. AfdSanResetPendingRequests (
  62. PAFD_ENDPOINT SanEndpoint
  63. );
  64. BOOLEAN
  65. AfdSanReferenceEndpointObject (
  66. PAFD_ENDPOINT Endpoint
  67. );
  68. NTSTATUS
  69. AfdSanFindSwitchSocketByProcessContext (
  70. IN NTSTATUS Status,
  71. IN PAFD_ENDPOINT SanHlprEndpoint,
  72. IN PAFD_SWITCH_CONTEXT SwitchContext,
  73. OUT PFILE_OBJECT *FileObject
  74. );
  75. VOID
  76. AfdSanProcessAddrListForProviderChange (
  77. PAFD_ENDPOINT SpecificEndpoint
  78. );
  79. NTSTATUS
  80. AfdSanGetCompletionObjectTypePointer (
  81. VOID
  82. );
  83. #ifdef ALLOC_PRAGMA
  84. #pragma alloc_text (PAGE,AfdSanCreateHelper)
  85. #pragma alloc_text (PAGE,AfdSanCleanupHelper)
  86. #pragma alloc_text (PAGE,AfdSanCleanupEndpoint)
  87. #pragma alloc_text (PAGE,AfdSanReferenceSwitchSocketByHandle)
  88. #pragma alloc_text (PAGE,AfdSanFindSwitchSocketByProcessContext)
  89. #pragma alloc_text (PAGESAN,AfdSanReferenceEndpointObject)
  90. #pragma alloc_text (PAGE,AfdSanDupEndpointIntoServiceProcess)
  91. #pragma alloc_text (PAGESAN,AfdSanResetPendingRequests)
  92. #pragma alloc_text (PAGESAN,AfdSanFastCementEndpoint)
  93. #pragma alloc_text (PAGESAN,AfdSanFastSetEvents)
  94. #pragma alloc_text (PAGESAN,AfdSanFastResetEvents)
  95. #pragma alloc_text (PAGESAN,AfdSanAcceptCore)
  96. #pragma alloc_text (PAGESAN,AfdSanConnectHandler)
  97. #pragma alloc_text (PAGESAN,AfdSanReleaseConnection)
  98. #pragma alloc_text (PAGESAN,AfdSanFastCompleteAccept)
  99. #pragma alloc_text (PAGESAN,AfdSanCancelAccept)
  100. #pragma alloc_text (PAGESAN,AfdSanCancelConnect)
  101. #pragma alloc_text (PAGESAN,AfdSanRedirectRequest)
  102. #pragma alloc_text (PAGESAN,AfdSanFastCompleteRequest)
  103. #pragma alloc_text (PAGE, AfdSanFastCompleteIo)
  104. #pragma alloc_text (PAGESAN,AfdSanDequeueRequest)
  105. #pragma alloc_text (PAGESAN,AfdSanCancelRequest)
  106. #pragma alloc_text (PAGESAN,AfdSanFastRefreshEndpoint)
  107. #pragma alloc_text (PAGE, AfdSanFastGetPhysicalAddr)
  108. #pragma alloc_text (PAGE, AfdSanFastGetServicePid)
  109. #pragma alloc_text (PAGE, AfdSanFastSetServiceProcess)
  110. #pragma alloc_text (PAGE, AfdSanFastProviderChange)
  111. #pragma alloc_text (PAGE, AfdSanAddrListChange)
  112. #pragma alloc_text (PAGESAN, AfdSanProcessAddrListForProviderChange)
  113. #pragma alloc_text (PAGE, AfdSanFastUnlockAll)
  114. #pragma alloc_text (PAGE, AfdSanPollBegin)
  115. #pragma alloc_text (PAGE, AfdSanPollEnd)
  116. #pragma alloc_text (PAGESAN, AfdSanPollUpdate)
  117. #pragma alloc_text (PAGE, AfdSanPollMerge)
  118. #pragma alloc_text (PAGE, AfdSanFastTransferCtx)
  119. #pragma alloc_text (PAGESAN, AfdSanAcquireContext)
  120. #pragma alloc_text (PAGESAN, AfdSanInitEndpoint)
  121. #pragma alloc_text (PAGE, AfdSanNotifyRequest)
  122. #pragma alloc_text (PAGESAN, AfdSanRestartRequestProcessing)
  123. #pragma alloc_text (PAGE, AfdSanGetCompletionObjectTypePointer)
  124. #pragma alloc_text (PAGESAN, AfdSanAbortConnection)
  125. #endif
  126. //
  127. // Dispatch level routines - external SAN entry points.
  128. //
  129. NTSTATUS
  130. AfdSanCreateHelper (
  131. PIRP Irp,
  132. PFILE_FULL_EA_INFORMATION EaBuffer,
  133. PAFD_ENDPOINT *Endpoint
  134. )
  135. /*++
  136. Routine Description:
  137. Allocates and initializes SAN helper endpoint for communication between switch
  138. and AFD.
  139. Arguments:
  140. Irp - Create IRP
  141. EaBuffer - Create IRP Ea buffer (AFD_SWITCH_OPEN_PACKET structure)
  142. CompletionPort - completion port to reflect kernel calls to switch
  143. CompletionEvent - event to identify overlapped IO triggered by the
  144. switch as opposed to the application
  145. Endpoint - buffer to place created endpoint pointer.
  146. Return Value:
  147. STATUS_SUCCESS - operation succeeded
  148. STATUS_ACCESS_VIOLATION - incorrect input buffer size.
  149. other - failed to access port/event object or allocation failure..
  150. --*/
  151. {
  152. NTSTATUS status;
  153. HANDLE port, event;
  154. PVOID ioCompletionPort;
  155. PVOID ioCompletionEvent;
  156. if ( !MmIsThisAnNtAsSystem () ) {
  157. #ifndef DONT_CHECK_FOR_DTC
  158. return STATUS_NOT_SUPPORTED;
  159. #else
  160. DbgPrint ("AFD: Temporarily allowing SAN support on non-server build\n");
  161. #endif //DONT_CHECK_FOR_DTC
  162. }
  163. #ifdef _WIN64
  164. if (IoIs32bitProcess (Irp)) {
  165. PAFD_SWITCH_OPEN_PACKET32 openPacket32;
  166. if (EaBuffer->EaValueLength<sizeof (*openPacket32)) {
  167. IF_DEBUG(SAN_SWITCH) {
  168. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  169. "AfdSanCreateHelper: Invalid switch open packet size.\n"));
  170. }
  171. return STATUS_ACCESS_VIOLATION;
  172. }
  173. openPacket32 = (PAFD_SWITCH_OPEN_PACKET32)(EaBuffer->EaName +
  174. EaBuffer->EaNameLength + 1);
  175. event = openPacket32->CompletionEvent;
  176. port = openPacket32->CompletionPort;
  177. }
  178. else
  179. #endif //_WIN64
  180. {
  181. PAFD_SWITCH_OPEN_PACKET openPacket;
  182. if (EaBuffer->EaValueLength<sizeof (*openPacket)) {
  183. IF_DEBUG (SAN_SWITCH) {
  184. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  185. "AfdSanCreateHelper: Invalid switch open packet size.\n"));
  186. }
  187. return STATUS_ACCESS_VIOLATION;
  188. }
  189. openPacket = (PAFD_SWITCH_OPEN_PACKET)(EaBuffer->EaName +
  190. EaBuffer->EaNameLength + 1);
  191. event = openPacket->CompletionEvent;
  192. port = openPacket->CompletionPort;
  193. }
  194. if (IoCompletionObjectType==NULL) {
  195. status = AfdSanGetCompletionObjectTypePointer ();
  196. if (!NT_SUCCESS (status)) {
  197. IF_DEBUG(SAN_SWITCH) {
  198. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_INFO_LEVEL,
  199. "AfdSanCreateHelper: Could not get completion OT:%lx\n",
  200. status));
  201. }
  202. return status;
  203. }
  204. }
  205. //
  206. // Get references to completion port and event
  207. //
  208. status = ObReferenceObjectByHandle (
  209. port,
  210. IO_COMPLETION_ALL_ACCESS,
  211. IoCompletionObjectType,
  212. Irp->RequestorMode,
  213. &ioCompletionPort,
  214. NULL
  215. );
  216. if (!NT_SUCCESS (status)) {
  217. IF_DEBUG (SAN_SWITCH) {
  218. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  219. "AfdSanCreateHelper: Could not reference completion port (%p).\n",
  220. status));
  221. }
  222. return status;
  223. }
  224. status = ObReferenceObjectByHandle (
  225. event,
  226. EVENT_ALL_ACCESS,
  227. *ExEventObjectType,
  228. Irp->RequestorMode,
  229. &ioCompletionEvent,
  230. NULL
  231. );
  232. if (!NT_SUCCESS (status)) {
  233. ObDereferenceObject (ioCompletionPort);
  234. IF_DEBUG(SAN_SWITCH) {
  235. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  236. "AfdSanCreateHelper: Could not reference completion event (%p).\n",
  237. status));
  238. }
  239. return status;
  240. }
  241. //
  242. // Allocate an AFD "helper" endpoint.
  243. //
  244. status = AfdAllocateEndpoint(
  245. Endpoint,
  246. NULL,
  247. 0
  248. );
  249. if( !NT_SUCCESS(status) ) {
  250. ObDereferenceObject (ioCompletionPort);
  251. ObDereferenceObject (ioCompletionEvent);
  252. return status;
  253. }
  254. (*Endpoint)->Type = AfdBlockTypeSanHelper;
  255. (*Endpoint)->Common.SanHlpr.IoCompletionPort = ioCompletionPort;
  256. (*Endpoint)->Common.SanHlpr.IoCompletionEvent = ioCompletionEvent;
  257. (*Endpoint)->Common.SanHlpr.Plsn = 0;
  258. KeEnterCriticalRegion ();
  259. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  260. if (AfdSanCodeHandle==NULL) {
  261. AfdSanCodeHandle = MmLockPagableCodeSection( AfdSanFastCementEndpoint );
  262. ASSERT( AfdDiscardableCodeHandle != NULL );
  263. InitializeListHead (&AfdSanHelperList);
  264. }
  265. InsertTailList (&AfdSanHelperList, &(*Endpoint)->Common.SanHlpr.SanListLink);
  266. ExReleaseResourceLite( AfdResource );
  267. KeLeaveCriticalRegion ();
  268. return STATUS_SUCCESS;
  269. }
  270. NTSTATUS
  271. AfdSanFastCementEndpoint (
  272. IN PFILE_OBJECT FileObject,
  273. IN ULONG IoctlCode,
  274. IN KPROCESSOR_MODE RequestorMode,
  275. IN PVOID InputBuffer,
  276. IN ULONG InputBufferLength,
  277. IN PVOID OutputBuffer,
  278. IN ULONG OutputBufferLength,
  279. OUT PUINT_PTR Information
  280. )
  281. /*++
  282. Routine Description:
  283. Changes the endpoint type to SAN to indicate that
  284. it is used for support of user mode SAN providers
  285. Associates switch context with the endpoint.
  286. Arguments:
  287. FileObject - SAN helper object - communication channel between the
  288. switch and AFD in the process.
  289. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_CEMENT_SAN)
  290. RequestorMode - mode of the caller
  291. InputBuffer - input parameters for the operation (AFD_SWITCH_CONTEXT_INFO)
  292. SocketHandle - handle of the endpoint being changed to SAN
  293. SwitchContext - switch context associated with the endpoint
  294. InputBufferLength - sizeof(AFD_SWITCH_CONTEXT_INFO)
  295. OutputBuffer - unused
  296. OutputBufferLength - unused
  297. Information - pointer for buffer to place return information into, unused
  298. Return Value:
  299. STATUS_SUCCESS - operation succeeded
  300. STATUS_INVALID_HANDLE - helper endpoint or switch socket is of incorrect type
  301. STATUS_INVALID_PARAMETER - input buffer is of incorrect size
  302. other - failed when attempting to access switch socket, input buffer, or switch context.
  303. --*/
  304. {
  305. NTSTATUS status;
  306. AFD_LOCK_QUEUE_HANDLE lockHandle;
  307. PFILE_OBJECT sanFileObject;
  308. AFD_SWITCH_CONTEXT_INFO contextInfo;
  309. PAFD_ENDPOINT sanEndpoint, sanHlprEndpoint;
  310. PVOID context;
  311. *Information = 0;
  312. try {
  313. #ifdef _WIN64
  314. if (IoIs32bitProcess (NULL)) {
  315. PAFD_SWITCH_CONTEXT_INFO32 contextInfo32;
  316. if (InputBufferLength<sizeof (*contextInfo32)) {
  317. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  318. }
  319. if (RequestorMode!=KernelMode) {
  320. ProbeForRead (InputBuffer,
  321. sizeof (*contextInfo32),
  322. PROBE_ALIGNMENT32 (AFD_SWITCH_CONTEXT_INFO32));
  323. }
  324. contextInfo32 = InputBuffer;
  325. contextInfo.SocketHandle = contextInfo32->SocketHandle;
  326. contextInfo.SwitchContext = contextInfo32->SwitchContext;
  327. }
  328. else
  329. #endif _WIN64
  330. {
  331. if (InputBufferLength<sizeof (contextInfo)) {
  332. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  333. }
  334. if (RequestorMode!=KernelMode) {
  335. ProbeForRead (InputBuffer,
  336. sizeof (contextInfo),
  337. PROBE_ALIGNMENT (AFD_SWITCH_CONTEXT_INFO));
  338. }
  339. contextInfo = *((PAFD_SWITCH_CONTEXT_INFO)InputBuffer);
  340. }
  341. if (contextInfo.SwitchContext==NULL) {
  342. IF_DEBUG(SAN_SWITCH) {
  343. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  344. "AFD: Switch context is NULL in AfdSanFastCementEndpoint\n"));
  345. }
  346. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  347. }
  348. if (RequestorMode!=KernelMode) {
  349. ProbeForWrite (contextInfo.SwitchContext,
  350. sizeof (*contextInfo.SwitchContext),
  351. PROBE_ALIGNMENT (AFD_SWITCH_CONTEXT));
  352. }
  353. }
  354. except (AFD_EXCEPTION_FILTER (&status)) {
  355. return status;
  356. }
  357. sanHlprEndpoint = FileObject->FsContext;
  358. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  359. status = AfdSanReferenceSwitchSocketByHandle (
  360. contextInfo.SocketHandle,
  361. (IoctlCode>>14)&3,
  362. RequestorMode,
  363. sanHlprEndpoint,
  364. NULL,
  365. &sanFileObject
  366. );
  367. if (!NT_SUCCESS (status)) {
  368. return status;
  369. }
  370. sanEndpoint = sanFileObject->FsContext;
  371. IF_DEBUG(SAN_SWITCH) {
  372. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  373. "AfdFastCementSanEndpoint: endp-%p, hlpr-%p.\n",
  374. sanEndpoint, sanHlprEndpoint));
  375. }
  376. //
  377. // Make sure that helper endpoint is really the one
  378. // and that san endpoint is in the state where it can
  379. // be given to the san provider.
  380. //
  381. context = AfdLockEndpointContext (sanEndpoint);
  382. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  383. if (!sanEndpoint->EndpointCleanedUp &&
  384. (sanEndpoint->Type==AfdBlockTypeEndpoint) &&
  385. (sanEndpoint->State==AfdEndpointStateBound) ) {
  386. AFD_SWITCH_CONTEXT localContext = {0,0,0,0};
  387. AfdSanInitEndpoint (sanHlprEndpoint, sanFileObject, contextInfo.SwitchContext);
  388. sanEndpoint->DisableFastIoSend = TRUE;
  389. sanEndpoint->DisableFastIoRecv = TRUE;
  390. sanEndpoint->EnableSendEvent = TRUE;
  391. sanEndpoint->Common.SanEndp.SelectEventsActive = AFD_POLL_SEND;
  392. sanEndpoint->State = AfdEndpointStateConnected;
  393. sanEndpoint->Common.SanEndp.LocalContext = &localContext;
  394. AfdIndicateEventSelectEvent (sanEndpoint, AFD_POLL_CONNECT|AFD_POLL_SEND, STATUS_SUCCESS);
  395. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  396. AfdIndicatePollEvent (sanEndpoint, AFD_POLL_CONNECT|AFD_POLL_SEND, STATUS_SUCCESS);
  397. status = AfdSanPollMerge (sanEndpoint, &localContext);
  398. sanEndpoint->Common.SanEndp.LocalContext = NULL;
  399. }
  400. else {
  401. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  402. status = STATUS_INVALID_HANDLE;
  403. }
  404. AfdUnlockEndpointContext (sanEndpoint, context);
  405. UPDATE_ENDPOINT2 (sanEndpoint, "AfdSanFastCementEndpoint, status: %lx", status);
  406. ObDereferenceObject (sanFileObject);
  407. return status;
  408. }
  409. NTSTATUS
  410. AfdSanFastSetEvents (
  411. IN PFILE_OBJECT FileObject,
  412. IN ULONG IoctlCode,
  413. IN KPROCESSOR_MODE RequestorMode,
  414. IN PVOID InputBuffer,
  415. IN ULONG InputBufferLength,
  416. IN PVOID OutputBuffer,
  417. IN ULONG OutputBufferLength,
  418. OUT PUINT_PTR Information
  419. )
  420. /*++
  421. Routine Description:
  422. Sets the poll event on the san endpoint to report
  423. to the application via various forms of the select
  424. Arguments:
  425. FileObject - SAN helper object - communication channel between the
  426. switch and AFD in the process.
  427. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_SET_EVENTS)
  428. RequestorMode - mode of the caller
  429. InputBuffer - input parameters for the operation (AFD_SWITCH_EVENT_INFO)
  430. SocketHandle - handle of the endpoint being changed to SAN
  431. EventBit - event bit to set
  432. Status - associated status (for AFD_POLL_EVENT_CONNECT_FAIL)
  433. InputBufferLength - sizeof(AFD_SWITCH_EVENT_INFO)
  434. OutputBuffer - unused
  435. OutputBufferLength - unused
  436. Information - pointer for buffer to place return information into, unused
  437. Return Value:
  438. STATUS_SUCCESS - operation succeeded
  439. STATUS_INVALID_HANDLE - helper endpoint or switch socket is of incorrect type
  440. STATUS_INVALID_PARAMETER - input buffer is of incorrect size, invalid event bit.
  441. other - failed when attempting to access switch socket, input buffer, or switch context.
  442. --*/
  443. {
  444. NTSTATUS status;
  445. PFILE_OBJECT sanFileObject;
  446. AFD_SWITCH_EVENT_INFO eventInfo;
  447. PAFD_ENDPOINT sanEndpoint, sanHlprEndpoint;
  448. AFD_LOCK_QUEUE_HANDLE lockHandle;
  449. *Information = 0;
  450. try {
  451. #ifdef _WIN64
  452. if (IoIs32bitProcess (NULL)) {
  453. PAFD_SWITCH_EVENT_INFO32 eventInfo32;
  454. if (InputBufferLength<sizeof (*eventInfo32)) {
  455. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  456. }
  457. if (RequestorMode!=KernelMode) {
  458. ProbeForRead (InputBuffer,
  459. sizeof (*eventInfo32),
  460. PROBE_ALIGNMENT32 (AFD_SWITCH_EVENT_INFO32));
  461. }
  462. eventInfo32 = InputBuffer;
  463. eventInfo.SocketHandle = eventInfo32->SocketHandle;
  464. eventInfo.SwitchContext = eventInfo32->SwitchContext;
  465. eventInfo.EventBit = eventInfo32->EventBit;
  466. eventInfo.Status = eventInfo32->Status;
  467. }
  468. else
  469. #endif _WIN64
  470. {
  471. if (InputBufferLength<sizeof (eventInfo)) {
  472. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  473. }
  474. if (RequestorMode!=KernelMode) {
  475. ProbeForRead (InputBuffer,
  476. sizeof (eventInfo),
  477. PROBE_ALIGNMENT (AFD_SWITCH_EVENT_INFO));
  478. }
  479. eventInfo = *((PAFD_SWITCH_EVENT_INFO)InputBuffer);
  480. }
  481. }
  482. except (AFD_EXCEPTION_FILTER (&status)) {
  483. return status;
  484. }
  485. if (eventInfo.EventBit >= AFD_NUM_POLL_EVENTS) {
  486. IF_DEBUG(SAN_SWITCH) {
  487. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  488. "AFD: Invalid EventBit=%d passed to AfdSanFastSetEvents\n",
  489. eventInfo.EventBit));
  490. }
  491. return STATUS_INVALID_PARAMETER;
  492. }
  493. eventInfo.Status = AfdValidateStatus (eventInfo.Status);
  494. //
  495. // If event is connect failure, then context should not exist.
  496. // If event is not connect failure, context should exist.
  497. //
  498. if ((eventInfo.EventBit==AFD_POLL_CONNECT_FAIL_BIT) ^
  499. (eventInfo.SwitchContext==NULL)) {
  500. IF_DEBUG(SAN_SWITCH) {
  501. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  502. "AFD: AfdSanFastSetEvents-bit:%ld, context:%p inconsistent\n",
  503. eventInfo.EventBit,
  504. eventInfo.SwitchContext));
  505. }
  506. return STATUS_INVALID_PARAMETER;
  507. }
  508. sanHlprEndpoint = FileObject->FsContext;
  509. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  510. status = AfdSanReferenceSwitchSocketByHandle (
  511. eventInfo.SocketHandle,
  512. (IoctlCode>>14)&3,
  513. RequestorMode,
  514. sanHlprEndpoint,
  515. eventInfo.SwitchContext,
  516. &sanFileObject
  517. );
  518. if (!NT_SUCCESS (status)) {
  519. return status;
  520. }
  521. sanEndpoint = sanFileObject->FsContext;
  522. if (sanEndpoint->State==AfdEndpointStateConnected ||
  523. (eventInfo.EventBit==AFD_POLL_CONNECT_FAIL_BIT &&
  524. sanEndpoint->State==AfdEndpointStateBound) ) {
  525. IF_DEBUG(SAN_SWITCH) {
  526. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  527. "AfdFastSetSanEvents: endp-%p, bit-%lx, status-%lx.\n",
  528. sanEndpoint, eventInfo.EventBit, eventInfo.Status));
  529. }
  530. try {
  531. LONG currentEvents, newEvents;
  532. //
  533. // Update our event record. Make sure endpoint is connected, otherwise
  534. // sanEndpoint->Common.SanEndp.SwitchContext will not be valid
  535. //
  536. if (sanEndpoint->State==AfdEndpointStateConnected) {
  537. do {
  538. currentEvents = *((LONG volatile *)&sanEndpoint->Common.SanEndp.SelectEventsActive);
  539. newEvents = *((LONG volatile *)&sanEndpoint->Common.SanEndp.SwitchContext->EventsActive);
  540. }
  541. while (InterlockedCompareExchange (
  542. (PLONG)&sanEndpoint->Common.SanEndp.SelectEventsActive,
  543. newEvents,
  544. currentEvents)!=currentEvents);
  545. }
  546. }
  547. except (AFD_EXCEPTION_FILTER (&status)) {
  548. goto complete;
  549. }
  550. //
  551. // Signal the event.
  552. //
  553. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  554. AfdIndicateEventSelectEvent (sanEndpoint, 1<<eventInfo.EventBit, eventInfo.Status);
  555. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  556. AfdIndicatePollEvent (sanEndpoint, 1<<eventInfo.EventBit, eventInfo.Status);
  557. status = STATUS_SUCCESS;
  558. }
  559. else {
  560. status = STATUS_INVALID_HANDLE;
  561. }
  562. complete:
  563. UPDATE_ENDPOINT2 (sanEndpoint,
  564. "AfdFastSetEvents, event/status: %lx",
  565. NT_SUCCESS (status) ? eventInfo.EventBit : status);
  566. ObDereferenceObject (sanFileObject);
  567. return status;
  568. }
  569. NTSTATUS
  570. AfdSanFastResetEvents (
  571. IN PFILE_OBJECT FileObject,
  572. IN ULONG IoctlCode,
  573. IN KPROCESSOR_MODE RequestorMode,
  574. IN PVOID InputBuffer,
  575. IN ULONG InputBufferLength,
  576. IN PVOID OutputBuffer,
  577. IN ULONG OutputBufferLength,
  578. OUT PUINT_PTR Information
  579. )
  580. /*++
  581. Routine Description:
  582. Resets the poll event on the san endpoint so that it is no
  583. longer reported to the application via various forms of the select
  584. Arguments:
  585. FileObject - SAN helper object - communication channel between the
  586. switch and AFD in the process.
  587. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_RESET_EVENTS)
  588. RequestorMode - mode of the caller
  589. InputBuffer - input parameters for the operation (AFD_SWITCH_EVENT_INFO)
  590. SocketHandle - handle of the endpoint being changed to SAN
  591. EventBit - event bit to reset
  592. Status - associated status (ignored)
  593. InputBufferLength - sizeof(AFD_SWITCH_EVENT_INFO)
  594. OutputBuffer - unused
  595. OutputBufferLength - unused
  596. Information - pointer for buffer to place return information into, unused
  597. Return Value:
  598. STATUS_SUCCESS - operation succeeded
  599. STATUS_INVALID_HANDLE - helper endpoint or switch socket is of incorrect type
  600. STATUS_INVALID_PARAMETER - input buffer is of incorrect size, invalid event bit.
  601. other - failed when attempting to access switch socket, input buffer, or switch context.
  602. --*/
  603. {
  604. AFD_LOCK_QUEUE_HANDLE lockHandle;
  605. NTSTATUS status;
  606. PFILE_OBJECT sanFileObject;
  607. AFD_SWITCH_EVENT_INFO eventInfo;
  608. PAFD_ENDPOINT sanEndpoint, sanHlprEndpoint;
  609. *Information = 0;
  610. try {
  611. #ifdef _WIN64
  612. if (IoIs32bitProcess (NULL)) {
  613. PAFD_SWITCH_EVENT_INFO32 eventInfo32;
  614. if (InputBufferLength<sizeof (*eventInfo32)) {
  615. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  616. }
  617. if (RequestorMode!=KernelMode) {
  618. ProbeForRead (InputBuffer,
  619. sizeof (*eventInfo32),
  620. PROBE_ALIGNMENT32 (AFD_SWITCH_EVENT_INFO32));
  621. }
  622. eventInfo32 = InputBuffer;
  623. eventInfo.SocketHandle = eventInfo32->SocketHandle;
  624. eventInfo.SwitchContext = eventInfo32->SwitchContext;
  625. eventInfo.EventBit = eventInfo32->EventBit;
  626. eventInfo.Status = eventInfo32->Status;
  627. }
  628. else
  629. #endif _WIN64
  630. {
  631. if (InputBufferLength<sizeof (eventInfo)) {
  632. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  633. }
  634. if (RequestorMode!=KernelMode) {
  635. ProbeForRead (InputBuffer,
  636. sizeof (eventInfo),
  637. PROBE_ALIGNMENT (AFD_SWITCH_EVENT_INFO));
  638. }
  639. eventInfo = *((PAFD_SWITCH_EVENT_INFO)InputBuffer);
  640. }
  641. }
  642. except (AFD_EXCEPTION_FILTER (&status)) {
  643. return status;
  644. }
  645. if (eventInfo.EventBit >= AFD_NUM_POLL_EVENTS) {
  646. IF_DEBUG(SAN_SWITCH) {
  647. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  648. "AFD: Invalid EventBit=%d passed to AfdSanFastResetEvents\n",
  649. eventInfo.EventBit));
  650. }
  651. return STATUS_INVALID_PARAMETER;
  652. }
  653. if (eventInfo.SwitchContext==NULL) {
  654. KdPrint (("AFD: Switch context is NULL in AfdSanFastResetEvents\n"));
  655. return STATUS_INVALID_PARAMETER;
  656. }
  657. sanHlprEndpoint = FileObject->FsContext;
  658. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  659. status = AfdSanReferenceSwitchSocketByHandle (
  660. eventInfo.SocketHandle,
  661. (IoctlCode>>14)&3,
  662. RequestorMode,
  663. sanHlprEndpoint,
  664. eventInfo.SwitchContext,
  665. &sanFileObject
  666. );
  667. if (!NT_SUCCESS (status)) {
  668. return status;
  669. }
  670. sanEndpoint = sanFileObject->FsContext;
  671. IF_DEBUG(SAN_SWITCH) {
  672. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  673. "AfdFastResetSanEvents: endp-%p, bit-%lx, status-%lx.\n",
  674. sanEndpoint, eventInfo.EventBit, eventInfo.Status));
  675. }
  676. try {
  677. LONG currentEvents, newEvents;
  678. //
  679. // Update our event record.
  680. //
  681. do {
  682. currentEvents = *((LONG volatile *)&sanEndpoint->Common.SanEndp.SelectEventsActive);
  683. newEvents = *((LONG volatile *)&sanEndpoint->Common.SanEndp.SwitchContext->EventsActive);
  684. }
  685. while (InterlockedCompareExchange (
  686. (PLONG)&sanEndpoint->Common.SanEndp.SelectEventsActive,
  687. newEvents,
  688. currentEvents)!=currentEvents);
  689. }
  690. except (AFD_EXCEPTION_FILTER (&status)) {
  691. goto complete;
  692. }
  693. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  694. //
  695. // Reset EventSelect mask
  696. sanEndpoint->EventsActive &= (~ (1<<(eventInfo.EventBit)));
  697. if (eventInfo.EventBit == AFD_POLL_SEND_BIT)
  698. sanEndpoint->EnableSendEvent = TRUE;
  699. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  700. status = STATUS_SUCCESS;
  701. complete:
  702. UPDATE_ENDPOINT2 (sanEndpoint,
  703. "AfdFastResetEvents, event/status: %lx",
  704. NT_SUCCESS (status) ? eventInfo.EventBit : status);
  705. ObDereferenceObject (sanFileObject);
  706. return status;
  707. }
  708. //
  709. // Macros to make the super accept restart code more maintainable.
  710. //
  711. #define AfdRestartSuperAcceptInfo DeviceIoControl
  712. // Used while IRP is in AFD queue (otherwise AfdAcceptFileObject
  713. // is stored as completion routine context).
  714. #define AfdAcceptFileObject Type3InputBuffer
  715. // Used when IRP is passed to the transport (otherwise MdlAddress
  716. // is stored in the IRP itself).
  717. #define AfdMdlAddress Type3InputBuffer
  718. #define AfdReceiveDataLength OutputBufferLength
  719. #define AfdRemoteAddressLength InputBufferLength
  720. #define AfdLocalAddressLength IoControlCode
  721. NTSTATUS
  722. FASTCALL
  723. AfdSanConnectHandler (
  724. PIRP Irp,
  725. PIO_STACK_LOCATION IrpSp
  726. )
  727. /*++
  728. Routine Description:
  729. Implements connect indication from SAN provider.
  730. Picks up the accept from the listening endpoint queue
  731. or queues the IRP an signals the application to come
  732. down with an accept.
  733. Arguments:
  734. Irp - SAN connect IRP
  735. IrpSp - stack location
  736. Return Value:
  737. NTSTATUS
  738. --*/
  739. {
  740. NTSTATUS status;
  741. PAFD_SWITCH_CONNECT_INFO connectInfo;
  742. union {
  743. #ifdef _WIN64
  744. PAFD_SWITCH_ACCEPT_INFO32 acceptInfo32;
  745. #endif //_WIN64
  746. PAFD_SWITCH_ACCEPT_INFO acceptInfo;
  747. } u;
  748. PFILE_OBJECT listenFileObject;
  749. PAFD_ENDPOINT sanHlprEndpoint;
  750. PAFD_ENDPOINT listenEndpoint;
  751. PAFD_CONNECTION connection;
  752. ULONG RemoteAddressLength;
  753. AFD_LOCK_QUEUE_HANDLE lockHandle;
  754. PIRP acceptIrp;
  755. PTA_ADDRESS localAddress;
  756. #ifdef _WIN64
  757. if (IoIs32bitProcess (Irp)) {
  758. PAFD_SWITCH_CONNECT_INFO newSystemBuffer;
  759. PAFD_SWITCH_CONNECT_INFO32 oldSystemBuffer = Irp->AssociatedIrp.SystemBuffer;
  760. ULONG newLength;
  761. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  762. sizeof(*oldSystemBuffer) ) {
  763. status = STATUS_INVALID_PARAMETER;
  764. goto complete;
  765. }
  766. newLength = sizeof (*newSystemBuffer)
  767. -sizeof(*oldSystemBuffer)
  768. +IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  769. try {
  770. newSystemBuffer = ExAllocatePoolWithQuota (NonPagedPool, newLength);
  771. }
  772. except (EXCEPTION_EXECUTE_HANDLER) {
  773. status = GetExceptionCode ();
  774. goto complete;
  775. }
  776. newSystemBuffer->ListenHandle = oldSystemBuffer->ListenHandle;
  777. newSystemBuffer->SwitchContext = oldSystemBuffer->SwitchContext;
  778. RtlMoveMemory (&newSystemBuffer->RemoteAddress,
  779. &oldSystemBuffer->RemoteAddress,
  780. IrpSp->Parameters.DeviceIoControl.InputBufferLength-
  781. FIELD_OFFSET (AFD_SWITCH_CONNECT_INFO32, RemoteAddress));
  782. ExFreePool (Irp->AssociatedIrp.SystemBuffer);
  783. Irp->AssociatedIrp.SystemBuffer = newSystemBuffer;
  784. IrpSp->Parameters.DeviceIoControl.InputBufferLength = newLength;
  785. }
  786. #endif // _WIN64
  787. //
  788. // Set up local variables.
  789. //
  790. listenFileObject = NULL;
  791. sanHlprEndpoint = IrpSp->FileObject->FsContext;
  792. ASSERT( sanHlprEndpoint->Type == AfdBlockTypeSanHelper);
  793. Irp->IoStatus.Information = 0;
  794. connectInfo = Irp->AssociatedIrp.SystemBuffer;
  795. //
  796. // Verify input parameters
  797. //
  798. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  799. sizeof (*connectInfo) ||
  800. connectInfo->RemoteAddress.TAAddressCount!=2 || // Must have local and remote addresses
  801. (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  802. FIELD_OFFSET (AFD_SWITCH_CONNECT_INFO,
  803. RemoteAddress.Address[0].Address[
  804. connectInfo->RemoteAddress.Address[0].AddressLength])+sizeof(TA_ADDRESS))) {
  805. status = STATUS_INVALID_PARAMETER;
  806. goto complete;
  807. }
  808. #ifdef _WIN64
  809. if (IoIs32bitProcess (Irp)) {
  810. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  811. sizeof (*u.acceptInfo32)) {
  812. status = STATUS_INVALID_PARAMETER;
  813. goto complete;
  814. }
  815. }
  816. else
  817. #endif // _WIN64
  818. {
  819. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  820. sizeof (*u.acceptInfo)) {
  821. status = STATUS_INVALID_PARAMETER;
  822. goto complete;
  823. }
  824. }
  825. RemoteAddressLength = FIELD_OFFSET (TRANSPORT_ADDRESS, Address[0].Address[
  826. connectInfo->RemoteAddress.Address[0].AddressLength]);
  827. localAddress = (PTA_ADDRESS)
  828. &(connectInfo->RemoteAddress.Address[0].Address[
  829. connectInfo->RemoteAddress.Address[0].AddressLength]);
  830. if (&localAddress->Address[localAddress->AddressLength]-(PUCHAR)Irp->AssociatedIrp.SystemBuffer>
  831. (LONG)IrpSp->Parameters.DeviceIoControl.InputBufferLength) {
  832. status = STATUS_INVALID_PARAMETER;
  833. goto complete;
  834. }
  835. if (!IS_SAN_HELPER(sanHlprEndpoint) ||
  836. sanHlprEndpoint->OwningProcess!=IoGetCurrentProcess ()) {
  837. status = STATUS_INVALID_HANDLE;
  838. goto complete;
  839. }
  840. //
  841. // We will separate addresses, so change the count
  842. //
  843. connectInfo->RemoteAddress.TAAddressCount = 1;
  844. #ifdef _WIN64
  845. if (IoIs32bitProcess (Irp)) {
  846. u.acceptInfo32 = MmGetMdlVirtualAddress (Irp->MdlAddress);
  847. ASSERT (u.acceptInfo32!=NULL);
  848. ASSERT (MmGetMdlByteCount (Irp->MdlAddress)>=sizeof (*u.acceptInfo32));
  849. }
  850. else
  851. #endif // _WIN64
  852. {
  853. u.acceptInfo = MmGetMdlVirtualAddress (Irp->MdlAddress);
  854. ASSERT (u.acceptInfo!=NULL);
  855. ASSERT (MmGetMdlByteCount (Irp->MdlAddress)>=sizeof (*u.acceptInfo));
  856. }
  857. //
  858. // Get the listening file object and verify its type and state
  859. //
  860. status = ObReferenceObjectByHandle (
  861. connectInfo->ListenHandle,
  862. (IrpSp->Parameters.DeviceIoControl.IoControlCode >> 14) & 3, // DesiredAccess
  863. *IoFileObjectType,
  864. Irp->RequestorMode,
  865. (PVOID)&listenFileObject,
  866. NULL);
  867. if (!NT_SUCCESS (status)) {
  868. goto complete;
  869. }
  870. if (IoGetRelatedDeviceObject (listenFileObject)!=AfdDeviceObject) {
  871. status = STATUS_INVALID_HANDLE;
  872. goto complete;
  873. }
  874. listenEndpoint = listenFileObject->FsContext;
  875. if ( !listenEndpoint->Listening ||
  876. listenEndpoint->State == AfdEndpointStateClosing ||
  877. listenEndpoint->EndpointCleanedUp ) {
  878. status = STATUS_INVALID_HANDLE;
  879. goto complete;
  880. }
  881. IF_DEBUG(SAN_SWITCH) {
  882. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  883. "AfdSanConnectHandler: endp-%p, irp-%p.\n",
  884. listenEndpoint,
  885. Irp));
  886. }
  887. if (!IS_DELAYED_ACCEPTANCE_ENDPOINT (listenEndpoint)) {
  888. //
  889. // Keep getting accept IRPs/connection structures till
  890. // we find one that can be used to satisfy connect indication
  891. // or queue it.
  892. //
  893. while ((connection = AfdGetFreeConnection( listenEndpoint, &acceptIrp ))!=NULL
  894. && acceptIrp!=NULL) {
  895. PAFD_ENDPOINT acceptEndpoint;
  896. PFILE_OBJECT acceptFileObject;
  897. PIO_STACK_LOCATION irpSp;
  898. IF_DEBUG(LISTEN) {
  899. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  900. "AfdSanConnectHandler: using connection %lx\n",
  901. connection ));
  902. }
  903. ASSERT( connection->Type == AfdBlockTypeConnection );
  904. irpSp = IoGetCurrentIrpStackLocation (acceptIrp);
  905. acceptFileObject = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdAcceptFileObject;
  906. acceptEndpoint = acceptFileObject->FsContext;
  907. ASSERT (IS_AFD_ENDPOINT_TYPE (acceptEndpoint));
  908. ASSERT (acceptIrp->Tail.Overlay.DriverContext[0] == connection);
  909. ASSERT (connection->Endpoint == NULL);
  910. InterlockedDecrement (
  911. &listenEndpoint->Common.VcListening.FailedConnectionAdds);
  912. InterlockedPushEntrySList (
  913. &listenEndpoint->Common.VcListening.FreeConnectionListHead,
  914. &connection->SListEntry
  915. );
  916. DEBUG connection = NULL;
  917. //
  918. // Make sure connection indication comes from current process.
  919. // (we do check it indirectly up above when validating the request.
  920. // This check is explicit).
  921. //
  922. if (IoThreadToProcess (Irp->Tail.Overlay.Thread)==IoGetCurrentProcess ()) {
  923. //
  924. // Check if super accept Irp has enough space for
  925. // the remote address
  926. //
  927. if( (ULONG)RemoteAddressLength <=
  928. irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength ) {
  929. //
  930. // Check if we have enough system PTE's to map
  931. // the buffer.
  932. //
  933. status = AfdMapMdlChain (acceptIrp->MdlAddress);
  934. if( NT_SUCCESS (status) ) {
  935. HANDLE acceptHandle;
  936. BOOLEAN handleDuplicated;
  937. if (IoThreadToProcess (Irp->Tail.Overlay.Thread)==
  938. IoThreadToProcess (acceptIrp->Tail.Overlay.Thread)) {
  939. acceptHandle = acceptIrp->Tail.Overlay.DriverContext[3];
  940. status = STATUS_SUCCESS;
  941. handleDuplicated = FALSE;
  942. }
  943. else {
  944. //
  945. // Listen process is different than the accepting one.
  946. // We need to duplicate accepting handle into the listening
  947. // process so that accept can take place there and the accepting
  948. // socket will later get dup-ed into the accepting process when
  949. // that process performs an IO operation on it.
  950. //
  951. status = ObOpenObjectByPointer (
  952. acceptFileObject,
  953. OBJ_CASE_INSENSITIVE,
  954. NULL,
  955. MAXIMUM_ALLOWED,
  956. *IoFileObjectType,
  957. KernelMode,
  958. &acceptHandle);
  959. handleDuplicated = TRUE; // If we fail duplication above,
  960. // this variable is not used
  961. // so setting it to TRUE won't
  962. // have any effect.
  963. }
  964. if (NT_SUCCESS (status)) {
  965. AfdAcquireSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  966. if (!acceptEndpoint->EndpointCleanedUp) {
  967. IoSetCancelRoutine (acceptIrp, AfdSanCancelAccept);
  968. if (!acceptIrp->Cancel) {
  969. //
  970. // Copy the remote address from the connection object
  971. //
  972. #ifndef i386
  973. if (acceptEndpoint->Common.VcConnecting.FixAddressAlignment) {
  974. USHORT addressLength =
  975. connectInfo->RemoteAddress.Address[0].AddressLength
  976. + sizeof (USHORT);
  977. USHORT UNALIGNED *pAddrLength = (PVOID)
  978. ((PUCHAR)MmGetSystemAddressForMdl (acceptIrp->MdlAddress)
  979. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  980. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  981. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength
  982. - sizeof (USHORT));
  983. RtlMoveMemory (
  984. (PUCHAR)MmGetSystemAddressForMdl (acceptIrp->MdlAddress)
  985. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  986. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  987. &connectInfo->RemoteAddress.Address[0].AddressType,
  988. addressLength);
  989. *pAddrLength = addressLength;
  990. }
  991. else
  992. #endif
  993. {
  994. RtlMoveMemory (
  995. (PUCHAR)MmGetSystemAddressForMdl (acceptIrp->MdlAddress)
  996. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  997. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  998. &connectInfo->RemoteAddress,
  999. RemoteAddressLength);
  1000. }
  1001. if (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0) {
  1002. TDI_ADDRESS_INFO UNALIGNED *addressInfo = (PVOID)
  1003. ((PUCHAR)MmGetSystemAddressForMdl(acceptIrp->MdlAddress)
  1004. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength);
  1005. #ifndef i386
  1006. if (acceptEndpoint->Common.VcConnecting.FixAddressAlignment) {
  1007. USHORT UNALIGNED * pAddrLength = (PVOID)
  1008. ((PUCHAR)addressInfo
  1009. +irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  1010. -sizeof(USHORT));
  1011. RtlMoveMemory (
  1012. addressInfo,
  1013. &localAddress->AddressType,
  1014. localAddress->AddressLength+sizeof (USHORT));
  1015. *pAddrLength = localAddress->AddressLength+sizeof (USHORT);
  1016. }
  1017. else
  1018. #endif
  1019. {
  1020. addressInfo->ActivityCount = 0;
  1021. addressInfo->Address.TAAddressCount = 1;
  1022. RtlMoveMemory (
  1023. &addressInfo->Address.Address,
  1024. localAddress,
  1025. FIELD_OFFSET (TA_ADDRESS, Address[localAddress->AddressLength]));
  1026. }
  1027. }
  1028. ASSERT (acceptEndpoint->Irp==acceptIrp);
  1029. acceptEndpoint->Irp = NULL;
  1030. //
  1031. // Convert endpoint to SAN
  1032. //
  1033. AfdSanInitEndpoint (sanHlprEndpoint, acceptFileObject, connectInfo->SwitchContext);
  1034. UPDATE_ENDPOINT (acceptEndpoint);
  1035. InsertTailList (&acceptEndpoint->Common.SanEndp.IrpList,
  1036. &acceptIrp->Tail.Overlay.ListEntry);
  1037. //
  1038. // Setup output for switch and complete its IRP
  1039. //
  1040. // Do this under protection of exception handler since application
  1041. // can change protection attributes of the virtual address range
  1042. // or even deallocate it.
  1043. try {
  1044. #ifdef _WIN64
  1045. if (IoIs32bitProcess (Irp)) {
  1046. u.acceptInfo32->AcceptHandle = (VOID * POINTER_32)acceptHandle;
  1047. u.acceptInfo32->ReceiveLength = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength;
  1048. Irp->IoStatus.Information = sizeof (*u.acceptInfo32);
  1049. }
  1050. else
  1051. #endif //_WIN64
  1052. {
  1053. u.acceptInfo->AcceptHandle = acceptHandle;
  1054. u.acceptInfo->ReceiveLength = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength;
  1055. Irp->IoStatus.Information = sizeof (*u.acceptInfo);
  1056. }
  1057. }
  1058. except (AFD_EXCEPTION_FILTER (&status)) {
  1059. //
  1060. // If the app is playing with switch's virtual addresses
  1061. // we can't help much - it's accept IRP will probably
  1062. // just hang since the switch is not going to follow
  1063. // the failed connect IRP with accept completion.
  1064. //
  1065. }
  1066. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1067. AfdRecordConnectionsPreaccepted ();
  1068. Irp->IoStatus.Status = STATUS_SUCCESS;
  1069. IoCompleteRequest (Irp, AfdPriorityBoost);
  1070. ObDereferenceObject (listenFileObject);
  1071. IF_DEBUG(SAN_SWITCH) {
  1072. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1073. "AfdSanConnectHandler: pre-accepted, endp-%p, SuperAccept irp-%p\n",
  1074. acceptEndpoint, acceptIrp));
  1075. }
  1076. return STATUS_SUCCESS;
  1077. }
  1078. else { //if (!acceptIrp->Cancel
  1079. if (IoSetCancelRoutine (acceptIrp, NULL)==NULL) {
  1080. KIRQL cancelIrql;
  1081. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1082. IoAcquireCancelSpinLock (&cancelIrql);
  1083. IoReleaseCancelSpinLock (cancelIrql);
  1084. }
  1085. else {
  1086. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1087. }
  1088. }
  1089. }
  1090. else { // if (!acceptEndpoint->EndpointCleanedUp)
  1091. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, &lockHandle);
  1092. IF_DEBUG(SAN_SWITCH) {
  1093. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1094. "AfdSanConnectHandler: accept endpoint cleanedup. endp=%lx",
  1095. acceptEndpoint));
  1096. }
  1097. }
  1098. if (handleDuplicated) {
  1099. #if DBG
  1100. status =
  1101. #endif
  1102. NtClose (acceptHandle);
  1103. }
  1104. ASSERT (NT_SUCCESS (status));
  1105. status = STATUS_CANCELLED;
  1106. } // if (!accept handle duplication succeeded)
  1107. } // if (!MDL mapping succeeded).
  1108. }
  1109. else {
  1110. status = STATUS_BUFFER_TOO_SMALL;
  1111. }
  1112. }
  1113. else {
  1114. status = STATUS_INVALID_HANDLE;
  1115. }
  1116. UPDATE_ENDPOINT2 (acceptEndpoint,
  1117. "AfdSanConnectHandler, Superaccept failed with status: %lx",
  1118. status);
  1119. AfdCleanupSuperAccept (acceptIrp, status);
  1120. IoCompleteRequest (acceptIrp, AfdPriorityBoost);
  1121. }
  1122. }
  1123. else {
  1124. //
  1125. // We have little choice but create an extra connection
  1126. // on the fly since regular connection are posted to
  1127. // the transport as TDI_LISTENs.
  1128. //
  1129. status = AfdCreateConnection(
  1130. &listenEndpoint->TransportInfo->TransportDeviceName,
  1131. listenEndpoint->AddressHandle,
  1132. IS_TDI_BUFFERRING(listenEndpoint),
  1133. listenEndpoint->InLine,
  1134. listenEndpoint->OwningProcess,
  1135. &connection
  1136. );
  1137. if (!NT_SUCCESS (status)) {
  1138. goto complete;
  1139. }
  1140. InterlockedDecrement (
  1141. &listenEndpoint->Common.VcListening.FailedConnectionAdds);
  1142. }
  1143. if (connection!=NULL) {
  1144. LIST_ENTRY irpList;
  1145. ASSERT (connection->Endpoint == NULL);
  1146. if ( connection->RemoteAddress != NULL &&
  1147. connection->RemoteAddressLength < (ULONG)RemoteAddressLength ) {
  1148. AFD_RETURN_REMOTE_ADDRESS(
  1149. connection->RemoteAddress,
  1150. connection->RemoteAddressLength
  1151. );
  1152. connection->RemoteAddress = NULL;
  1153. }
  1154. if ( connection->RemoteAddress == NULL ) {
  1155. connection->RemoteAddress = AFD_ALLOCATE_REMOTE_ADDRESS (RemoteAddressLength);
  1156. if (connection->RemoteAddress==NULL) {
  1157. AfdSanReleaseConnection (listenEndpoint, connection, TRUE);
  1158. status = STATUS_INSUFFICIENT_RESOURCES;
  1159. goto complete;
  1160. }
  1161. }
  1162. connection->RemoteAddressLength = RemoteAddressLength;
  1163. RtlMoveMemory(
  1164. connection->RemoteAddress,
  1165. &connectInfo->RemoteAddress,
  1166. RemoteAddressLength
  1167. );
  1168. //
  1169. // We just got a connection without AcceptEx IRP
  1170. // We'll have to queue the IRP, setup cancel routine and pend it
  1171. //
  1172. AfdAcquireSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1173. //
  1174. // Setup the connection, so cancel routine can
  1175. // operate on it properly.
  1176. //
  1177. connection->ConnectIrp = NULL;
  1178. IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = connection;
  1179. IoSetCancelRoutine (Irp, AfdSanCancelConnect);
  1180. if (Irp->Cancel) {
  1181. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  1182. KIRQL cancelIrql;
  1183. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1184. //
  1185. // Cancel routine is running, let it complete
  1186. //
  1187. IoAcquireCancelSpinLock (&cancelIrql);
  1188. IoReleaseCancelSpinLock (cancelIrql);
  1189. }
  1190. else {
  1191. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1192. }
  1193. AfdSanReleaseConnection (listenEndpoint, connection, TRUE);
  1194. status = STATUS_CANCELLED;
  1195. goto complete;
  1196. }
  1197. IoMarkIrpPending (Irp);
  1198. connection->Endpoint = listenEndpoint;
  1199. REFERENCE_ENDPOINT (listenEndpoint);
  1200. connection->ConnectIrp = Irp;
  1201. connection->SanConnection = TRUE;
  1202. connection->State = AfdConnectionStateUnaccepted;
  1203. InitializeListHead (&irpList);
  1204. //
  1205. // Try to find AcceptEx or Listen IRP to complete.
  1206. //
  1207. while (1) {
  1208. PIRP waitForListenIrp;
  1209. if (!IS_DELAYED_ACCEPTANCE_ENDPOINT (listenEndpoint)) {
  1210. if (AfdServiceSuperAccept (listenEndpoint, connection, &lockHandle, &irpList)) {
  1211. goto CompleteIrps;
  1212. }
  1213. }
  1214. //
  1215. // Complete listen IRPs until we find the one that has enough space
  1216. // for the remote address.
  1217. //
  1218. if (IsListEmpty( &listenEndpoint->Common.VcListening.ListeningIrpListHead ) )
  1219. break;
  1220. //
  1221. // Get a pointer to the current IRP, and get a pointer to the
  1222. // current stack lockation.
  1223. //
  1224. waitForListenIrp = CONTAINING_RECORD(
  1225. listenEndpoint->Common.VcListening.ListeningIrpListHead.Flink,
  1226. IRP,
  1227. Tail.Overlay.ListEntry
  1228. );
  1229. //
  1230. // Take the first IRP off the listening list.
  1231. //
  1232. RemoveEntryList(
  1233. &waitForListenIrp->Tail.Overlay.ListEntry
  1234. );
  1235. waitForListenIrp->Tail.Overlay.ListEntry.Flink = NULL;
  1236. IF_DEBUG(SAN_SWITCH) {
  1237. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1238. "AfdSanConnectHandler: completing IRP %lx\n",
  1239. waitForListenIrp ));
  1240. }
  1241. status = AfdServiceWaitForListen (waitForListenIrp,
  1242. connection,
  1243. &lockHandle);
  1244. if (NT_SUCCESS (status)) {
  1245. ObDereferenceObject (listenFileObject);
  1246. return STATUS_PENDING;
  1247. }
  1248. //
  1249. // Synchronize with cancel routine if it is running
  1250. //
  1251. if (IoSetCancelRoutine (waitForListenIrp, NULL)==NULL) {
  1252. KIRQL cancelIrql;
  1253. //
  1254. // The cancel routine won't find the IRP on the list
  1255. // Just make sure it completes before we complete the IRP.
  1256. //
  1257. IoAcquireCancelSpinLock (&cancelIrql);
  1258. IoReleaseCancelSpinLock (cancelIrql);
  1259. }
  1260. IoCompleteRequest (waitForListenIrp, AfdPriorityBoost);
  1261. AfdAcquireSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1262. }
  1263. //
  1264. // At this point, we still hold the AFD spinlock.
  1265. // and we could find matching listen request.
  1266. // Put the connection on unaccepted list.
  1267. //
  1268. InsertTailList(
  1269. &listenEndpoint->Common.VcListening.UnacceptedConnectionListHead,
  1270. &connection->ListEntry
  1271. );
  1272. IF_DEBUG(SAN_SWITCH) {
  1273. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1274. "AfdSanConnectHandler: unaccepted, conn-%p\n",
  1275. connection));
  1276. }
  1277. //
  1278. // Listening endpoint is never a specifically SAN endpoint.
  1279. // Poll/EventSelect events on it are handled like on a regular
  1280. // TCP/IP endpoint - no need for special tricks like on connected/accepted
  1281. // endpoints.
  1282. //
  1283. AfdIndicateEventSelectEvent(
  1284. listenEndpoint,
  1285. AFD_POLL_ACCEPT,
  1286. STATUS_SUCCESS
  1287. );
  1288. AfdReleaseSpinLock (&listenEndpoint->SpinLock, &lockHandle);
  1289. //
  1290. // If there are outstanding polls waiting for a connection on this
  1291. // endpoint, complete them.
  1292. //
  1293. AfdIndicatePollEvent(
  1294. listenEndpoint,
  1295. AFD_POLL_ACCEPT,
  1296. STATUS_SUCCESS
  1297. );
  1298. CompleteIrps:
  1299. //
  1300. // Complete previously failed accept irps if any.
  1301. //
  1302. while (!IsListEmpty (&irpList)) {
  1303. PIRP irp;
  1304. irp = CONTAINING_RECORD (irpList.Flink, IRP, Tail.Overlay.ListEntry);
  1305. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  1306. IoCompleteRequest (irp, AfdPriorityBoost);
  1307. }
  1308. ObDereferenceObject (listenFileObject);
  1309. return STATUS_PENDING;
  1310. }
  1311. else {
  1312. status = STATUS_INSUFFICIENT_RESOURCES;
  1313. }
  1314. UPDATE_ENDPOINT2 (listenEndpoint,
  1315. "AfdSanConnectHandler, accept failed with status: %lx",
  1316. status);
  1317. complete:
  1318. if (listenFileObject!=NULL) {
  1319. ObDereferenceObject (listenFileObject);
  1320. }
  1321. Irp->IoStatus.Status = status;
  1322. IoCompleteRequest (Irp, AfdPriorityBoost);
  1323. return status;
  1324. }
  1325. NTSTATUS
  1326. AfdSanFastCompleteAccept (
  1327. IN PFILE_OBJECT FileObject,
  1328. IN ULONG IoctlCode,
  1329. IN KPROCESSOR_MODE RequestorMode,
  1330. IN PVOID InputBuffer,
  1331. IN ULONG InputBufferLength,
  1332. IN PVOID OutputBuffer,
  1333. IN ULONG OutputBufferLength,
  1334. OUT PUINT_PTR Information
  1335. )
  1336. /*++
  1337. Routine Description:
  1338. Completes the Accept operation initiated by the SAN provider
  1339. Arguments:
  1340. FileObject - SAN helper object - communication channel between the
  1341. switch and AFD in the process.
  1342. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_CMPL_ACCEPT)
  1343. RequestorMode - mode of the caller
  1344. InputBuffer - input parameters for the operation (AFD_SWITCH_CONTEXT_INFO)
  1345. SocketHandle - handle of the accepting endpoint
  1346. SwitchContext - switch context associated with the endpoint
  1347. InputBufferLength - sizeof(AFD_SWITCH_CONTEXT_INFO)
  1348. OutputBuffer - data to copy into the AcceptEx receive buffer
  1349. OutputBufferLength - size of received data
  1350. Information - pointer for buffer to place return information into, unused
  1351. Return Value:
  1352. STATUS_SUCCESS - operation succeeded
  1353. STATUS_INVALID_HANDLE - helper endpoint or switch socket is of incorrect type
  1354. STATUS_INVALID_PARAMETER - input buffer is of incorrect size.
  1355. STATIS_LOCAL_DISCONNECT - accept was aborted by the application.
  1356. other - failed when attempting to access accept socket, input buffer, or switch context.
  1357. --*/
  1358. {
  1359. NTSTATUS status;
  1360. PIRP acceptIrp;
  1361. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1362. PFILE_OBJECT sanFileObject;
  1363. AFD_SWITCH_CONTEXT_INFO contextInfo;
  1364. PAFD_ENDPOINT sanEndpoint, sanHlprEndpoint;
  1365. PVOID context;
  1366. *Information = 0;
  1367. try {
  1368. #ifdef _WIN64
  1369. if (IoIs32bitProcess (NULL)) {
  1370. PAFD_SWITCH_CONTEXT_INFO32 contextInfo32;
  1371. if (InputBufferLength<sizeof (*contextInfo32)) {
  1372. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1373. }
  1374. if (RequestorMode!=KernelMode) {
  1375. ProbeForRead (InputBuffer,
  1376. sizeof (*contextInfo32),
  1377. PROBE_ALIGNMENT32 (AFD_SWITCH_CONTEXT_INFO32));
  1378. }
  1379. contextInfo32 = InputBuffer;
  1380. contextInfo.SocketHandle = contextInfo32->SocketHandle;
  1381. contextInfo.SwitchContext = contextInfo32->SwitchContext;
  1382. }
  1383. else
  1384. #endif _WIN64
  1385. {
  1386. if (InputBufferLength<sizeof (contextInfo)) {
  1387. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1388. }
  1389. if (RequestorMode!=KernelMode) {
  1390. ProbeForRead (InputBuffer,
  1391. sizeof (contextInfo),
  1392. PROBE_ALIGNMENT (AFD_SWITCH_CONTEXT_INFO));
  1393. }
  1394. contextInfo = *((PAFD_SWITCH_CONTEXT_INFO)InputBuffer);
  1395. }
  1396. if (contextInfo.SwitchContext==NULL) {
  1397. IF_DEBUG(SAN_SWITCH) {
  1398. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1399. "AFD: Switch context is NULL in AfdSanFastCompleteAccept\n"));
  1400. }
  1401. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1402. }
  1403. if (RequestorMode!=KernelMode) {
  1404. ProbeForWrite (contextInfo.SwitchContext,
  1405. sizeof (*contextInfo.SwitchContext),
  1406. PROBE_ALIGNMENT (AFD_SWITCH_CONTEXT));
  1407. }
  1408. }
  1409. except (AFD_EXCEPTION_FILTER (&status)) {
  1410. return status;
  1411. }
  1412. sanHlprEndpoint = FileObject->FsContext;
  1413. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  1414. status = AfdSanReferenceSwitchSocketByHandle (
  1415. contextInfo.SocketHandle,
  1416. (IoctlCode>>14)&3,
  1417. RequestorMode,
  1418. sanHlprEndpoint,
  1419. contextInfo.SwitchContext,
  1420. &sanFileObject
  1421. );
  1422. if (!NT_SUCCESS (status)) {
  1423. return status;
  1424. }
  1425. sanEndpoint = sanFileObject->FsContext;
  1426. //
  1427. // Make sure that endpoints are of correct type
  1428. //
  1429. context = AfdLockEndpointContext (sanEndpoint);
  1430. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1431. if (!sanEndpoint->EndpointCleanedUp &&
  1432. sanEndpoint->State==AfdEndpointStateOpen) {
  1433. //
  1434. // See if accept IRP is still there
  1435. //
  1436. if (!IsListEmpty (&sanEndpoint->Common.SanEndp.IrpList)) {
  1437. AFD_SWITCH_CONTEXT localContext = {0,0,0,0};
  1438. acceptIrp = CONTAINING_RECORD (
  1439. sanEndpoint->Common.SanEndp.IrpList.Flink,
  1440. IRP,
  1441. Tail.Overlay.ListEntry);
  1442. RemoveEntryList (&acceptIrp->Tail.Overlay.ListEntry);
  1443. acceptIrp->Tail.Overlay.ListEntry.Flink = NULL;
  1444. sanEndpoint->Common.SanEndp.SelectEventsActive = AFD_POLL_SEND;
  1445. sanEndpoint->State = AfdEndpointStateConnected;
  1446. sanEndpoint->DisableFastIoSend = TRUE;
  1447. sanEndpoint->DisableFastIoRecv = TRUE;
  1448. sanEndpoint->EnableSendEvent = TRUE;
  1449. ASSERT (sanEndpoint->Common.SanEndp.LocalContext==NULL);
  1450. sanEndpoint->Common.SanEndp.LocalContext = &localContext;
  1451. AFD_END_STATE_CHANGE (sanEndpoint);
  1452. AfdIndicateEventSelectEvent (sanEndpoint, AFD_POLL_SEND, STATUS_SUCCESS);
  1453. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1454. AfdIndicatePollEvent (sanEndpoint, AFD_POLL_SEND, STATUS_SUCCESS);
  1455. status = AfdSanPollMerge (sanEndpoint, &localContext);
  1456. sanEndpoint->Common.SanEndp.LocalContext = NULL;
  1457. IF_DEBUG(SAN_SWITCH) {
  1458. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1459. "AfdFastSanCompleteAccept: endp-%p, irp-%p\n",
  1460. sanEndpoint,
  1461. acceptIrp));
  1462. }
  1463. if (IoSetCancelRoutine (acceptIrp, NULL)==NULL) {
  1464. KIRQL cancelIrql;
  1465. //
  1466. // Irp is being cancelled, sync up with cancel routine
  1467. //
  1468. IoAcquireCancelSpinLock (&cancelIrql);
  1469. IoReleaseCancelSpinLock (cancelIrql);
  1470. }
  1471. //
  1472. // Copy receive data if passed and IRP has buffer for it
  1473. //
  1474. if ((OutputBufferLength>0) && (acceptIrp->MdlAddress!=NULL)) {
  1475. try {
  1476. ULONG bytesCopied;
  1477. NTSTATUS tdiStatus;
  1478. tdiStatus = TdiCopyBufferToMdl (
  1479. OutputBuffer,
  1480. 0,
  1481. OutputBufferLength,
  1482. acceptIrp->MdlAddress,
  1483. 0,
  1484. &bytesCopied);
  1485. ASSERT (NT_SUCCESS (tdiStatus));
  1486. *Information = bytesCopied;
  1487. acceptIrp->IoStatus.Information = bytesCopied;
  1488. }
  1489. except (AFD_EXCEPTION_FILTER (&status)) {
  1490. //
  1491. // Even if copy failed, we still have to complete
  1492. // the accept IRP because we have already removed
  1493. // cancel routine and modified endpoint state.
  1494. //
  1495. }
  1496. }
  1497. else {
  1498. acceptIrp->IoStatus.Information = 0;
  1499. }
  1500. acceptIrp->IoStatus.Status = status;
  1501. //
  1502. // Complete the accept IRP.
  1503. //
  1504. IoCompleteRequest (acceptIrp, AfdPriorityBoost);
  1505. //
  1506. // undo the references done in AfdAcceptCore()
  1507. //
  1508. ASSERT( InterlockedDecrement( &sanEndpoint->ObReferenceBias ) >= 0 );
  1509. ObDereferenceObject (sanFileObject);
  1510. }
  1511. else {
  1512. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1513. status = STATUS_LOCAL_DISCONNECT;
  1514. }
  1515. }
  1516. else {
  1517. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1518. status = STATUS_INVALID_HANDLE;
  1519. }
  1520. AfdUnlockEndpointContext (sanEndpoint, context);
  1521. UPDATE_ENDPOINT2 (sanEndpoint, "AfdSanFastCompletAccept, status: %lx", status);
  1522. ObDereferenceObject (sanFileObject); // undo reference we did earlier in this routine
  1523. return status;
  1524. }
  1525. //
  1526. // Macros to make request/context passing code readable.
  1527. //
  1528. #define AfdSanRequestInfo Tail.Overlay
  1529. #define AfdSanRequestCtx DriverContext[0]
  1530. #define AfdSanSwitchCtx DriverContext[1]
  1531. #define AfdSanProcessId DriverContext[2]
  1532. #define AfdSanHelperEndp DriverContext[3]
  1533. NTSTATUS
  1534. FASTCALL
  1535. AfdSanRedirectRequest (
  1536. IN PIRP Irp,
  1537. IN PIO_STACK_LOCATION IrpSp
  1538. )
  1539. /*++
  1540. Routine Description:
  1541. Redirects file system Read/Write IRP to SAN provider
  1542. Arguments:
  1543. Irp - the to be redirected.
  1544. IrpSp - current stack location
  1545. Return Value:
  1546. Status of the redirect operation.
  1547. --*/
  1548. {
  1549. PAFD_ENDPOINT sanEndpoint;
  1550. NTSTATUS status;
  1551. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1552. ULONG_PTR requestInfo;
  1553. ULONG requestType;
  1554. PVOID requestCtx;
  1555. BOOLEAN postRequest = FALSE;;
  1556. Irp->IoStatus.Information = 0;
  1557. //
  1558. // Get the endpoint and validate it.
  1559. //
  1560. sanEndpoint = IrpSp->FileObject->FsContext;
  1561. ASSERT (IS_SAN_ENDPOINT (sanEndpoint));
  1562. //
  1563. // Make sure Irp has not been cancelled meanwhile
  1564. //
  1565. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1566. IoSetCancelRoutine (Irp, AfdSanCancelRequest);
  1567. if (Irp->Cancel) {
  1568. //
  1569. // Oops, let it go
  1570. //
  1571. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  1572. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1573. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  1574. KIRQL cancelIrql;
  1575. //
  1576. // Cancel routine must be running, make sure
  1577. // it complete before we complete the IRP
  1578. //
  1579. IoAcquireCancelSpinLock (&cancelIrql);
  1580. IoReleaseCancelSpinLock (cancelIrql);
  1581. }
  1582. status = STATUS_CANCELLED;
  1583. goto complete;
  1584. }
  1585. if (sanEndpoint->State!=AfdEndpointStateConnected) {
  1586. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1587. status = STATUS_INVALID_CONNECTION;
  1588. goto complete;
  1589. }
  1590. if (sanEndpoint->Common.SanEndp.CtxTransferStatus!=STATUS_PENDING &&
  1591. sanEndpoint->Common.SanEndp.CtxTransferStatus!=STATUS_MORE_PROCESSING_REQUIRED) {
  1592. if (!NT_SUCCESS (sanEndpoint->Common.SanEndp.CtxTransferStatus)) {
  1593. status = sanEndpoint->Common.SanEndp.CtxTransferStatus;
  1594. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  1595. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1596. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  1597. KIRQL cancelIrql;
  1598. //
  1599. // Cancel routine must be running, make sure
  1600. // it complete before we complete the IRP
  1601. //
  1602. IoAcquireCancelSpinLock (&cancelIrql);
  1603. IoReleaseCancelSpinLock (cancelIrql);
  1604. }
  1605. goto complete;
  1606. }
  1607. //
  1608. // Get the request information based on IRP MJ code
  1609. //
  1610. switch (IrpSp->MajorFunction) {
  1611. case IRP_MJ_READ:
  1612. requestType = AFD_SWITCH_REQUEST_READ;
  1613. requestInfo = IrpSp->Parameters.Read.Length;
  1614. break;
  1615. case IRP_MJ_WRITE:
  1616. requestType = AFD_SWITCH_REQUEST_WRITE;
  1617. requestInfo = IrpSp->Parameters.Write.Length;
  1618. break;
  1619. default:
  1620. ASSERT (!"Unsupported IRP Major Function");
  1621. __assume (0);
  1622. }
  1623. //
  1624. // Generate request context that uniquely identifies
  1625. // it among other requests on the same endpoint.
  1626. //
  1627. requestCtx = AFD_SWITCH_MAKE_REQUEST_CONTEXT(
  1628. sanEndpoint->Common.SanEndp.RequestId,
  1629. requestType);
  1630. sanEndpoint->Common.SanEndp.RequestId += 1;
  1631. //
  1632. // Store the request context in the Irp and insert it into
  1633. // the list
  1634. //
  1635. Irp->AfdSanRequestInfo.AfdSanRequestCtx = requestCtx;
  1636. postRequest = TRUE;
  1637. UPDATE_ENDPOINT (sanEndpoint);
  1638. }
  1639. else {
  1640. Irp->AfdSanRequestInfo.AfdSanRequestCtx = NULL;
  1641. UPDATE_ENDPOINT (sanEndpoint);
  1642. }
  1643. //
  1644. // We are going to pend this IRP, mark it so
  1645. //
  1646. IoMarkIrpPending (Irp);
  1647. InsertTailList (&sanEndpoint->Common.SanEndp.IrpList,
  1648. &Irp->Tail.Overlay.ListEntry);
  1649. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1650. IF_DEBUG(SAN_SWITCH) {
  1651. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1652. "AfdSanRedirectRequest: endp-%p, irp-%p, context-%p\n",
  1653. sanEndpoint, Irp, requestCtx));
  1654. }
  1655. if (postRequest) {
  1656. AfdSanNotifyRequest (sanEndpoint, requestCtx, STATUS_SUCCESS, requestInfo);
  1657. }
  1658. return STATUS_PENDING;
  1659. complete:
  1660. //
  1661. // Failure before we queued the IRP, complete and return
  1662. // status to the caller.
  1663. //
  1664. Irp->IoStatus.Status = status;
  1665. IoCompleteRequest (Irp, AfdPriorityBoost);
  1666. return status;
  1667. }
  1668. NTSTATUS
  1669. AfdSanFastCompleteRequest (
  1670. IN PFILE_OBJECT FileObject,
  1671. IN ULONG IoctlCode,
  1672. IN KPROCESSOR_MODE RequestorMode,
  1673. IN PVOID InputBuffer,
  1674. IN ULONG InputBufferLength,
  1675. IN PVOID OutputBuffer,
  1676. IN ULONG OutputBufferLength,
  1677. OUT PUINT_PTR Information
  1678. )
  1679. /*++
  1680. Routine Description:
  1681. Completes the redirected read/write request processed by SAN provider
  1682. Arguments:
  1683. FileObject - SAN helper object - communication channel between the
  1684. switch and AFD in the process.
  1685. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_CMPL_ACCEPT)
  1686. RequestorMode - mode of the caller
  1687. InputBuffer - input parameters for the operation (AFD_SWITCH_REQUEST_INFO)
  1688. SocketHandle - SAN endpoint on which to complete the request
  1689. SwitchContext - switch context associated with endpoint
  1690. to validate the handle-endpoint association
  1691. RequestContext - value that identifies the request to complete
  1692. RequestStatus - status with which to complete the request (
  1693. STATUS_PENDING has special meaning, request
  1694. is not completed - merely data is copied)
  1695. DataOffset - offset in the request buffer to read/write the data
  1696. InputBufferLength - sizeof (AFD_SWITCH_REQUEST_INFO)
  1697. OutputBuffer - switch buffer to read/write data
  1698. OutputBufferLength - length of the buffer
  1699. Information - pointer to buffer to return number of bytes copied
  1700. Return Value:
  1701. STATUS_SUCCESS - operation succeeded
  1702. STATUS_INVALID_HANDLE - helper or SAN endpoint is of incorrect type
  1703. STATUS_INVALID_PARAMETER - input buffer is of incorrect size.
  1704. STATUS_CANCELLED - request to be completed has already been cancelled
  1705. other - failed when attempting to access SAN endpoint, input buffer or output buffers.
  1706. --*/
  1707. {
  1708. NTSTATUS status;
  1709. PIO_STACK_LOCATION irpSp;
  1710. PIRP irp;
  1711. ULONG bytesCopied;
  1712. AFD_LOCK_QUEUE_HANDLE lockHandle;
  1713. PFILE_OBJECT sanFileObject;
  1714. AFD_SWITCH_REQUEST_INFO requestInfo;
  1715. PAFD_ENDPOINT sanEndpoint, sanHlprEndpoint;
  1716. *Information = 0;
  1717. try {
  1718. #ifdef _WIN64
  1719. if (IoIs32bitProcess (NULL)) {
  1720. PAFD_SWITCH_REQUEST_INFO32 requestInfo32;
  1721. if (InputBufferLength<sizeof (*requestInfo32)) {
  1722. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1723. }
  1724. if (RequestorMode!=KernelMode) {
  1725. ProbeForRead (InputBuffer,
  1726. sizeof (*requestInfo32),
  1727. PROBE_ALIGNMENT32 (AFD_SWITCH_REQUEST_INFO32));
  1728. }
  1729. requestInfo32 = InputBuffer;
  1730. requestInfo.SocketHandle = requestInfo32->SocketHandle;
  1731. requestInfo.SwitchContext = requestInfo32->SwitchContext;
  1732. requestInfo.RequestContext = requestInfo32->RequestContext;
  1733. requestInfo.RequestStatus = requestInfo32->RequestStatus;
  1734. requestInfo.DataOffset = requestInfo32->DataOffset;
  1735. }
  1736. else
  1737. #endif _WIN64
  1738. {
  1739. if (InputBufferLength<sizeof (requestInfo)) {
  1740. return STATUS_INVALID_PARAMETER;
  1741. }
  1742. if (RequestorMode!=KernelMode) {
  1743. ProbeForRead (InputBuffer,
  1744. sizeof (requestInfo),
  1745. PROBE_ALIGNMENT (AFD_SWITCH_REQUEST_INFO));
  1746. }
  1747. requestInfo = *((PAFD_SWITCH_REQUEST_INFO)InputBuffer);
  1748. }
  1749. if (requestInfo.SwitchContext==NULL) {
  1750. IF_DEBUG(SAN_SWITCH) {
  1751. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1752. "AFD: Switch context is NULL in AfdSanFastCompleteRequest\n"));
  1753. }
  1754. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1755. }
  1756. }
  1757. except (AFD_EXCEPTION_FILTER (&status)) {
  1758. return status;
  1759. }
  1760. sanHlprEndpoint = FileObject->FsContext;
  1761. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  1762. status = AfdSanReferenceSwitchSocketByHandle (
  1763. requestInfo.SocketHandle,
  1764. (IoctlCode>>14)&3,
  1765. RequestorMode,
  1766. sanHlprEndpoint,
  1767. requestInfo.SwitchContext,
  1768. &sanFileObject
  1769. );
  1770. if (!NT_SUCCESS (status)) {
  1771. return status;
  1772. }
  1773. sanEndpoint = sanFileObject->FsContext;
  1774. //
  1775. // Find and dequeue the request in question
  1776. //
  1777. irp = AfdSanDequeueRequest (sanEndpoint, requestInfo.RequestContext);
  1778. if (irp!=NULL) {
  1779. IF_DEBUG(SAN_SWITCH) {
  1780. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  1781. "AfdSanFastCompleteRequest: endp-%p, irp-%p, context-%p, status-%lx\n",
  1782. sanEndpoint, irp,
  1783. requestInfo.RequestContext,
  1784. requestInfo.RequestStatus));
  1785. }
  1786. //
  1787. // Expect the operation to succeed
  1788. //
  1789. status = STATUS_SUCCESS;
  1790. //
  1791. // Get IRP stack location and perform data copy
  1792. //
  1793. irpSp = IoGetCurrentIrpStackLocation (irp);
  1794. switch (irpSp->MajorFunction) {
  1795. case IRP_MJ_READ:
  1796. //
  1797. // Read request, data is copied from switch buffer
  1798. // to the request MDL
  1799. //
  1800. ASSERT (AFD_SWITCH_REQUEST_TYPE(requestInfo.RequestContext)==AFD_SWITCH_REQUEST_READ);
  1801. if (NT_SUCCESS (requestInfo.RequestStatus) &&
  1802. (MmGetMdlByteCount (irp->MdlAddress)>requestInfo.DataOffset)) {
  1803. if (irp->MdlAddress!=NULL) {
  1804. try {
  1805. if (RequestorMode!=KernelMode) {
  1806. ProbeForRead (OutputBuffer,
  1807. OutputBufferLength,
  1808. sizeof (UCHAR));
  1809. }
  1810. status = TdiCopyBufferToMdl (
  1811. OutputBuffer,
  1812. 0,
  1813. OutputBufferLength,
  1814. irp->MdlAddress,
  1815. requestInfo.DataOffset,
  1816. &bytesCopied
  1817. );
  1818. *Information = bytesCopied;
  1819. ASSERT (irp->IoStatus.Information==requestInfo.DataOffset);
  1820. irp->IoStatus.Information += bytesCopied;
  1821. }
  1822. except (AFD_EXCEPTION_FILTER (&status)) {
  1823. }
  1824. }
  1825. else {
  1826. //
  1827. // Indicate to the switch that offset
  1828. // is outside of the buffer
  1829. //
  1830. status = STATUS_INVALID_PARAMETER;
  1831. }
  1832. }
  1833. break;
  1834. case IRP_MJ_WRITE:
  1835. //
  1836. // Write request, data is copied to switch buffer
  1837. // from the request MDL
  1838. //
  1839. ASSERT (AFD_SWITCH_REQUEST_TYPE(requestInfo.RequestContext)==AFD_SWITCH_REQUEST_WRITE);
  1840. if (NT_SUCCESS (requestInfo.RequestStatus) &&
  1841. (irp->MdlAddress!=NULL)) {
  1842. if (MmGetMdlByteCount (irp->MdlAddress)>requestInfo.DataOffset) {
  1843. try {
  1844. if (RequestorMode!=KernelMode) {
  1845. ProbeForWrite (OutputBuffer,
  1846. OutputBufferLength,
  1847. sizeof (UCHAR));
  1848. }
  1849. status = TdiCopyMdlToBuffer (
  1850. irp->MdlAddress,
  1851. requestInfo.DataOffset,
  1852. OutputBuffer,
  1853. 0,
  1854. OutputBufferLength,
  1855. &bytesCopied
  1856. );
  1857. *Information = bytesCopied;
  1858. ASSERT (irp->IoStatus.Information==requestInfo.DataOffset);
  1859. irp->IoStatus.Information += bytesCopied;
  1860. }
  1861. except (AFD_EXCEPTION_FILTER (&status)) {
  1862. }
  1863. }
  1864. else {
  1865. //
  1866. // Indicate to the switch that offset
  1867. // is outside of the buffer
  1868. //
  1869. status = STATUS_INVALID_PARAMETER;
  1870. }
  1871. }
  1872. break;
  1873. default:
  1874. ASSERT (!"Unsupported IRP Major Function");
  1875. __assume (0);
  1876. }
  1877. //
  1878. // If switch did not ask to pend the request, complete it
  1879. //
  1880. if (NT_SUCCESS (status) && requestInfo.RequestStatus!=STATUS_PENDING) {
  1881. //
  1882. // Prepeare the request for completion
  1883. //
  1884. irp->IoStatus.Status = AfdValidateStatus (requestInfo.RequestStatus);
  1885. IoCompleteRequest (irp, AfdPriorityBoost);
  1886. }
  1887. else {
  1888. //
  1889. // Otherwise, put it back into the queue
  1890. //
  1891. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1892. IoSetCancelRoutine (irp, AfdSanCancelRequest);
  1893. //
  1894. // Of course, we need to make sure that request
  1895. // was not cancelled while we were processing it.
  1896. //
  1897. if (!irp->Cancel) {
  1898. InsertHeadList (&sanEndpoint->Common.SanEndp.IrpList,
  1899. &irp->Tail.Overlay.ListEntry);
  1900. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1901. }
  1902. else {
  1903. //
  1904. // Request has already been cancelled
  1905. //
  1906. ASSERT (irp->Tail.Overlay.ListEntry.Flink == NULL);
  1907. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  1908. if (IoSetCancelRoutine (irp, NULL)==NULL) {
  1909. KIRQL cancelIrql;
  1910. //
  1911. // Cancel routine is running, synchronize with
  1912. // it
  1913. //
  1914. IoAcquireCancelSpinLock (&cancelIrql);
  1915. IoReleaseCancelSpinLock (cancelIrql);
  1916. }
  1917. //
  1918. // Complete the request and indicate to the
  1919. // switch that it was cancelled
  1920. //
  1921. irp->IoStatus.Status = STATUS_CANCELLED;
  1922. IoCompleteRequest (irp, AfdPriorityBoost);
  1923. status = STATUS_CANCELLED;
  1924. }
  1925. }
  1926. }
  1927. else {
  1928. //
  1929. // Could not find the request, it must have been
  1930. // cancelled already
  1931. //
  1932. status = STATUS_CANCELLED;
  1933. }
  1934. UPDATE_ENDPOINT2 (sanEndpoint, "AfdSanFastCompleteRequest, status: %lx", status);
  1935. ObDereferenceObject (sanFileObject);
  1936. return status;
  1937. }
  1938. NTSTATUS
  1939. AfdSanFastCompleteIo (
  1940. IN PFILE_OBJECT FileObject,
  1941. IN ULONG IoctlCode,
  1942. IN KPROCESSOR_MODE RequestorMode,
  1943. IN PVOID InputBuffer,
  1944. IN ULONG InputBufferLength,
  1945. IN PVOID OutputBuffer,
  1946. IN ULONG OutputBufferLength,
  1947. OUT PUINT_PTR Information
  1948. )
  1949. /*++
  1950. Routine Description:
  1951. Simulates async IO completion for the switch.
  1952. Arguments:
  1953. FileObject - SAN endpoint on which to complete the IO
  1954. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_CMPL_IO)
  1955. RequestorMode - mode of the caller
  1956. InputBuffer - input parameters for the operation (IO_STATUS_BLOCK)
  1957. Status - final operation status
  1958. Information - associated information (number of bytes
  1959. transferred to/from request buffer(s))
  1960. InputBufferLength - sizeof (IO_STATUS_BLOCK)
  1961. OutputBuffer - unused
  1962. OutputBufferLength - unused
  1963. Information - pointer to buffer to return number of bytes transferred
  1964. Return Value:
  1965. STATUS_INVALID_PARAMETER - input buffer is of invalid size.
  1966. other - status of the IO operation or failure code when attempting to access input buffer.
  1967. --*/
  1968. {
  1969. NTSTATUS status;
  1970. PAGED_CODE ();
  1971. #ifdef _WIN64
  1972. if (IoIs32bitProcess (NULL)) {
  1973. if (InputBufferLength>=sizeof (IO_STATUS_BLOCK32)) {
  1974. // Carefully write status info
  1975. try {
  1976. if (RequestorMode!=KernelMode) {
  1977. ProbeForRead (InputBuffer,
  1978. sizeof (IO_STATUS_BLOCK32),
  1979. PROBE_ALIGNMENT32 (IO_STATUS_BLOCK32));
  1980. }
  1981. *Information = ((PIO_STATUS_BLOCK32)InputBuffer)->Information;
  1982. status = AfdValidateStatus (((PIO_STATUS_BLOCK32)InputBuffer)->Status);
  1983. }
  1984. except (AFD_EXCEPTION_FILTER (&status)) {
  1985. }
  1986. }
  1987. else {
  1988. status = STATUS_INVALID_PARAMETER;
  1989. }
  1990. }
  1991. else
  1992. #endif //_WIN64
  1993. {
  1994. if (InputBufferLength>=sizeof (IO_STATUS_BLOCK)) {
  1995. // Carefully write status info
  1996. try {
  1997. if (RequestorMode!=KernelMode) {
  1998. ProbeForRead (InputBuffer,
  1999. sizeof (IO_STATUS_BLOCK),
  2000. PROBE_ALIGNMENT (IO_STATUS_BLOCK));
  2001. }
  2002. *Information = ((PIO_STATUS_BLOCK)InputBuffer)->Information;
  2003. status = AfdValidateStatus (((PIO_STATUS_BLOCK)InputBuffer)->Status);
  2004. }
  2005. except (AFD_EXCEPTION_FILTER (&status)) {
  2006. }
  2007. }
  2008. else {
  2009. status = STATUS_INVALID_PARAMETER;
  2010. }
  2011. }
  2012. UPDATE_ENDPOINT2 (FileObject->FsContext, "AfdSanFastCompletIo, status: %lx", status);
  2013. return status;
  2014. }
  2015. NTSTATUS
  2016. AfdSanFastRefreshEndpoint (
  2017. IN PFILE_OBJECT FileObject,
  2018. IN ULONG IoctlCode,
  2019. IN KPROCESSOR_MODE RequestorMode,
  2020. IN PVOID InputBuffer,
  2021. IN ULONG InputBufferLength,
  2022. IN PVOID OutputBuffer,
  2023. IN ULONG OutputBufferLength,
  2024. OUT PUINT_PTR Information
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. Refreshes endpoint so it can be used again in AcceptEx
  2029. Arguments:
  2030. FileObject - SAN helper object - communication channel between the
  2031. switch and AFD in the process.
  2032. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_REFRESH_ENDP)
  2033. RequestorMode - mode of the caller
  2034. InputBuffer - input parameters for the operation (AFD_SWITCH_CONTEXT_INFO)
  2035. SocketHandle - SAN endpoint on which to referesh
  2036. SwitchContext - switch context associated with endpoint
  2037. to validate the handle-endpoint association
  2038. InputBufferLength - unused
  2039. OutputBuffer - unused
  2040. OutputBufferLength - unused
  2041. Information - pointer for buffer to place return information into, unused
  2042. Return Value:
  2043. STATUS_SUCCESS - operation succeeded
  2044. STATUS_INVALID_HANDLE - helper endpoint or switch socket is of incorrect type
  2045. other - failed when attempting to access SAN socket.
  2046. --*/
  2047. {
  2048. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2049. KIRQL oldIrql;
  2050. NTSTATUS status;
  2051. PFILE_OBJECT sanFileObject;
  2052. AFD_SWITCH_CONTEXT_INFO contextInfo;
  2053. PAFD_ENDPOINT sanEndpoint, sanHlprEndpoint;
  2054. *Information = 0;
  2055. try {
  2056. #ifdef _WIN64
  2057. if (IoIs32bitProcess (NULL)) {
  2058. PAFD_SWITCH_CONTEXT_INFO32 contextInfo32;
  2059. if (InputBufferLength<sizeof (*contextInfo32)) {
  2060. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2061. }
  2062. if (RequestorMode!=KernelMode) {
  2063. ProbeForRead (InputBuffer,
  2064. sizeof (*contextInfo32),
  2065. PROBE_ALIGNMENT32 (AFD_SWITCH_CONTEXT_INFO32));
  2066. }
  2067. contextInfo32 = InputBuffer;
  2068. contextInfo.SocketHandle = contextInfo32->SocketHandle;
  2069. contextInfo.SwitchContext = contextInfo32->SwitchContext;
  2070. }
  2071. else
  2072. #endif _WIN64
  2073. {
  2074. if (InputBufferLength<sizeof (contextInfo)) {
  2075. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2076. }
  2077. if (RequestorMode!=KernelMode) {
  2078. ProbeForRead (InputBuffer,
  2079. sizeof (contextInfo),
  2080. PROBE_ALIGNMENT (AFD_SWITCH_CONTEXT_INFO));
  2081. }
  2082. contextInfo = *((PAFD_SWITCH_CONTEXT_INFO)InputBuffer);
  2083. }
  2084. if (contextInfo.SwitchContext==NULL) {
  2085. IF_DEBUG(SAN_SWITCH) {
  2086. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2087. "AFD: Switch context is NULL in AfdSanFastRefereshEndpoint\n"));
  2088. }
  2089. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2090. }
  2091. if (RequestorMode!=KernelMode) {
  2092. ProbeForWrite (contextInfo.SwitchContext,
  2093. sizeof (*contextInfo.SwitchContext),
  2094. PROBE_ALIGNMENT (AFD_SWITCH_CONTEXT));
  2095. }
  2096. }
  2097. except (AFD_EXCEPTION_FILTER (&status)) {
  2098. return status;
  2099. }
  2100. sanHlprEndpoint = FileObject->FsContext;
  2101. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  2102. status = AfdSanReferenceSwitchSocketByHandle (
  2103. contextInfo.SocketHandle,
  2104. (IoctlCode>>14)&3,
  2105. RequestorMode,
  2106. sanHlprEndpoint,
  2107. contextInfo.SwitchContext,
  2108. &sanFileObject
  2109. );
  2110. if (!NT_SUCCESS (status)) {
  2111. return status;
  2112. }
  2113. sanEndpoint = sanFileObject->FsContext;
  2114. //
  2115. // Just make sure that endpoints are of correct type
  2116. // and in correct state
  2117. //
  2118. KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
  2119. AfdAcquireSpinLockAtDpcLevel (&sanEndpoint->SpinLock, &lockHandle);
  2120. if (!sanEndpoint->EndpointCleanedUp &&
  2121. sanEndpoint->State==AfdEndpointStateConnected) {
  2122. //
  2123. // Reset the state so we can't get anymore IRPs
  2124. //
  2125. sanEndpoint->State = AfdEndpointStateTransmitClosing;
  2126. //
  2127. // Cleanup all IRPs on the endpoint.
  2128. //
  2129. if (!IsListEmpty (&sanEndpoint->Common.SanEndp.IrpList)) {
  2130. PIRP irp;
  2131. PDRIVER_CANCEL cancelRoutine;
  2132. KIRQL cancelIrql;
  2133. AfdReleaseSpinLockFromDpcLevel (&sanEndpoint->SpinLock, &lockHandle);
  2134. //
  2135. // Acquire cancel spinlock and endpoint spinlock in
  2136. // this order and recheck the IRP list
  2137. //
  2138. IoAcquireCancelSpinLock (&cancelIrql);
  2139. ASSERT (cancelIrql==DISPATCH_LEVEL);
  2140. AfdAcquireSpinLockAtDpcLevel (&sanEndpoint->SpinLock, &lockHandle);
  2141. //
  2142. // While list is not empty attempt to cancel the IRPs
  2143. //
  2144. while (!IsListEmpty (&sanEndpoint->Common.SanEndp.IrpList)) {
  2145. irp = CONTAINING_RECORD (
  2146. sanEndpoint->Common.SanEndp.IrpList.Flink,
  2147. IRP,
  2148. Tail.Overlay.ListEntry);
  2149. //
  2150. // Reset the cancel routine.
  2151. //
  2152. cancelRoutine = IoSetCancelRoutine (irp, NULL);
  2153. if (cancelRoutine!=NULL) {
  2154. //
  2155. // Cancel routine was not NULL, cancel it here.
  2156. // If someone else attempts to complete this IRP
  2157. // it will have to wait at least until cancel
  2158. // spinlock is released, so we can release
  2159. // the endpoint spinlock
  2160. //
  2161. AfdReleaseSpinLockFromDpcLevel (&sanEndpoint->SpinLock, &lockHandle);
  2162. irp->CancelIrql = DISPATCH_LEVEL;
  2163. irp->Cancel = TRUE;
  2164. (*cancelRoutine) (AfdDeviceObject, irp);
  2165. }
  2166. IoAcquireCancelSpinLock (&cancelIrql);
  2167. ASSERT (cancelIrql==DISPATCH_LEVEL);
  2168. AfdAcquireSpinLockAtDpcLevel (&sanEndpoint->SpinLock, &lockHandle);
  2169. }
  2170. IoReleaseCancelSpinLock (DISPATCH_LEVEL);
  2171. }
  2172. if (sanEndpoint->Common.SanEndp.SanHlpr!=NULL) {
  2173. DEREFERENCE_ENDPOINT (sanEndpoint->Common.SanEndp.SanHlpr);
  2174. }
  2175. //
  2176. // Make sure we cleanup all the fields since they will be
  2177. // treated as other part (VC) of the endpoint union.
  2178. //
  2179. RtlZeroMemory (&sanEndpoint->Common.SanEndp,
  2180. sizeof (sanEndpoint->Common.SanEndp));
  2181. //
  2182. // Reinitialize the endpoint structure.
  2183. //
  2184. sanEndpoint->Type = AfdBlockTypeEndpoint;
  2185. if (sanEndpoint->AddressFileObject!=NULL) {
  2186. //
  2187. // This is TransmitFile after SuperConnect
  2188. //
  2189. sanEndpoint->State = AfdEndpointStateBound;
  2190. }
  2191. else {
  2192. //
  2193. // This is TransmitFile after SuperAccept
  2194. //
  2195. sanEndpoint->State = AfdEndpointStateOpen;
  2196. }
  2197. sanEndpoint->DisconnectMode = 0;
  2198. sanEndpoint->EndpointStateFlags = 0;
  2199. AfdRecordEndpointsReused ();
  2200. status = STATUS_SUCCESS;
  2201. }
  2202. else {
  2203. status = STATUS_INVALID_HANDLE;
  2204. }
  2205. AfdReleaseSpinLockFromDpcLevel (&sanEndpoint->SpinLock, &lockHandle);
  2206. KeLowerIrql (oldIrql);
  2207. UPDATE_ENDPOINT2 (sanEndpoint, "AfdSanFastRefreshEndpoint, status: %lx", status);
  2208. ObDereferenceObject( sanFileObject );
  2209. return status;
  2210. }
  2211. NTSTATUS
  2212. AfdSanFastGetPhysicalAddr (
  2213. IN PFILE_OBJECT FileObject,
  2214. IN ULONG IoctlCode,
  2215. IN KPROCESSOR_MODE RequestorMode,
  2216. IN PVOID InputBuffer,
  2217. IN ULONG InputBufferLength,
  2218. IN PVOID OutputBuffer,
  2219. IN ULONG OutputBufferLength,
  2220. OUT PUINT_PTR Information
  2221. )
  2222. /*++
  2223. Routine Description:
  2224. Returns physical address corresponding to provided virtual address.
  2225. Arguments:
  2226. FileObject - SAN helper object - communication channel between the
  2227. switch and AFD in the process.
  2228. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_GET_PHYSICAL_ADDR)
  2229. RequestorMode - mode of the caller
  2230. InputBuffer - user mode virtual address
  2231. InputBufferLength - access mode
  2232. OutputBuffer - Buffer to place physical address into.
  2233. OutputBufferLength - sizeof (PHYSICAL_ADDRESS)
  2234. Information - pointer for buffer to place the size of the return information into
  2235. Return Value:
  2236. STATUS_SUCCESS - operation succeeded
  2237. STATUS_INVALID_HANDLE - helper endpoint is of incorrect type
  2238. STATUS_INVALID_PARAMETER - invalid access mode.
  2239. STATUS_BUFFER_TOO_SMALL - output buffer is of incorrect size.
  2240. other - failed when attempting to access input virtual address or output buffer.
  2241. --*/
  2242. {
  2243. #ifndef TEST_RDMA_CACHE
  2244. return STATUS_INVALID_PARAMETER;
  2245. #else
  2246. NTSTATUS status;
  2247. PVOID Va; // virtual address
  2248. ULONG accessMode;
  2249. PAFD_ENDPOINT sanHlprEndpoint;
  2250. PAGED_CODE ();
  2251. *Information = 0;
  2252. Va = InputBuffer;
  2253. accessMode = InputBufferLength;
  2254. if (accessMode!=MEM_READ_ACCESS &&
  2255. accessMode!=MEM_WRITE_ACCESS) {
  2256. return STATUS_INVALID_PARAMETER;
  2257. }
  2258. if (OutputBufferLength<sizeof(PHYSICAL_ADDRESS)) {
  2259. return STATUS_BUFFER_TOO_SMALL;
  2260. }
  2261. sanHlprEndpoint = FileObject->FsContext;
  2262. if (!IS_SAN_HELPER(sanHlprEndpoint) ||
  2263. sanHlprEndpoint->OwningProcess!=IoGetCurrentProcess ()) {
  2264. return STATUS_INVALID_HANDLE;
  2265. }
  2266. try {
  2267. if (RequestorMode!=KernelMode) {
  2268. //
  2269. // Do some verification on the app buffer. Make sure it is
  2270. // mapped and that it is a user-mode address with appropriate
  2271. // read or write permissions
  2272. //
  2273. if (accessMode == MEM_READ_ACCESS) {
  2274. ProbeAndReadChar ((PCHAR)Va);
  2275. }
  2276. else {
  2277. ProbeForWriteChar ((PCHAR)Va);
  2278. }
  2279. }
  2280. //
  2281. // Validate the output structure if it comes from the user mode
  2282. // application
  2283. //
  2284. if (RequestorMode != KernelMode ) {
  2285. ASSERT(sizeof(PHYSICAL_ADDRESS) == sizeof(QUAD));
  2286. ProbeForWriteQuad ((PQUAD)OutputBuffer);
  2287. }
  2288. *(PPHYSICAL_ADDRESS)OutputBuffer = MmGetPhysicalAddress(Va);
  2289. *Information = sizeof(PHYSICAL_ADDRESS);
  2290. status = STATUS_SUCCESS;
  2291. } except( AFD_EXCEPTION_FILTER(&status) ) {
  2292. }
  2293. UPDATE_ENDPOINT2 (sanHlprEndpoint, "AfdSanGetPhysicalAddress, status: %lx", status);
  2294. return status;
  2295. #endif // 0
  2296. }
  2297. NTSTATUS
  2298. AfdSanFastGetServicePid (
  2299. IN PFILE_OBJECT FileObject,
  2300. IN ULONG IoctlCode,
  2301. IN KPROCESSOR_MODE RequestorMode,
  2302. IN PVOID InputBuffer,
  2303. IN ULONG InputBufferLength,
  2304. IN PVOID OutputBuffer,
  2305. IN ULONG OutputBufferLength,
  2306. OUT PUINT_PTR Information
  2307. )
  2308. /*++
  2309. Routine Description:
  2310. Returns PID of SAN service process.
  2311. Arguments:
  2312. FileObject - SAN helper object - communication channel between the
  2313. switch and AFD in the process.
  2314. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_GET_PHYSICAL_ADDR)
  2315. RequestorMode - mode of the caller
  2316. InputBuffer - NULL, ignored
  2317. InputBufferLength - 0, ignored
  2318. OutputBuffer - NULL, ignored
  2319. OutputBufferLength - 0, ignored
  2320. Information - pointer to buffer to return pid of the SAN service process
  2321. Return Value:
  2322. STATUS_SUCCESS - operation succeeded
  2323. STATUS_INVALID_HANDLE - helper endpoint is of incorrect type
  2324. --*/
  2325. {
  2326. PAFD_ENDPOINT sanHlprEndpoint;
  2327. PAGED_CODE ();
  2328. *Information = 0;
  2329. sanHlprEndpoint = FileObject->FsContext;
  2330. if (!IS_SAN_HELPER(sanHlprEndpoint) ||
  2331. sanHlprEndpoint->OwningProcess!=IoGetCurrentProcess ()) {
  2332. return STATUS_INVALID_HANDLE;
  2333. }
  2334. *Information = (ULONG_PTR)AfdSanServicePid;
  2335. UPDATE_ENDPOINT2 (sanHlprEndpoint,
  2336. "AfdSanFastGetServicePid, pid: %lx",
  2337. HandleToUlong (AfdSanServicePid));
  2338. return STATUS_SUCCESS;
  2339. }
  2340. NTSTATUS
  2341. AfdSanFastSetServiceProcess (
  2342. IN PFILE_OBJECT FileObject,
  2343. IN ULONG IoctlCode,
  2344. IN KPROCESSOR_MODE RequestorMode,
  2345. IN PVOID InputBuffer,
  2346. IN ULONG InputBufferLength,
  2347. IN PVOID OutputBuffer,
  2348. IN ULONG OutputBufferLength,
  2349. OUT PUINT_PTR Information
  2350. )
  2351. /*++
  2352. Routine Description:
  2353. Set the service helper endpoint
  2354. Arguments:
  2355. FileObject - SAN helper object - communication channel between the
  2356. switch and AFD in the process.
  2357. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_GET_PHYSICAL_ADDR)
  2358. RequestorMode - mode of the caller
  2359. InputBuffer - NULL, ignored
  2360. InputBufferLength - 0, ignored
  2361. OutputBuffer - NULL, ignored
  2362. OutputBufferLength - 0, ignored
  2363. Information - 0, ignored
  2364. Return Value:
  2365. STATUS_SUCCESS - operation succeeded
  2366. STATUS_INVALID_HANDLE - helper endpoint is of incorrect type
  2367. STATUS_ACCESS_DENIED - process is not priviliged enough to become service process.
  2368. STATUS_ADDRESS_ALREADY_EXISTS - service process has already registered.
  2369. --*/
  2370. {
  2371. NTSTATUS status;
  2372. PAFD_ENDPOINT sanHlprEndpoint;
  2373. PAGED_CODE ();
  2374. *Information = 0;
  2375. sanHlprEndpoint = FileObject->FsContext;
  2376. if (!IS_SAN_HELPER(sanHlprEndpoint) ||
  2377. sanHlprEndpoint->OwningProcess!=IoGetCurrentProcess ()) {
  2378. return STATUS_INVALID_HANDLE;
  2379. }
  2380. if (!sanHlprEndpoint->AdminAccessGranted) {
  2381. return STATUS_ACCESS_DENIED;
  2382. }
  2383. KeEnterCriticalRegion ();
  2384. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  2385. if (AfdSanServiceHelper==NULL) {
  2386. AfdSanServiceHelper = sanHlprEndpoint;
  2387. AfdSanServicePid = PsGetCurrentProcessId ();
  2388. //
  2389. // HACKHACK. Force IO subsystem to call us when last handle to the file is closed
  2390. // in any given process. We are specifically intersted only in this process
  2391. // only.
  2392. //
  2393. FileObject->LockOperation = TRUE;
  2394. status = STATUS_SUCCESS;
  2395. }
  2396. else if (AfdSanServiceHelper==sanHlprEndpoint) {
  2397. ASSERT (FileObject->LockOperation == TRUE);
  2398. status = STATUS_SUCCESS;
  2399. }
  2400. else {
  2401. status = STATUS_ADDRESS_ALREADY_EXISTS;
  2402. }
  2403. ExReleaseResourceLite (AfdResource);
  2404. KeLeaveCriticalRegion ();
  2405. UPDATE_ENDPOINT2 (sanHlprEndpoint, "AfdSanFastSetServiceProcess, status: %lx", status);
  2406. return status;
  2407. }
  2408. NTSTATUS
  2409. AfdSanFastProviderChange (
  2410. IN PFILE_OBJECT FileObject,
  2411. IN ULONG IoctlCode,
  2412. IN KPROCESSOR_MODE RequestorMode,
  2413. IN PVOID InputBuffer,
  2414. IN ULONG InputBufferLength,
  2415. IN PVOID OutputBuffer,
  2416. IN ULONG OutputBufferLength,
  2417. OUT PUINT_PTR Information
  2418. )
  2419. /*++
  2420. Routine Description:
  2421. Notifies interested processes of SAN provider addition/deletion/change
  2422. Arguments:
  2423. FileObject - SAN helper object for the service process communication channel between the
  2424. switch and AFD in the process.
  2425. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_PROVIDER_CHANGE)
  2426. RequestorMode - mode of the caller
  2427. InputBuffer - NULL, ignored
  2428. InputBufferLength - 0, ignored
  2429. OutputBuffer - NULL, ignored
  2430. OutputBufferLength - 0, ignored
  2431. Information - 0, ignored
  2432. Return Value:
  2433. STATUS_SUCCESS - operation succeeded
  2434. STATUS_INVALID_HANDLE - helper endpoint is of incorrect type
  2435. STATUS_ACCESS_DENIED - helper endpoint is not for the service process.
  2436. --*/
  2437. {
  2438. PAFD_ENDPOINT sanHlprEndpoint;
  2439. *Information = 0;
  2440. sanHlprEndpoint = FileObject->FsContext;
  2441. if (!IS_SAN_HELPER(sanHlprEndpoint) ||
  2442. sanHlprEndpoint->OwningProcess!=IoGetCurrentProcess ()) {
  2443. return STATUS_INVALID_HANDLE;
  2444. }
  2445. if (sanHlprEndpoint!=AfdSanServiceHelper) {
  2446. return STATUS_ACCESS_DENIED;
  2447. }
  2448. UPDATE_ENDPOINT2 (sanHlprEndpoint,
  2449. "AfdSanFastProviderChange, seq num: %ld",
  2450. AfdSanProviderListSeqNum);
  2451. AfdSanProcessAddrListForProviderChange (NULL);
  2452. return STATUS_SUCCESS;
  2453. }
  2454. NTSTATUS
  2455. FASTCALL
  2456. AfdSanAddrListChange (
  2457. IN PIRP Irp,
  2458. IN PIO_STACK_LOCATION IrpSp
  2459. )
  2460. /*++
  2461. Routine Description:
  2462. Processes address SAN list change IRP
  2463. Notifies both of address list changes and SAN
  2464. provider changes.
  2465. Arguments:
  2466. Irp - Pointer to I/O request packet.
  2467. IrpSp - pointer to the stack location to use for this request.
  2468. Return Value:
  2469. NTSTATUS -- Indicates whether the request was successfully queued.
  2470. --*/
  2471. {
  2472. PAFD_ENDPOINT sanHlprEndpoint;
  2473. NTSTATUS status;
  2474. sanHlprEndpoint = IrpSp->FileObject->FsContext;
  2475. if (IS_SAN_HELPER(sanHlprEndpoint) &&
  2476. sanHlprEndpoint->OwningProcess==IoGetCurrentProcess ()) {
  2477. if (AfdSanProviderListSeqNum==0 ||
  2478. sanHlprEndpoint->Common.SanHlpr.Plsn==AfdSanProviderListSeqNum) {
  2479. status = AfdAddressListChange (Irp, IrpSp);
  2480. if (AfdSanProviderListSeqNum==0 ||
  2481. sanHlprEndpoint->Common.SanHlpr.Plsn==AfdSanProviderListSeqNum) {
  2482. UPDATE_ENDPOINT (sanHlprEndpoint);
  2483. }
  2484. else {
  2485. UPDATE_ENDPOINT (sanHlprEndpoint);
  2486. AfdSanProcessAddrListForProviderChange (sanHlprEndpoint);
  2487. }
  2488. return status;
  2489. }
  2490. else {
  2491. sanHlprEndpoint->Common.SanHlpr.Plsn = AfdSanProviderListSeqNum;
  2492. status = STATUS_SUCCESS;
  2493. Irp->IoStatus.Information = sanHlprEndpoint->Common.SanHlpr.Plsn;
  2494. UPDATE_ENDPOINT (sanHlprEndpoint);
  2495. }
  2496. }
  2497. else {
  2498. status = STATUS_INVALID_PARAMETER;
  2499. Irp->IoStatus.Information = 0;
  2500. UPDATE_ENDPOINT (sanHlprEndpoint);
  2501. }
  2502. Irp->IoStatus.Status = status;
  2503. IoCompleteRequest (Irp, AfdPriorityBoost);
  2504. return status;
  2505. }
  2506. NTSTATUS
  2507. FASTCALL
  2508. AfdSanAcquireContext (
  2509. IN PIRP Irp,
  2510. IN PIO_STACK_LOCATION IrpSp
  2511. )
  2512. /*++
  2513. Routine Description:
  2514. Requests trasfer of the socket context to the current process.
  2515. Arguments:
  2516. Irp - acquire conect IRP
  2517. IrpSp - current stack location
  2518. Return Value:
  2519. STATUS_PENDING - operation was successfully enqued
  2520. --*/
  2521. {
  2522. NTSTATUS status;
  2523. AFD_SWITCH_ACQUIRE_CTX_INFO ctxInfo;
  2524. PAFD_ENDPOINT sanHlprEndpoint, sanEndpoint;
  2525. PFILE_OBJECT sanFileObject = NULL;
  2526. PVOID requestCtx;
  2527. AFD_LOCK_QUEUE_HANDLE lockHandle;
  2528. BOOLEAN doTransfer;
  2529. try {
  2530. #ifdef _WIN64
  2531. if (IoIs32bitProcess (Irp)) {
  2532. PAFD_SWITCH_ACQUIRE_CTX_INFO ctxInfo32;
  2533. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof (*ctxInfo32)) {
  2534. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2535. }
  2536. if (Irp->RequestorMode!=KernelMode) {
  2537. ProbeForRead (IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  2538. sizeof (*ctxInfo32),
  2539. PROBE_ALIGNMENT32 (AFD_SWITCH_ACQUIRE_CTX_INFO32));
  2540. }
  2541. ctxInfo32 = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  2542. ctxInfo.SocketHandle = ctxInfo32->SocketHandle;
  2543. ctxInfo.SwitchContext = ctxInfo32->SwitchContext;
  2544. ctxInfo.SocketCtxBuf = ctxInfo32->SocketCtxBuf;
  2545. ctxInfo.SocketCtxBufSize = ctxInfo32->SocketCtxBufSize;
  2546. }
  2547. else
  2548. #endif //_WIN64
  2549. {
  2550. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength<sizeof (ctxInfo)) {
  2551. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2552. }
  2553. if (Irp->RequestorMode!=KernelMode) {
  2554. ProbeForRead (IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  2555. sizeof (ctxInfo),
  2556. PROBE_ALIGNMENT (AFD_SWITCH_ACQUIRE_CTX_INFO));
  2557. }
  2558. ctxInfo = *((PAFD_SWITCH_ACQUIRE_CTX_INFO)IrpSp->Parameters.DeviceIoControl.Type3InputBuffer);
  2559. }
  2560. Irp->MdlAddress = IoAllocateMdl (ctxInfo.SocketCtxBuf, // VirtualAddress
  2561. ctxInfo.SocketCtxBufSize, // Length
  2562. FALSE, // SecondaryBuffer
  2563. TRUE, // ChargeQuota
  2564. NULL); // Irp
  2565. if (Irp->MdlAddress==NULL) {
  2566. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  2567. }
  2568. MmProbeAndLockPages(
  2569. Irp->MdlAddress, // MemoryDescriptorList
  2570. Irp->RequestorMode, // AccessMode
  2571. IoWriteAccess // Operation
  2572. );
  2573. if (MmGetSystemAddressForMdlSafe(Irp->MdlAddress, LowPagePriority)==NULL) {
  2574. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  2575. }
  2576. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength>0) {
  2577. Irp->MdlAddress->Next = IoAllocateMdl (Irp->UserBuffer, // VirtualAddress
  2578. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,// Length
  2579. FALSE, // SecondaryBuffer
  2580. TRUE, // ChargeQuota
  2581. NULL); // Irp
  2582. if (Irp->MdlAddress->Next==NULL) {
  2583. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  2584. }
  2585. MmProbeAndLockPages(
  2586. Irp->MdlAddress->Next, // MemoryDescriptorList
  2587. Irp->RequestorMode, // AccessMode
  2588. IoWriteAccess // Operation
  2589. );
  2590. if (MmGetSystemAddressForMdlSafe(Irp->MdlAddress->Next, LowPagePriority)==NULL) {
  2591. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  2592. }
  2593. }
  2594. }
  2595. except (AFD_EXCEPTION_FILTER (&status)) {
  2596. //
  2597. // Cleanup partially processed MDLs since IO subsystem can't do it.
  2598. //
  2599. while (Irp->MdlAddress!=NULL) {
  2600. PMDL mdl = Irp->MdlAddress;
  2601. Irp->MdlAddress = mdl->Next;
  2602. mdl->Next = NULL;
  2603. if (mdl->MdlFlags & MDL_PAGES_LOCKED) {
  2604. MmUnlockPages (mdl);
  2605. }
  2606. IoFreeMdl (mdl);
  2607. }
  2608. goto complete;
  2609. }
  2610. status = ObReferenceObjectByHandle (
  2611. ctxInfo.SocketHandle,
  2612. (IrpSp->Parameters.DeviceIoControl.IoControlCode>>14)&3,
  2613. *IoFileObjectType,
  2614. Irp->RequestorMode,
  2615. (PVOID)&sanFileObject,
  2616. NULL
  2617. );
  2618. if (!NT_SUCCESS (status)) {
  2619. goto complete;
  2620. }
  2621. if (sanFileObject->DeviceObject!=AfdDeviceObject) {
  2622. status = STATUS_INVALID_HANDLE;
  2623. goto complete;
  2624. }
  2625. sanHlprEndpoint = IrpSp->FileObject->FsContext;
  2626. sanEndpoint = sanFileObject->FsContext;
  2627. IF_DEBUG(SAN_SWITCH) {
  2628. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2629. "AfdSanFastAcquireCtx: endp-%p.\n",
  2630. sanEndpoint));
  2631. }
  2632. //
  2633. // Just make sure that endpoints are of correct type
  2634. //
  2635. if (IS_SAN_HELPER(sanHlprEndpoint) &&
  2636. sanHlprEndpoint->OwningProcess==IoGetCurrentProcess () &&
  2637. IS_SAN_ENDPOINT(sanEndpoint)) {
  2638. if (sanEndpoint->Common.SanEndp.SanHlpr==AfdSanServiceHelper &&
  2639. sanHlprEndpoint==AfdSanServiceHelper &&
  2640. sanEndpoint->Common.SanEndp.CtxTransferStatus==STATUS_MORE_PROCESSING_REQUIRED) {
  2641. PVOID context;
  2642. ASSERT ((ULONG_PTR)sanEndpoint->Common.SanEndp.SavedContext>MM_USER_PROBE_ADDRESS);
  2643. context = AfdLockEndpointContext (sanEndpoint);
  2644. if (ctxInfo.SocketCtxBufSize <= sanEndpoint->Common.SanEndp.SavedContextLength &&
  2645. ctxInfo.SocketCtxBufSize +
  2646. IrpSp->Parameters.DeviceIoControl.OutputBufferLength >
  2647. sanEndpoint->Common.SanEndp.SavedContextLength) {
  2648. RtlCopyMemory (
  2649. MmGetSystemAddressForMdl (Irp->MdlAddress),
  2650. sanEndpoint->Common.SanEndp.SavedContext,
  2651. ctxInfo.SocketCtxBufSize);
  2652. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength!=0) {
  2653. Irp->IoStatus.Information =
  2654. sanEndpoint->Common.SanEndp.SavedContextLength-
  2655. ctxInfo.SocketCtxBufSize;
  2656. RtlCopyMemory (
  2657. MmGetSystemAddressForMdl (Irp->MdlAddress->Next),
  2658. (PCHAR)sanEndpoint->Common.SanEndp.SavedContext+
  2659. ctxInfo.SocketCtxBufSize,
  2660. Irp->IoStatus.Information);
  2661. }
  2662. else {
  2663. Irp->IoStatus.Information = 0;
  2664. }
  2665. AFD_FREE_POOL (sanEndpoint->Common.SanEndp.SavedContext, AFD_SAN_CONTEXT_POOL_TAG);
  2666. // sanEndpoint->Common.SanEndp.SavedContext = NULL;
  2667. sanEndpoint->Common.SanEndp.SwitchContext = ctxInfo.SwitchContext;
  2668. status = STATUS_SUCCESS;
  2669. }
  2670. else {
  2671. status = STATUS_BUFFER_TOO_SMALL;
  2672. }
  2673. AfdUnlockEndpointContext (sanEndpoint, context);
  2674. if (NT_SUCCESS (status)) {
  2675. UPDATE_ENDPOINT (sanEndpoint);
  2676. Irp->IoStatus.Status = status;
  2677. IoCompleteRequest (Irp, AfdPriorityBoost);
  2678. AfdSanRestartRequestProcessing (sanEndpoint, status);
  2679. ObDereferenceObject (sanFileObject);
  2680. return status;
  2681. }
  2682. }
  2683. else {
  2684. AfdAcquireSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  2685. //
  2686. // Make sure Irp has not been cancelled meanwhile
  2687. //
  2688. IoSetCancelRoutine (Irp, AfdSanCancelRequest);
  2689. if (Irp->Cancel) {
  2690. //
  2691. // Oops, let it go
  2692. //
  2693. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  2694. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  2695. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  2696. KIRQL cancelIrql;
  2697. //
  2698. // Cancel routine must be running, make sure
  2699. // it completes before we complete the IRP
  2700. //
  2701. IoAcquireCancelSpinLock (&cancelIrql);
  2702. IoReleaseCancelSpinLock (cancelIrql);
  2703. }
  2704. status = STATUS_CANCELLED;
  2705. goto complete;
  2706. }
  2707. if (sanEndpoint->Common.SanEndp.CtxTransferStatus!=STATUS_PENDING &&
  2708. sanEndpoint->Common.SanEndp.CtxTransferStatus!=STATUS_MORE_PROCESSING_REQUIRED) {
  2709. if (!NT_SUCCESS (sanEndpoint->Common.SanEndp.CtxTransferStatus)) {
  2710. status = sanEndpoint->Common.SanEndp.CtxTransferStatus;
  2711. Irp->Tail.Overlay.ListEntry.Flink = NULL;
  2712. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  2713. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  2714. KIRQL cancelIrql;
  2715. //
  2716. // Cancel routine must be running, make sure
  2717. // it completes before we complete the IRP
  2718. //
  2719. IoAcquireCancelSpinLock (&cancelIrql);
  2720. IoReleaseCancelSpinLock (cancelIrql);
  2721. }
  2722. goto complete;
  2723. }
  2724. //
  2725. // Generate request context that uniquely identifies
  2726. // it among other requests on the same endpoint.
  2727. //
  2728. requestCtx = AFD_SWITCH_MAKE_REQUEST_CONTEXT(
  2729. sanEndpoint->Common.SanEndp.RequestId,
  2730. AFD_SWITCH_REQUEST_TFCTX);
  2731. sanEndpoint->Common.SanEndp.RequestId += 1;
  2732. //
  2733. // Store the request context in the Irp and insert it into
  2734. // the list
  2735. //
  2736. Irp->AfdSanRequestInfo.AfdSanRequestCtx = requestCtx;
  2737. sanEndpoint->Common.SanEndp.CtxTransferStatus = STATUS_PENDING;
  2738. doTransfer = TRUE;
  2739. }
  2740. else {
  2741. Irp->AfdSanRequestInfo.AfdSanRequestCtx = NULL;
  2742. doTransfer = FALSE;
  2743. }
  2744. Irp->AfdSanRequestInfo.AfdSanSwitchCtx = ctxInfo.SwitchContext;
  2745. Irp->AfdSanRequestInfo.AfdSanProcessId = PsGetCurrentProcessId();
  2746. Irp->AfdSanRequestInfo.AfdSanHelperEndp = sanHlprEndpoint;
  2747. //
  2748. // We are going to pend this IRP, mark it so
  2749. //
  2750. IoMarkIrpPending (Irp);
  2751. InsertTailList (&sanEndpoint->Common.SanEndp.IrpList,
  2752. &Irp->Tail.Overlay.ListEntry);
  2753. IoGetCurrentIrpStackLocation(Irp)->FileObject = sanFileObject;
  2754. UPDATE_ENDPOINT (sanEndpoint);
  2755. AfdReleaseSpinLock (&sanEndpoint->SpinLock, &lockHandle);
  2756. IF_DEBUG(SAN_SWITCH) {
  2757. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2758. "AfdSanRedirectRequest: endp-%p, irp-%p, context-%p\n",
  2759. sanEndpoint, Irp, requestCtx));
  2760. }
  2761. if (doTransfer) {
  2762. if (!AfdSanNotifyRequest (sanEndpoint,
  2763. requestCtx,
  2764. STATUS_SUCCESS,
  2765. (ULONG_PTR)PsGetCurrentProcessId())) {
  2766. AfdSanRestartRequestProcessing (sanEndpoint, STATUS_SUCCESS);
  2767. }
  2768. }
  2769. //
  2770. // The request is in the queue or completed, we no longer need
  2771. // object reference.
  2772. //
  2773. ObDereferenceObject (sanFileObject);
  2774. return STATUS_PENDING;
  2775. }
  2776. }
  2777. else {
  2778. status = STATUS_INVALID_HANDLE;
  2779. }
  2780. UPDATE_ENDPOINT2 (sanEndpoint, "AfdSanAcquireContext, status: %lx", status);
  2781. complete:
  2782. if (sanFileObject!=NULL)
  2783. ObDereferenceObject (sanFileObject);
  2784. Irp->IoStatus.Status = status;
  2785. IoCompleteRequest (Irp, AfdPriorityBoost);
  2786. return status;
  2787. }
  2788. NTSTATUS
  2789. AfdSanFastTransferCtx (
  2790. IN PFILE_OBJECT FileObject,
  2791. IN ULONG IoctlCode,
  2792. IN KPROCESSOR_MODE RequestorMode,
  2793. IN PVOID InputBuffer,
  2794. IN ULONG InputBufferLength,
  2795. IN PVOID OutputBuffer,
  2796. IN ULONG OutputBufferLength,
  2797. OUT PUINT_PTR Information
  2798. )
  2799. /*++
  2800. Routine Description:
  2801. Requests AFD to transfer endpoint into another process context
  2802. Arguments:
  2803. FileObject - SAN helper object - communication channel between the
  2804. switch and AFD in the process.
  2805. IoctlCode - operation IOCTL code (IOCTL_AFD_SWITCH_TRANSFER_CTX)
  2806. RequestorMode - mode of the caller
  2807. InputBuffer - input parameters for the operation (AFD_SWITCH_TRANSFER_CTX_INFO)
  2808. SocketHandle - SAN endpoint to be transferred
  2809. RequestContext - value that identifies corresponding acquire request.
  2810. SocketCtxBuf - endpoint context buffer to copy destination process
  2811. acquire request
  2812. SocketCtxSize - size of the buffer to copy
  2813. RcvBufferArray - array of buffered data to transfer to
  2814. destination process acquire request
  2815. RcvBufferCount - number of elements in the array.
  2816. InputBufferLength - sizeof (AFD_SWITCH_TRANSFER_CTX_INFO)
  2817. OutputBuffer - unused
  2818. OutputBufferLength - unused
  2819. Information - pointer to buffer to return number of bytes copied
  2820. Return Value:
  2821. STATUS_SUCCESS - operation succeeded
  2822. STATUS_INVALID_HANDLE - helper endpoint or switch endpoint is of incorrect type
  2823. STATUS_INVALID_PARAMETER - invalid input buffer size.
  2824. other - failed when attempting to access san endpoint or input buffer(s).
  2825. --*/
  2826. {
  2827. NTSTATUS status;
  2828. AFD_SWITCH_TRANSFER_CTX_INFO ctxInfo;
  2829. PVOID context;
  2830. PAFD_ENDPOINT sanHlprEndpoint, sanEndpoint;
  2831. PFILE_OBJECT sanFileObject;
  2832. PIRP irp;
  2833. PIO_STACK_LOCATION irpSp;
  2834. #ifdef _WIN64
  2835. WSABUF localArray[8];
  2836. LPWSABUF pArray = localArray;
  2837. #endif
  2838. PAGED_CODE ();
  2839. try {
  2840. #ifdef _WIN64
  2841. if (IoIs32bitProcess (NULL)) {
  2842. PAFD_SWITCH_TRANSFER_CTX_INFO ctxInfo32;
  2843. ULONG i;
  2844. if (InputBufferLength<sizeof (*ctxInfo32)) {
  2845. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2846. }
  2847. if (RequestorMode!=KernelMode) {
  2848. ProbeForRead (InputBuffer,
  2849. sizeof (*ctxInfo32),
  2850. PROBE_ALIGNMENT32 (AFD_SWITCH_TRANSFER_CTX_INFO32));
  2851. }
  2852. ctxInfo32 = InputBuffer;
  2853. ctxInfo.SocketHandle = ctxInfo32->SocketHandle;
  2854. ctxInfo.SwitchContext = ctxInfo32->SwitchContext;
  2855. ctxInfo.RequestContext = ctxInfo32->RequestContext;
  2856. ctxInfo.SocketCtxBuf = ctxInfo32->SocketCtxBuf;
  2857. ctxInfo.SocketCtxBufSize = ctxInfo32->SocketCtxBufSize;
  2858. ctxInfo.RcvBufferArray = ctxInfo32->RcvBufferArray;
  2859. ctxInfo.RcvBufferCount = ctxInfo32->RcvBufferCount;
  2860. ctxInfo.Status = ctxInfo32->Status;
  2861. if (RequestorMode!=KernelMode) {
  2862. if (ctxInfo.SocketCtxBufSize==0 ||
  2863. ctxInfo.RcvBufferCount>(MAXULONG/sizeof (WSABUF32))) {
  2864. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2865. }
  2866. ProbeForRead (ctxInfo.SocketCtxBuf,
  2867. ctxInfo.SocketCtxBufSize,
  2868. sizeof (UCHAR));
  2869. ProbeForRead (ctxInfo.RcvBufferArray,
  2870. sizeof (WSABUF32)*ctxInfo.RcvBufferCount,
  2871. PROBE_ALIGNMENT32 (WSABUF32));
  2872. }
  2873. if (ctxInfo.RcvBufferCount>sizeof(localArray)/sizeof(localArray[0])) {
  2874. pArray = AFD_ALLOCATE_POOL_WITH_QUOTA (
  2875. NonPagedPool,
  2876. sizeof (WSABUF)*ctxInfo.RcvBufferCount,
  2877. AFD_TEMPORARY_POOL_TAG);
  2878. // AFD_ALLOCATE_POOL_WITH_QUOTA macro sets
  2879. // POOL_RAISE_IF_ALLOCATION_FAILURE flag
  2880. ASSERT (pArray!=NULL);
  2881. }
  2882. for (i=0; i<ctxInfo.RcvBufferCount; i++) {
  2883. pArray[i].buf = ctxInfo.RcvBufferArray[i].buf;
  2884. pArray[i].len = ctxInfo.RcvBufferArray[i].len;
  2885. }
  2886. ctxInfo.RcvBufferArray = pArray;
  2887. }
  2888. else
  2889. #endif //_WIN64
  2890. {
  2891. if (InputBufferLength<sizeof (ctxInfo)) {
  2892. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2893. }
  2894. if (RequestorMode!=KernelMode) {
  2895. ProbeForRead (InputBuffer,
  2896. sizeof (ctxInfo),
  2897. PROBE_ALIGNMENT (AFD_SWITCH_TRANSFER_CTX_INFO));
  2898. }
  2899. ctxInfo = *((PAFD_SWITCH_TRANSFER_CTX_INFO)InputBuffer);
  2900. if (RequestorMode!=KernelMode) {
  2901. if (ctxInfo.SocketCtxBufSize==0 ||
  2902. ctxInfo.RcvBufferCount>(MAXULONG/sizeof (WSABUF))) {
  2903. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2904. }
  2905. ProbeForRead (ctxInfo.SocketCtxBuf,
  2906. ctxInfo.SocketCtxBufSize,
  2907. sizeof (UCHAR));
  2908. ProbeForRead (ctxInfo.RcvBufferArray,
  2909. sizeof (ctxInfo.RcvBufferArray)*ctxInfo.RcvBufferCount,
  2910. PROBE_ALIGNMENT (WSABUF));
  2911. }
  2912. }
  2913. if (ctxInfo.SwitchContext==NULL) {
  2914. IF_DEBUG(SAN_SWITCH) {
  2915. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2916. "AFD: Switch context is NULL in AfdSanFastTransferCtx\n"));
  2917. }
  2918. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  2919. }
  2920. }
  2921. except (AFD_EXCEPTION_FILTER (&status)) {
  2922. goto complete;
  2923. }
  2924. ctxInfo.Status = AfdValidateStatus (ctxInfo.Status);
  2925. sanHlprEndpoint = FileObject->FsContext;
  2926. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  2927. status = AfdSanReferenceSwitchSocketByHandle (
  2928. ctxInfo.SocketHandle,
  2929. (IoctlCode>>14)&3,
  2930. RequestorMode,
  2931. sanHlprEndpoint,
  2932. ctxInfo.SwitchContext,
  2933. &sanFileObject
  2934. );
  2935. if (!NT_SUCCESS (status)) {
  2936. goto complete;
  2937. }
  2938. sanEndpoint = sanFileObject->FsContext;
  2939. IF_DEBUG(SAN_SWITCH) {
  2940. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  2941. "AfdSanFastTransferCtx: endp-%p.\n",
  2942. sanEndpoint));
  2943. }
  2944. if (ctxInfo.RequestContext==NULL ||
  2945. ctxInfo.RequestContext==AFD_SWITCH_MAKE_REQUEST_CONTEXT (0, AFD_SWITCH_REQUEST_TFCTX)) {
  2946. PVOID savedContext = NULL;
  2947. ULONG ctxLength;
  2948. if (NT_SUCCESS (ctxInfo.Status)) {
  2949. try {
  2950. ctxLength = ctxInfo.SocketCtxBufSize;
  2951. if (ctxInfo.RcvBufferCount>0)
  2952. ctxLength += AfdCalcBufferArrayByteLength(
  2953. ctxInfo.RcvBufferArray,
  2954. ctxInfo.RcvBufferCount);
  2955. savedContext = AFD_ALLOCATE_POOL (PagedPool,
  2956. ctxLength,
  2957. AFD_SAN_CONTEXT_POOL_TAG);
  2958. if (savedContext==NULL) {
  2959. ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
  2960. }
  2961. RtlCopyMemory (
  2962. savedContext,
  2963. ctxInfo.SocketCtxBuf,
  2964. ctxInfo.SocketCtxBufSize);
  2965. if (ctxInfo.RcvBufferCount>0) {
  2966. AfdCopyBufferArrayToBuffer (
  2967. (PUCHAR)savedContext+ctxInfo.SocketCtxBufSize,
  2968. ctxLength-ctxInfo.SocketCtxBufSize,
  2969. ctxInfo.RcvBufferArray,
  2970. ctxInfo.RcvBufferCount);
  2971. }
  2972. }
  2973. except (AFD_EXCEPTION_FILTER (&status)) {
  2974. }
  2975. if (NT_SUCCESS (status)) {
  2976. status = AfdSanDupEndpointIntoServiceProcess (sanFileObject,
  2977. savedContext,
  2978. ctxLength);
  2979. }
  2980. if (!NT_SUCCESS (status)) {
  2981. if (savedContext!=NULL) {
  2982. AFD_FREE_POOL (savedContext, AFD_SAN_CONTEXT_POOL_TAG);
  2983. }
  2984. AfdSanRestartRequestProcessing (sanEndpoint, status);
  2985. }
  2986. }
  2987. else {
  2988. AfdSanRestartRequestProcessing (sanEndpoint, ctxInfo.Status);
  2989. }
  2990. }
  2991. else {
  2992. irp = AfdSanDequeueRequest (sanEndpoint, ctxInfo.RequestContext);
  2993. if (irp!=NULL) {
  2994. //
  2995. // Get IRP stack location and perform data copy
  2996. //
  2997. irpSp = IoGetCurrentIrpStackLocation (irp);
  2998. if (NT_SUCCESS (ctxInfo.Status)) {
  2999. AFD_SWITCH_CONTEXT localContext;
  3000. status = STATUS_SUCCESS;
  3001. try {
  3002. if ( MmGetMdlByteCount(irp->MdlAddress)!=ctxInfo.SocketCtxBufSize ||
  3003. (ctxInfo.RcvBufferCount!=0 &&
  3004. irpSp->Parameters.DeviceIoControl.OutputBufferLength<
  3005. AfdCalcBufferArrayByteLength(
  3006. ctxInfo.RcvBufferArray,
  3007. ctxInfo.RcvBufferCount)) ){
  3008. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  3009. }
  3010. RtlCopyMemory (
  3011. MmGetSystemAddressForMdl (irp->MdlAddress),
  3012. ctxInfo.SocketCtxBuf,
  3013. ctxInfo.SocketCtxBufSize);
  3014. if (ctxInfo.RcvBufferCount>0) {
  3015. irp->IoStatus.Information =
  3016. AfdCopyBufferArrayToBuffer (
  3017. MmGetSystemAddressForMdl (irp->MdlAddress->Next),
  3018. irpSp->Parameters.DeviceIoControl.OutputBufferLength,
  3019. ctxInfo.RcvBufferArray,
  3020. ctxInfo.RcvBufferCount);
  3021. }
  3022. else {
  3023. irp->IoStatus.Information = 0;
  3024. }
  3025. }
  3026. except (AFD_EXCEPTION_FILTER (&status)) {
  3027. }
  3028. if (NT_SUCCESS (status)) {
  3029. //
  3030. // Now change sanEndpoint's SanHlpr and SwitchContext to point
  3031. // to the new address space and switch socket
  3032. //
  3033. context = AfdLockEndpointContext (sanEndpoint);
  3034. try {
  3035. localContext = *sanEndpoint->Common.SanEndp.SwitchContext;
  3036. }
  3037. except (AFD_EXCEPTION_FILTER(&status)) {
  3038. }
  3039. if (NT_SUCCESS (status)) {
  3040. KeAttachProcess (PsGetProcessPcb(((PAFD_ENDPOINT)irp->AfdSanRequestInfo.AfdSanHelperEndp)->OwningProcess));
  3041. try {
  3042. //
  3043. // Place info regarding select/eventselect events in SwitchContext
  3044. // of the new switch socket
  3045. //
  3046. *((PAFD_SWITCH_CONTEXT)irp->AfdSanRequestInfo.AfdSanSwitchCtx) = localContext;
  3047. }
  3048. except (AFD_EXCEPTION_FILTER(&status)) {
  3049. }
  3050. KeDetachProcess ();
  3051. if (NT_SUCCESS (status)) {
  3052. sanEndpoint->Common.SanEndp.SanHlpr = irp->AfdSanRequestInfo.AfdSanHelperEndp;
  3053. REFERENCE_ENDPOINT2 (sanEndpoint->Common.SanEndp.SanHlpr,
  3054. "Transfer TO %lx",
  3055. HandleToUlong (ctxInfo.SocketHandle) );
  3056. sanEndpoint->Common.SanEndp.SwitchContext = irp->AfdSanRequestInfo.AfdSanSwitchCtx;
  3057. //
  3058. // Reset implicit dup flag if it was set.
  3059. // We are satisfying explicit request for
  3060. // duplication.
  3061. //
  3062. sanEndpoint->Common.SanEndp.ImplicitDup = FALSE;
  3063. DEREFERENCE_ENDPOINT2 (sanHlprEndpoint,
  3064. "Transfer FROM %lx",
  3065. HandleToUlong (ctxInfo.SocketHandle));
  3066. }
  3067. }
  3068. AfdUnlockEndpointContext (sanEndpoint, context);
  3069. }
  3070. irp->IoStatus.Status = status;
  3071. ctxInfo.Status = status;
  3072. }
  3073. else {
  3074. irp->IoStatus.Status = ctxInfo.Status;
  3075. status = STATUS_SUCCESS;
  3076. }
  3077. IoCompleteRequest (irp, AfdPriorityBoost);
  3078. AfdSanRestartRequestProcessing (sanEndpoint, ctxInfo.Status);
  3079. }
  3080. else
  3081. status = STATUS_INVALID_PARAMETER;
  3082. }
  3083. UPDATE_ENDPOINT2 (sanEndpoint, "AfdSanFastTransferCtx, status: %lx", status);
  3084. ObDereferenceObject (sanFileObject);
  3085. complete:
  3086. #ifdef _WIN64
  3087. if (pArray!=localArray) {
  3088. AFD_FREE_POOL (pArray, AFD_TEMPORARY_POOL_TAG);
  3089. }
  3090. #endif //_WIN64
  3091. return status;
  3092. }
  3093. BOOLEAN
  3094. AfdSanFastUnlockAll (
  3095. IN PFILE_OBJECT FileObject,
  3096. IN PEPROCESS Process,
  3097. OUT PIO_STATUS_BLOCK IoStatus,
  3098. IN PDEVICE_OBJECT DeviceObject
  3099. )
  3100. /*++
  3101. Routine Description:
  3102. Called by the system when last handle to the file object in closed
  3103. in some process while other processes still have handles opened
  3104. This is only called on files that were marked as locked at some point of time.
  3105. Arguments:
  3106. FileObject - file object of interest
  3107. Process - process which has last handle being closed
  3108. IoStatus - buffer to return operation status and information
  3109. DeviceObject - device object with which file object is associated
  3110. Return Value:
  3111. TRUE - operation completed OK.
  3112. --*/
  3113. {
  3114. PAFD_ENDPOINT sanEndpoint;
  3115. PVOID context;
  3116. sanEndpoint = FileObject->FsContext;
  3117. if (IS_SAN_ENDPOINT (sanEndpoint)) {
  3118. context = AfdLockEndpointContext (sanEndpoint);
  3119. if (sanEndpoint->Common.SanEndp.SanHlpr!=NULL) {
  3120. if (sanEndpoint->Common.SanEndp.SanHlpr->OwningProcess==Process) {
  3121. if (sanEndpoint->Common.SanEndp.SanHlpr!=AfdSanServiceHelper) {
  3122. //
  3123. // Last handle in the process that owns the socket is being
  3124. // closed while there are handles to it in other processes.
  3125. // Need to transfer the context to the service process
  3126. //
  3127. if (PsGetProcessExitTime( ).QuadPart==0) {
  3128. IoSetIoCompletion (
  3129. sanEndpoint->Common.SanEndp.SanHlpr->Common.SanHlpr.IoCompletionPort,
  3130. sanEndpoint->Common.SanEndp.SwitchContext,
  3131. AFD_SWITCH_MAKE_REQUEST_CONTEXT (0, AFD_SWITCH_REQUEST_TFCTX),
  3132. STATUS_SUCCESS,
  3133. (ULONG_PTR)AfdSanServicePid,
  3134. FALSE // ChargeQuota - Don't, handle is going away, no
  3135. // way for the run-away app to mount an attack
  3136. );
  3137. UPDATE_ENDPOINT (sanEndpoint);
  3138. }
  3139. else {
  3140. //
  3141. // Process has already exited, not much we can do.
  3142. //
  3143. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_WARNING_LEVEL,
  3144. "AFD: Process %p has exited before SAN context could be transferred out.\n",
  3145. Process));
  3146. UPDATE_ENDPOINT (sanEndpoint);
  3147. }
  3148. }
  3149. }
  3150. else {
  3151. if (sanEndpoint->Common.SanEndp.ImplicitDup) {
  3152. //
  3153. // Process is exiting and the only handle is in the
  3154. // other process where the handle was duplicated
  3155. // impilictly (without application request, e.g.
  3156. // cross proceess accepting socket duplicated into
  3157. // listening process to complete the accept or socket
  3158. // duplication into service process while waiting on
  3159. // other process to request ownership).
  3160. //
  3161. if (ObReferenceObject (FileObject)==3) {
  3162. // Why are we checking for refcount of 3?
  3163. // 1 - Handle in the implicit process
  3164. // 1 - IO manager for this call
  3165. // 1 - we just added
  3166. UPDATE_ENDPOINT (sanEndpoint);
  3167. IoSetIoCompletion (
  3168. sanEndpoint->Common.SanEndp.SanHlpr->Common.SanHlpr.IoCompletionPort,
  3169. sanEndpoint->Common.SanEndp.SwitchContext,
  3170. AFD_SWITCH_MAKE_REQUEST_CONTEXT (0, AFD_SWITCH_REQUEST_CLSOC),
  3171. STATUS_SUCCESS,
  3172. (ULONG_PTR)0,
  3173. FALSE); // ChargeQuota - Don't, handle is going away, no
  3174. // way for the run-away app to mount an attack
  3175. }
  3176. ObDereferenceObject (FileObject);
  3177. }
  3178. }
  3179. }
  3180. AfdUnlockEndpointContext (sanEndpoint, context);
  3181. }
  3182. else if (sanEndpoint==AfdSanServiceHelper) {
  3183. ASSERT (IS_SAN_HELPER (sanEndpoint));
  3184. if (Process==sanEndpoint->OwningProcess) {
  3185. //
  3186. // Last handle to the service helper is being closed in
  3187. // the service process (there must be some duplicates around).
  3188. // We can no longer count on it, clear our global.
  3189. //
  3190. KeEnterCriticalRegion ();
  3191. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  3192. AfdSanServiceHelper = NULL;
  3193. ExReleaseResourceLite( AfdResource );
  3194. KeLeaveCriticalRegion ();
  3195. }
  3196. }
  3197. IoStatus->Status = STATUS_SUCCESS;
  3198. IoStatus->Information = 0;
  3199. return TRUE;
  3200. }
  3201. //
  3202. // Internal routines.
  3203. //
  3204. NTSTATUS
  3205. AfdSanAcceptCore (
  3206. PIRP AcceptIrp,
  3207. PFILE_OBJECT AcceptFileObject,
  3208. PAFD_CONNECTION Connection,
  3209. PAFD_LOCK_QUEUE_HANDLE LockHandle
  3210. )
  3211. /*++
  3212. Routine Description:
  3213. Accept the incoming SAN connection on endpoint provided
  3214. Arguments:
  3215. AcceptIrp - accept IRP to complete
  3216. AcceptFileObject - file object of accepting endpoint
  3217. Connection - pointer to connection object that represents the incoming connection
  3218. LockHandle - IRQL at which listening endpoint spinlock was taken on entry to this routine.
  3219. Return Value:
  3220. STATUS_PENDING - accept operation started OK
  3221. STATUS_REMOTE_DISCONNECT - connection being accepted was aborted by the remote.
  3222. STATUS_CANCELLED - accepting endpoint was closed or accept IRP cancelled
  3223. --*/
  3224. {
  3225. PIRP connectIrp;
  3226. PIO_STACK_LOCATION irpSp;
  3227. PAFD_SWITCH_CONNECT_INFO connectInfo;
  3228. PAFD_ENDPOINT listenEndpoint, acceptEndpoint;
  3229. HANDLE acceptHandle;
  3230. ULONG receiveLength;
  3231. PKPROCESS listenProcess;
  3232. ASSERT (LockHandle->LockHandle.OldIrql < DISPATCH_LEVEL);
  3233. irpSp = IoGetCurrentIrpStackLocation (AcceptIrp);
  3234. listenEndpoint = irpSp->FileObject->FsContext;
  3235. acceptEndpoint = AcceptFileObject->FsContext;
  3236. ASSERT (Connection->SanConnection);
  3237. //
  3238. // Snag the connect indication IRP
  3239. //
  3240. connectIrp = Connection->ConnectIrp;
  3241. ASSERT (connectIrp!=NULL);
  3242. Connection->ConnectIrp = NULL;
  3243. //
  3244. // Handle EventSelect signalling
  3245. //
  3246. listenEndpoint->EventsActive &= ~AFD_POLL_ACCEPT;
  3247. IF_DEBUG(EVENT_SELECT) {
  3248. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  3249. "AfdSanAcceptCore: Endp %p, Active %lx\n",
  3250. listenEndpoint,
  3251. listenEndpoint->EventsActive
  3252. ));
  3253. }
  3254. if (!IsListEmpty (&listenEndpoint->Common.VcListening.UnacceptedConnectionListHead ) ) {
  3255. AfdIndicateEventSelectEvent(
  3256. listenEndpoint,
  3257. AFD_POLL_ACCEPT,
  3258. STATUS_SUCCESS
  3259. );
  3260. }
  3261. //
  3262. // We no longer need the connection object for SAN
  3263. // endpoint, return it
  3264. //
  3265. Connection->Endpoint = NULL;
  3266. Connection->SanConnection = FALSE;
  3267. AfdSanReleaseConnection (listenEndpoint, Connection, FALSE);
  3268. DEREFERENCE_ENDPOINT (listenEndpoint);
  3269. if (IoSetCancelRoutine (connectIrp, NULL)==NULL) {
  3270. AfdReleaseSpinLock (&listenEndpoint->SpinLock, LockHandle);
  3271. connectIrp->IoStatus.Status = STATUS_CANCELLED;
  3272. connectIrp->IoStatus.Information = 0;
  3273. IoCompleteRequest (connectIrp, AfdPriorityBoost);
  3274. return STATUS_REMOTE_DISCONNECT;
  3275. }
  3276. AfdReleaseSpinLock (&listenEndpoint->SpinLock, LockHandle);
  3277. //
  3278. // Check that accept IRP and SAN connection IRP belong to the same process
  3279. //
  3280. if (IoThreadToProcess (AcceptIrp->Tail.Overlay.Thread)!=
  3281. IoThreadToProcess (connectIrp->Tail.Overlay.Thread)) {
  3282. //
  3283. // Listen process is different than the accepting one.
  3284. // We need to duplicate accepting handle into the listening
  3285. // process so that accept can take place there and the accepting
  3286. // socket will later get dup-ed into the accepting process when
  3287. // that process performs an IO operation on it.
  3288. //
  3289. NTSTATUS status;
  3290. listenProcess = PsGetProcessPcb(IoThreadToProcess (connectIrp->Tail.Overlay.Thread));
  3291. KeAttachProcess (listenProcess);
  3292. status = ObOpenObjectByPointer (
  3293. AcceptFileObject,
  3294. OBJ_CASE_INSENSITIVE,
  3295. NULL,
  3296. MAXIMUM_ALLOWED,
  3297. *IoFileObjectType,
  3298. KernelMode,
  3299. &acceptHandle);
  3300. KeDetachProcess ();
  3301. if (!NT_SUCCESS (status)) {
  3302. connectIrp->IoStatus.Status = STATUS_INVALID_HANDLE;
  3303. connectIrp->IoStatus.Information = 0;
  3304. IoCompleteRequest (connectIrp, AfdPriorityBoost);
  3305. return STATUS_REMOTE_DISCONNECT;
  3306. }
  3307. }
  3308. else {
  3309. acceptHandle = AcceptIrp->Tail.Overlay.DriverContext[3];
  3310. listenProcess = NULL;
  3311. }
  3312. //
  3313. // Now take care of the accept endpoint
  3314. //
  3315. AfdAcquireSpinLock (&acceptEndpoint->SpinLock, LockHandle);
  3316. IoSetCancelRoutine (AcceptIrp, AfdSanCancelAccept);
  3317. if (acceptEndpoint->EndpointCleanedUp || AcceptIrp->Cancel) {
  3318. //
  3319. // Endpoint was closed or IRP cancelled,
  3320. // reset accept irp pointer and return error
  3321. // to both application and SAN provider (to refuse
  3322. // the connection)
  3323. //
  3324. AcceptIrp->Tail.Overlay.ListEntry.Flink = NULL;
  3325. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, LockHandle);
  3326. if (listenProcess!=NULL) {
  3327. #if DBG
  3328. NTSTATUS status = STATUS_UNSUCCESSFUL;
  3329. #endif
  3330. //
  3331. // Destroy the handle that we created for
  3332. // accepting socket duplication.
  3333. //
  3334. KeAttachProcess (listenProcess);
  3335. try {
  3336. #if DBG
  3337. status =
  3338. #endif
  3339. NtClose (acceptHandle);
  3340. }
  3341. finally {
  3342. KeDetachProcess ();
  3343. }
  3344. ASSERT (NT_SUCCESS (status));
  3345. }
  3346. connectIrp->IoStatus.Status = STATUS_CANCELLED;
  3347. connectIrp->IoStatus.Information = 0;
  3348. IoCompleteRequest (connectIrp, AfdPriorityBoost);
  3349. return STATUS_CANCELLED;
  3350. }
  3351. //
  3352. // Pend the accept IRP till provider
  3353. // completes it. This may take quite a while,
  3354. // which is not expected by the msafd and application,
  3355. // but we have no choice here
  3356. //
  3357. IoMarkIrpPending (AcceptIrp);
  3358. irpSp = IoGetCurrentIrpStackLocation (AcceptIrp);
  3359. receiveLength = irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength;
  3360. connectInfo = connectIrp->AssociatedIrp.SystemBuffer;
  3361. //
  3362. // Remove super accept IRP from the endpoint
  3363. //
  3364. acceptEndpoint->Irp = NULL;
  3365. //
  3366. // Convert endpoint to SAN
  3367. //
  3368. AfdSanInitEndpoint (IoGetCurrentIrpStackLocation (connectIrp)->FileObject->FsContext,
  3369. AcceptFileObject,
  3370. connectInfo->SwitchContext);
  3371. if (listenProcess!=NULL) {
  3372. //
  3373. // Note that socket was duplicated implicitly, without application request
  3374. //
  3375. acceptEndpoint->Common.SanEndp.ImplicitDup = TRUE;
  3376. }
  3377. UPDATE_ENDPOINT (acceptEndpoint);
  3378. InsertTailList (&acceptEndpoint->Common.SanEndp.IrpList,
  3379. &AcceptIrp->Tail.Overlay.ListEntry);
  3380. if (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength>0) {
  3381. ULONG remoteAddressLength =
  3382. FIELD_OFFSET (
  3383. TRANSPORT_ADDRESS,
  3384. Address[0].Address[
  3385. connectInfo->RemoteAddress.Address[0].AddressLength]);
  3386. #ifndef i386
  3387. if (acceptEndpoint->Common.VcConnecting.FixAddressAlignment) {
  3388. USHORT addressLength =
  3389. connectInfo->RemoteAddress.Address[0].AddressLength
  3390. + sizeof (USHORT);
  3391. USHORT UNALIGNED *pAddrLength = (PVOID)
  3392. ((PUCHAR)MmGetSystemAddressForMdl (AcceptIrp->MdlAddress)
  3393. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  3394. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  3395. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdRemoteAddressLength
  3396. - sizeof (USHORT));
  3397. RtlMoveMemory (
  3398. (PUCHAR)MmGetSystemAddressForMdl (AcceptIrp->MdlAddress)
  3399. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  3400. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  3401. &connectInfo->RemoteAddress.Address[0].AddressType,
  3402. addressLength);
  3403. *pAddrLength = addressLength;
  3404. }
  3405. else
  3406. #endif
  3407. {
  3408. RtlMoveMemory (
  3409. (PUCHAR)MmGetSystemAddressForMdl (AcceptIrp->MdlAddress)
  3410. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength
  3411. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength,
  3412. &connectInfo->RemoteAddress,
  3413. remoteAddressLength);
  3414. }
  3415. if (irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength>0) {
  3416. PTA_ADDRESS localAddress = (PTA_ADDRESS)
  3417. &(connectInfo->RemoteAddress.Address[0].Address[
  3418. connectInfo->RemoteAddress.Address[0].AddressLength]);
  3419. TDI_ADDRESS_INFO UNALIGNED *addressInfo = (PVOID)
  3420. ((PUCHAR)MmGetSystemAddressForMdl(AcceptIrp->MdlAddress)
  3421. + irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdReceiveDataLength);
  3422. #ifndef i386
  3423. if (acceptEndpoint->Common.VcConnecting.FixAddressAlignment) {
  3424. USHORT UNALIGNED * pAddrLength = (PVOID)
  3425. ((PUCHAR)addressInfo
  3426. +irpSp->Parameters.AfdRestartSuperAcceptInfo.AfdLocalAddressLength
  3427. -sizeof(USHORT));
  3428. RtlMoveMemory (
  3429. addressInfo,
  3430. &localAddress->AddressType,
  3431. localAddress->AddressLength+sizeof (USHORT));
  3432. *pAddrLength = localAddress->AddressLength+sizeof (USHORT);
  3433. }
  3434. else
  3435. #endif
  3436. {
  3437. addressInfo->ActivityCount = 0;
  3438. addressInfo->Address.TAAddressCount = 1;
  3439. RtlMoveMemory (
  3440. &addressInfo->Address.Address,
  3441. localAddress,
  3442. FIELD_OFFSET (TA_ADDRESS, Address[localAddress->AddressLength]));
  3443. }
  3444. }
  3445. }
  3446. AfdReleaseSpinLock (&acceptEndpoint->SpinLock, LockHandle);
  3447. //
  3448. // Setup the accept info for the provider
  3449. //
  3450. //
  3451. // Do this under protection of exception handler since application
  3452. // can change protection attributes of the virtual address range
  3453. // or even deallocate it. Make sure to attach to the listening
  3454. // process if necessary.
  3455. //
  3456. if (listenProcess!=NULL) {
  3457. KeAttachProcess (listenProcess);
  3458. }
  3459. else {
  3460. ASSERT (IoGetCurrentProcess ()==IoThreadToProcess (connectIrp->Tail.Overlay.Thread));
  3461. }
  3462. try {
  3463. #ifdef _WIN64
  3464. if (IoIs32bitProcess (connectIrp)) {
  3465. PAFD_SWITCH_ACCEPT_INFO32 acceptInfo32;
  3466. acceptInfo32 = MmGetMdlVirtualAddress (connectIrp->MdlAddress);
  3467. ASSERT (acceptInfo32!=NULL);
  3468. ASSERT (MmGetMdlByteCount (connectIrp->MdlAddress)>=sizeof (*acceptInfo32));
  3469. acceptInfo32->AcceptHandle = (VOID * POINTER_32)acceptHandle;
  3470. acceptInfo32->ReceiveLength = receiveLength;
  3471. connectIrp->IoStatus.Information = sizeof (*acceptInfo32);
  3472. }
  3473. else
  3474. #endif _WIN64
  3475. {
  3476. PAFD_SWITCH_ACCEPT_INFO acceptInfo;
  3477. acceptInfo = MmGetMdlVirtualAddress (connectIrp->MdlAddress);
  3478. ASSERT (acceptInfo!=NULL);
  3479. ASSERT (MmGetMdlByteCount (connectIrp->MdlAddress)>=sizeof (*acceptInfo));
  3480. acceptInfo->AcceptHandle = acceptHandle;
  3481. acceptInfo->ReceiveLength = receiveLength;
  3482. connectIrp->IoStatus.Information = sizeof (*acceptInfo);
  3483. }
  3484. connectIrp->IoStatus.Status = (listenProcess==NULL) ? STATUS_SUCCESS : STATUS_MORE_ENTRIES;
  3485. }
  3486. except (AFD_EXCEPTION_FILTER (&connectIrp->IoStatus.Status)) {
  3487. //
  3488. // If the app is playing with switch's virtual addresses
  3489. // we can't help much - it's accept IRP will probably
  3490. // just hang since the switch is not going to follow
  3491. // the failed connect IRP with accept completion.
  3492. //
  3493. }
  3494. if (listenProcess!=NULL) {
  3495. KeDetachProcess ();
  3496. }
  3497. //
  3498. // Complete the provider IRP.
  3499. //
  3500. IoCompleteRequest (connectIrp, AfdPriorityBoost);
  3501. return STATUS_PENDING;
  3502. }
  3503. VOID
  3504. AfdSanReleaseConnection (
  3505. PAFD_ENDPOINT ListenEndpoint,
  3506. PAFD_CONNECTION Connection,
  3507. BOOLEAN CheckBacklog
  3508. )
  3509. {
  3510. LONG failedAdds;
  3511. failedAdds = InterlockedDecrement (
  3512. &ListenEndpoint->Common.VcListening.FailedConnectionAdds);
  3513. if (CheckBacklog || failedAdds>=0) {
  3514. if (!IS_DELAYED_ACCEPTANCE_ENDPOINT (ListenEndpoint)) {
  3515. InterlockedPushEntrySList (
  3516. &ListenEndpoint->Common.VcListening.FreeConnectionListHead,
  3517. &Connection->SListEntry
  3518. );
  3519. return;
  3520. }
  3521. else {
  3522. NTSTATUS status;
  3523. status = AfdDelayedAcceptListen (ListenEndpoint, Connection);
  3524. if (NT_SUCCESS (status)) {
  3525. return;
  3526. }
  3527. }
  3528. }
  3529. InterlockedIncrement(
  3530. &ListenEndpoint->Common.VcListening.FailedConnectionAdds
  3531. );
  3532. DEREFERENCE_CONNECTION (Connection);
  3533. }
  3534. VOID
  3535. AfdSanCancelConnect (
  3536. IN PDEVICE_OBJECT DeviceObject,
  3537. IN PIRP Irp
  3538. )
  3539. /*++
  3540. Routine Description:
  3541. Cancels a connection indication IRP from SAN provider
  3542. Arguments:
  3543. DeviceObject - not used.
  3544. Irp - the IRP to cancel.
  3545. Return Value:
  3546. None.
  3547. --*/
  3548. {
  3549. PIO_STACK_LOCATION irpSp;
  3550. PAFD_CONNECTION connection;
  3551. PAFD_ENDPOINT endpoint;
  3552. AFD_LOCK_QUEUE_HANDLE lockHandle;
  3553. irpSp = IoGetCurrentIrpStackLocation (Irp);
  3554. connection = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  3555. ASSERT (connection->Type==AfdBlockTypeConnection);
  3556. ASSERT (connection->SanConnection);
  3557. endpoint = connection->Endpoint;
  3558. ASSERT (IS_AFD_ENDPOINT_TYPE (endpoint));
  3559. ASSERT (endpoint->Listening);
  3560. ASSERT (KeGetCurrentIrql ()==DISPATCH_LEVEL);
  3561. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle);
  3562. //
  3563. // If IRP still there, cancel it.
  3564. // Otherwise, it is being completed anyway.
  3565. //
  3566. if (connection->ConnectIrp!=NULL) {
  3567. IF_DEBUG(SAN_SWITCH) {
  3568. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  3569. "AfdSanCancelConnect: endp-%p, irp-%p\n",
  3570. endpoint, Irp));
  3571. }
  3572. ASSERT (connection->ConnectIrp == Irp);
  3573. connection->ConnectIrp = NULL;
  3574. ASSERT (connection->Endpoint == endpoint);
  3575. connection->Endpoint = NULL;
  3576. connection->SanConnection = FALSE;
  3577. ASSERT (connection->State == AfdConnectionStateUnaccepted ||
  3578. connection->State==AfdConnectionStateReturned);
  3579. RemoveEntryList (&connection->ListEntry);
  3580. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  3581. IoReleaseCancelSpinLock (Irp->CancelIrql);
  3582. ASSERT ((endpoint->Type&AfdBlockTypeVcListening)==AfdBlockTypeVcListening);
  3583. AfdSanReleaseConnection (endpoint, connection, TRUE);
  3584. DEREFERENCE_ENDPOINT (endpoint);
  3585. Irp->IoStatus.Status = STATUS_CANCELLED;
  3586. Irp->IoStatus.Information = 0;
  3587. IoCompleteRequest (Irp, AfdPriorityBoost);
  3588. }
  3589. else {
  3590. //
  3591. // Irp is about to be completed.
  3592. //
  3593. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  3594. IoReleaseCancelSpinLock (Irp->CancelIrql);
  3595. }
  3596. }
  3597. VOID
  3598. AfdSanCancelAccept (
  3599. IN PDEVICE_OBJECT DeviceObject,
  3600. IN PIRP Irp
  3601. )
  3602. /*++
  3603. Routine Description:
  3604. Cancels an accept IRP from application waiting on accept
  3605. completion from SAN
  3606. Arguments:
  3607. DeviceObject - not used.
  3608. Irp - the IRP to cancel.
  3609. Return Value:
  3610. None.
  3611. --*/
  3612. {
  3613. PIO_STACK_LOCATION irpSp;
  3614. PFILE_OBJECT acceptFileObject;
  3615. PAFD_ENDPOINT acceptEndpoint;
  3616. AFD_LOCK_QUEUE_HANDLE lockHandle;
  3617. irpSp = IoGetCurrentIrpStackLocation (Irp);
  3618. acceptFileObject = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  3619. acceptEndpoint = acceptFileObject->FsContext;
  3620. ASSERT (acceptEndpoint->Type==AfdBlockTypeSanEndpoint);
  3621. ASSERT (KeGetCurrentIrql()==DISPATCH_LEVEL);
  3622. AfdAcquireSpinLockAtDpcLevel (&acceptEndpoint->SpinLock, &lockHandle);
  3623. //
  3624. // If IRP still there, cancel it.
  3625. // Otherwise, it is being completed anyway.
  3626. //
  3627. if (Irp->Tail.Overlay.ListEntry.Flink!=NULL) {
  3628. RemoveEntryList (&Irp->Tail.Overlay.ListEntry);
  3629. IF_DEBUG(SAN_SWITCH) {
  3630. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  3631. "AfdSanCancelAccept: endp-%p, irp-%p\n",
  3632. acceptEndpoint, Irp));
  3633. }
  3634. if (!acceptEndpoint->EndpointCleanedUp) {
  3635. if (acceptEndpoint->Common.SanEndp.SanHlpr!=NULL) {
  3636. DEREFERENCE_ENDPOINT (acceptEndpoint->Common.SanEndp.SanHlpr);
  3637. }
  3638. //
  3639. // Make sure we cleanup all the fields since they will be
  3640. // treated as other part (VC) of the endpoint union.
  3641. //
  3642. RtlZeroMemory (&acceptEndpoint->Common.SanEndp,
  3643. sizeof (acceptEndpoint->Common.SanEndp));
  3644. //
  3645. // Reinitialize the endpoint structure.
  3646. //
  3647. acceptEndpoint->Type = AfdBlockTypeEndpoint;
  3648. acceptEndpoint->State = AfdEndpointStateOpen;
  3649. acceptEndpoint->DisconnectMode = 0;
  3650. acceptEndpoint->EndpointStateFlags = 0;
  3651. }
  3652. AfdReleaseSpinLockFromDpcLevel (&acceptEndpoint->SpinLock, &lockHandle);
  3653. IoReleaseCancelSpinLock (Irp->CancelIrql);
  3654. AFD_END_STATE_CHANGE (acceptEndpoint);
  3655. //
  3656. // Dereference accept file object and complete the IRP.
  3657. //
  3658. ASSERT( InterlockedDecrement( &acceptEndpoint->ObReferenceBias ) >= 0 );
  3659. ObDereferenceObject (acceptFileObject);
  3660. Irp->IoStatus.Status = STATUS_CANCELLED;
  3661. Irp->IoStatus.Information = 0;
  3662. IoCompleteRequest (Irp, AfdPriorityBoost);
  3663. }
  3664. else {
  3665. //
  3666. // Irp is about to be completed.
  3667. //
  3668. AfdReleaseSpinLockFromDpcLevel (&acceptEndpoint->SpinLock, &lockHandle);
  3669. IoReleaseCancelSpinLock (Irp->CancelIrql);
  3670. }
  3671. }
  3672. VOID
  3673. AfdSanCancelRequest (
  3674. IN PDEVICE_OBJECT DeviceObject,
  3675. IN PIRP Irp
  3676. )
  3677. /*++
  3678. Routine Description:
  3679. Cancels a redirected IRP
  3680. Arguments:
  3681. DeviceObject - not used.
  3682. Irp - the IRP to cancel.
  3683. Return Value:
  3684. None.
  3685. --*/
  3686. {
  3687. PIO_STACK_LOCATION irpSp;
  3688. PAFD_ENDPOINT endpoint;
  3689. AFD_LOCK_QUEUE_HANDLE lockHandle;
  3690. irpSp = IoGetCurrentIrpStackLocation (Irp);
  3691. endpoint = irpSp->FileObject->FsContext;
  3692. ASSERT (endpoint->Type==AfdBlockTypeSanEndpoint);
  3693. ASSERT (KeGetCurrentIrql ()==DISPATCH_LEVEL);
  3694. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle);
  3695. //
  3696. // If IRP still there, cancel it.
  3697. // Otherwise, it is being completed anyway.
  3698. //
  3699. if (Irp->Tail.Overlay.ListEntry.Flink!=NULL) {
  3700. BOOLEAN needRestartProcessing = FALSE;
  3701. RemoveEntryList (&Irp->Tail.Overlay.ListEntry);
  3702. if (AFD_SWITCH_REQUEST_TYPE (Irp->AfdSanRequestInfo.AfdSanRequestCtx)
  3703. == AFD_SWITCH_REQUEST_TFCTX) {
  3704. ASSERT (endpoint->Common.SanEndp.CtxTransferStatus==STATUS_PENDING);
  3705. if (!IsListEmpty (&endpoint->Common.SanEndp.IrpList)) {
  3706. needRestartProcessing = TRUE;
  3707. }
  3708. else {
  3709. endpoint->Common.SanEndp.CtxTransferStatus = STATUS_SUCCESS;
  3710. }
  3711. }
  3712. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  3713. IoReleaseCancelSpinLock (Irp->CancelIrql);
  3714. IF_DEBUG(SAN_SWITCH) {
  3715. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  3716. "AfdSanCancelRequest: endp-%p, irp-%p, context-%p\n",
  3717. endpoint, Irp, Irp->AfdSanRequestInfo.AfdSanRequestCtx));
  3718. }
  3719. Irp->IoStatus.Status = STATUS_CANCELLED;
  3720. Irp->IoStatus.Information = 0;
  3721. if (Irp->AfdSanRequestInfo.AfdSanRequestCtx!=NULL) {
  3722. //
  3723. // Notify the switch that request was cancelled
  3724. //
  3725. AfdSanNotifyRequest (endpoint, Irp->AfdSanRequestInfo.AfdSanRequestCtx,
  3726. STATUS_CANCELLED,
  3727. 0);
  3728. if (needRestartProcessing) {
  3729. AfdSanRestartRequestProcessing (endpoint, STATUS_SUCCESS);
  3730. }
  3731. }
  3732. IoCompleteRequest (Irp, AfdPriorityBoost);
  3733. }
  3734. else {
  3735. //
  3736. // Irp is about to be completed.
  3737. //
  3738. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  3739. IoReleaseCancelSpinLock (Irp->CancelIrql);
  3740. }
  3741. }
  3742. VOID
  3743. AfdSanRestartRequestProcessing (
  3744. PAFD_ENDPOINT Endpoint,
  3745. NTSTATUS Status
  3746. )
  3747. /*++
  3748. Routine Description:
  3749. Restarts request processing after completion of the
  3750. transfer context request.
  3751. Arguments:
  3752. Endpoint - endpoint on which to restart request processing
  3753. Return Value:
  3754. None
  3755. --*/
  3756. {
  3757. AFD_LOCK_QUEUE_HANDLE lockHandle;
  3758. PLIST_ENTRY listEntry;
  3759. LIST_ENTRY irpList;
  3760. InitializeListHead (&irpList);
  3761. Again:
  3762. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  3763. //
  3764. // The enpoint should have just finished transferring context
  3765. // from one process to another. The CtxTransferStatus
  3766. // should still be pending.
  3767. //
  3768. ASSERT (Endpoint->Common.SanEndp.CtxTransferStatus==STATUS_PENDING ||
  3769. Endpoint->Common.SanEndp.CtxTransferStatus==STATUS_MORE_PROCESSING_REQUIRED ||
  3770. !NT_SUCCESS (Endpoint->Common.SanEndp.CtxTransferStatus) ||
  3771. !NT_SUCCESS (Status));
  3772. //
  3773. // Scan the list for the request that have not been comminicated
  3774. // to the switch.
  3775. //
  3776. listEntry = Endpoint->Common.SanEndp.IrpList.Flink;
  3777. while (listEntry!=&Endpoint->Common.SanEndp.IrpList) {
  3778. ULONG_PTR requestInfo;
  3779. ULONG requestType;
  3780. PVOID requestCtx;
  3781. PIRP irp = CONTAINING_RECORD (listEntry,
  3782. IRP,
  3783. Tail.Overlay.ListEntry);
  3784. listEntry = listEntry->Flink;
  3785. if (NT_SUCCESS (Status)) {
  3786. if (irp->AfdSanRequestInfo.AfdSanRequestCtx==NULL) {
  3787. PIO_STACK_LOCATION irpSp;
  3788. //
  3789. // Create request context based on request type.
  3790. //
  3791. irpSp = IoGetCurrentIrpStackLocation (irp);
  3792. switch (irpSp->MajorFunction) {
  3793. case IRP_MJ_READ:
  3794. requestType = AFD_SWITCH_REQUEST_READ;
  3795. requestInfo = irpSp->Parameters.Read.Length;
  3796. break;
  3797. case IRP_MJ_WRITE:
  3798. requestType = AFD_SWITCH_REQUEST_WRITE;
  3799. requestInfo = irpSp->Parameters.Write.Length;
  3800. break;
  3801. case IRP_MJ_DEVICE_CONTROL:
  3802. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  3803. case IOCTL_AFD_SWITCH_ACQUIRE_CTX:
  3804. requestType = AFD_SWITCH_REQUEST_TFCTX;
  3805. requestInfo = (ULONG_PTR)irp->AfdSanRequestInfo.AfdSanProcessId;
  3806. break;
  3807. default:
  3808. ASSERT (!"Unsupported IOCTL");
  3809. __assume (0);
  3810. }
  3811. break;
  3812. default:
  3813. ASSERT (!"Unsupported IRP Major Function");
  3814. __assume (0);
  3815. }
  3816. requestCtx = AFD_SWITCH_MAKE_REQUEST_CONTEXT(
  3817. Endpoint->Common.SanEndp.RequestId,
  3818. requestType);
  3819. irp->AfdSanRequestInfo.AfdSanRequestCtx = requestCtx;
  3820. Endpoint->Common.SanEndp.RequestId += 1;
  3821. UPDATE_ENDPOINT (Endpoint);
  3822. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  3823. //
  3824. // If we successfully sent another context transfer request, we should
  3825. // stop processing until this request is completed. The context transfer
  3826. // flag should remain set.
  3827. //
  3828. if (AfdSanNotifyRequest (Endpoint, requestCtx, STATUS_SUCCESS, requestInfo) &&
  3829. requestType==AFD_SWITCH_REQUEST_TFCTX) {
  3830. return;
  3831. }
  3832. else {
  3833. //
  3834. // Reacquire the lock and continue processing from the beggining
  3835. // as the list could have changed while spinlock was released.
  3836. //
  3837. goto Again;
  3838. }
  3839. }
  3840. }
  3841. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  3842. InsertTailList (&irpList, &irp->Tail.Overlay.ListEntry);
  3843. }
  3844. //
  3845. // Ran till the end of the list and did not find another transfer request.
  3846. // We can reset the flag now.
  3847. //
  3848. Endpoint->Common.SanEndp.CtxTransferStatus = Status;
  3849. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  3850. while (!IsListEmpty (&irpList)) {
  3851. PIRP irp;
  3852. listEntry = RemoveHeadList (&irpList);
  3853. irp = CONTAINING_RECORD (listEntry,
  3854. IRP,
  3855. Tail.Overlay.ListEntry);
  3856. irp->IoStatus.Status = Status;
  3857. irp->IoStatus.Information = 0;
  3858. IoCompleteRequest (irp, AfdPriorityBoost);
  3859. }
  3860. }
  3861. PIRP
  3862. AfdSanDequeueRequest (
  3863. PAFD_ENDPOINT SanEndpoint,
  3864. PVOID RequestCtx
  3865. )
  3866. /*++
  3867. Routine Description:
  3868. Removes the request from the san endpoint list
  3869. Arguments:
  3870. SanEndpoint - endpoint from which to remove the request
  3871. RequestCtx - context that identifies the request
  3872. Return Value:
  3873. The request or NULL is not found.
  3874. --*/
  3875. {
  3876. AFD_LOCK_QUEUE_HANDLE lockHandle;
  3877. PLIST_ENTRY listEntry;
  3878. AfdAcquireSpinLock (&SanEndpoint->SpinLock, &lockHandle);
  3879. listEntry = SanEndpoint->Common.SanEndp.IrpList.Flink;
  3880. //
  3881. // Walk the list till we find the request
  3882. //
  3883. while (listEntry!=&SanEndpoint->Common.SanEndp.IrpList) {
  3884. PIRP irp = CONTAINING_RECORD (listEntry,
  3885. IRP,
  3886. Tail.Overlay.ListEntry);
  3887. listEntry = listEntry->Flink;
  3888. if (irp->AfdSanRequestInfo.AfdSanRequestCtx==RequestCtx) {
  3889. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  3890. irp->Tail.Overlay.ListEntry.Flink = NULL;
  3891. AfdReleaseSpinLock (&SanEndpoint->SpinLock, &lockHandle);
  3892. //
  3893. // Check if request is being cancelled and synchronize
  3894. // with the cancel routine if so.
  3895. //
  3896. if (IoSetCancelRoutine (irp, NULL)==NULL) {
  3897. KIRQL cancelIrql;
  3898. IoAcquireCancelSpinLock (&cancelIrql);
  3899. IoReleaseCancelSpinLock (cancelIrql);
  3900. }
  3901. return irp;
  3902. }
  3903. else if (irp->AfdSanRequestInfo.AfdSanRequestCtx==NULL) {
  3904. break;
  3905. }
  3906. }
  3907. AfdReleaseSpinLock (&SanEndpoint->SpinLock, &lockHandle);
  3908. return NULL;
  3909. }
  3910. BOOLEAN
  3911. AfdSanNotifyRequest (
  3912. PAFD_ENDPOINT SanEndpoint,
  3913. PVOID RequestCtx,
  3914. NTSTATUS Status,
  3915. ULONG_PTR Information
  3916. )
  3917. {
  3918. PVOID context;
  3919. PAFD_ENDPOINT sanHlprEndpoint;
  3920. NTSTATUS status;
  3921. PAGED_CODE ();
  3922. context = AfdLockEndpointContext (SanEndpoint);
  3923. //
  3924. // Get the san helper endpoint which we use to communicate
  3925. // with the switch
  3926. //
  3927. sanHlprEndpoint = SanEndpoint->Common.SanEndp.SanHlpr;
  3928. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  3929. //
  3930. // Notify the switch about the request.
  3931. //
  3932. status = IoSetIoCompletion (
  3933. sanHlprEndpoint->Common.SanHlpr.IoCompletionPort,// Port
  3934. SanEndpoint->Common.SanEndp.SwitchContext, // Key
  3935. RequestCtx, // ApcContext
  3936. Status, // Status
  3937. Information, // Information
  3938. TRUE // ChargeQuota
  3939. );
  3940. AfdUnlockEndpointContext (SanEndpoint, context);
  3941. if (NT_SUCCESS (status) || Status==STATUS_CANCELLED) {
  3942. return TRUE;
  3943. }
  3944. else {
  3945. PIRP irp;
  3946. //
  3947. // If notification failed, fail the request.
  3948. // Note that we cannot return the failure status directly
  3949. // as we already marked IRP as pending. Also, the IRP
  3950. // could have been cancelled, so we have to search for
  3951. // it in the list.
  3952. //
  3953. irp = AfdSanDequeueRequest (SanEndpoint, RequestCtx);
  3954. if (irp!=NULL) {
  3955. //
  3956. // Complete the Irp as we found it.
  3957. //
  3958. irp->IoStatus.Status = status;
  3959. IoCompleteRequest (irp, AfdPriorityBoost);
  3960. }
  3961. return FALSE;
  3962. }
  3963. }
  3964. NTSTATUS
  3965. AfdSanPollBegin (
  3966. PAFD_ENDPOINT Endpoint,
  3967. ULONG EventMask
  3968. )
  3969. /*++
  3970. Routine Description:
  3971. Records poll call so that switch knows to notify AFD to complete
  3972. select/AsyncSelect/EventSelect requests
  3973. Arguments:
  3974. Endpoint - endpoint to record
  3975. EventMask - events that needs to be notified
  3976. Return Value:
  3977. NTSTATUS - may fail to access user mode address
  3978. Note:
  3979. This routine must be called in the context of user mode process
  3980. that owns the endpoint
  3981. --*/
  3982. {
  3983. LONG currentEvents, newEvents;
  3984. PVOID context;
  3985. BOOLEAN attached = FALSE;
  3986. NTSTATUS status = STATUS_SUCCESS;
  3987. PAGED_CODE ();
  3988. context = AfdLockEndpointContext (Endpoint);
  3989. if (IoGetCurrentProcess()!=Endpoint->Common.SanEndp.SanHlpr->OwningProcess) {
  3990. KeAttachProcess (PsGetProcessPcb(Endpoint->Common.SanEndp.SanHlpr->OwningProcess));
  3991. attached = TRUE;
  3992. }
  3993. try {
  3994. //
  3995. // Increment appropriate counts to inform the switch that we are interested
  3996. // in the event.
  3997. //
  3998. if (EventMask & AFD_POLL_RECEIVE) {
  3999. InterlockedIncrement (&Endpoint->Common.SanEndp.SwitchContext->RcvCount);
  4000. //
  4001. // Inform switch that select has happened on this endpoint
  4002. //
  4003. Endpoint->Common.SanEndp.SwitchContext->SelectFlag = TRUE;
  4004. }
  4005. if (EventMask & AFD_POLL_RECEIVE_EXPEDITED) {
  4006. InterlockedIncrement (&Endpoint->Common.SanEndp.SwitchContext->ExpCount);
  4007. }
  4008. if (EventMask & AFD_POLL_SEND) {
  4009. InterlockedIncrement (&Endpoint->Common.SanEndp.SwitchContext->SndCount);
  4010. }
  4011. //
  4012. // Update our event record.
  4013. //
  4014. do {
  4015. currentEvents = *((LONG volatile *)&Endpoint->Common.SanEndp.SelectEventsActive);
  4016. newEvents = *((LONG volatile *)&Endpoint->Common.SanEndp.SwitchContext->EventsActive);
  4017. }
  4018. while (InterlockedCompareExchange (
  4019. (PLONG)&Endpoint->Common.SanEndp.SelectEventsActive,
  4020. newEvents,
  4021. currentEvents)!=currentEvents);
  4022. }
  4023. except (AFD_EXCEPTION_FILTER (&status)) {
  4024. }
  4025. if (attached) {
  4026. KeDetachProcess ();
  4027. }
  4028. AfdUnlockEndpointContext (Endpoint, context);
  4029. return status;
  4030. }
  4031. VOID
  4032. AfdSanPollEnd (
  4033. PAFD_ENDPOINT Endpoint,
  4034. ULONG EventMask
  4035. )
  4036. /*++
  4037. Routine Description:
  4038. Records poll call completion, so that switch can avoild expensive calls to notify AFD
  4039. to complete select/AsyncSelect/EventSelect requests
  4040. Arguments:
  4041. Endpoint - endpoint to record
  4042. EventMask - events that needs to be dereferenced
  4043. Return Value:
  4044. NTSTATUS - may fail to access user mode address
  4045. Note:
  4046. This routine must be called in the context of user mode process
  4047. that owns the endpoint
  4048. --*/
  4049. {
  4050. BOOLEAN attached = FALSE;
  4051. PVOID context;
  4052. PAGED_CODE ();
  4053. context = AfdLockEndpointContext (Endpoint);
  4054. if (IoGetCurrentProcess()!=Endpoint->Common.SanEndp.SanHlpr->OwningProcess) {
  4055. KeAttachProcess (PsGetProcessPcb(Endpoint->Common.SanEndp.SanHlpr->OwningProcess));
  4056. attached = TRUE;
  4057. }
  4058. try {
  4059. //
  4060. // Decrement appropriate counts to inform the switch that we are no longer interested
  4061. // in the event.
  4062. //
  4063. if (EventMask & AFD_POLL_RECEIVE) {
  4064. InterlockedDecrement (&Endpoint->Common.SanEndp.SwitchContext->RcvCount);
  4065. }
  4066. if (EventMask & AFD_POLL_RECEIVE_EXPEDITED) {
  4067. InterlockedDecrement (&Endpoint->Common.SanEndp.SwitchContext->ExpCount);
  4068. }
  4069. if (EventMask & AFD_POLL_SEND) {
  4070. InterlockedDecrement (&Endpoint->Common.SanEndp.SwitchContext->SndCount);
  4071. }
  4072. }
  4073. except (AFD_EXCEPTION_FILTER (NULL)) {
  4074. //
  4075. // Not much we can do. The switch will have to call us with all the events.
  4076. //
  4077. }
  4078. if (attached) {
  4079. KeDetachProcess ();
  4080. }
  4081. AfdUnlockEndpointContext (Endpoint, context);
  4082. }
  4083. VOID
  4084. AfdSanPollUpdate (
  4085. PAFD_ENDPOINT Endpoint,
  4086. ULONG EventMask
  4087. )
  4088. /*++
  4089. Routine Description:
  4090. Updates local kernel information currently outstanding polls on the
  4091. endpoint to be later merged into information maitained by the switch
  4092. Arguments:
  4093. Endpoint - endpoint to record
  4094. EventMask - events that needs to be recorded
  4095. Return Value:
  4096. None
  4097. --*/
  4098. {
  4099. ASSERT (KeGetCurrentIrql()==DISPATCH_LEVEL);
  4100. ASSERT (Endpoint->Common.SanEndp.LocalContext!=NULL);
  4101. if (EventMask & AFD_POLL_RECEIVE) {
  4102. InterlockedIncrement (&Endpoint->Common.SanEndp.LocalContext->RcvCount);
  4103. }
  4104. if (EventMask & AFD_POLL_RECEIVE_EXPEDITED) {
  4105. InterlockedIncrement (&Endpoint->Common.SanEndp.LocalContext->ExpCount);
  4106. }
  4107. if (EventMask & AFD_POLL_SEND) {
  4108. InterlockedIncrement (&Endpoint->Common.SanEndp.LocalContext->SndCount);
  4109. }
  4110. }
  4111. NTSTATUS
  4112. AfdSanPollMerge (
  4113. PAFD_ENDPOINT Endpoint,
  4114. PAFD_SWITCH_CONTEXT Context
  4115. )
  4116. /*++
  4117. Routine Description:
  4118. Merges information about outstanding poll calls into switch counts.
  4119. Arguments:
  4120. Endpoint - endpoint to record
  4121. Context - outstanding select info merge in
  4122. Return Value:
  4123. NTSTATUS - may fail to access user mode address
  4124. Note:
  4125. This routine must be called in the context of user mode process
  4126. that owns the endpoint
  4127. --*/
  4128. {
  4129. NTSTATUS status = STATUS_SUCCESS;
  4130. PAGED_CODE ();
  4131. ASSERT (IoGetCurrentProcess()==Endpoint->Common.SanEndp.SanHlpr->OwningProcess);
  4132. ASSERT (Endpoint->Common.SanEndp.LocalContext == Context);
  4133. try {
  4134. InterlockedExchangeAdd (&Endpoint->Common.SanEndp.SwitchContext->RcvCount,
  4135. Context->RcvCount);
  4136. InterlockedExchangeAdd (&Endpoint->Common.SanEndp.SwitchContext->SndCount,
  4137. Context->SndCount);
  4138. InterlockedExchangeAdd (&Endpoint->Common.SanEndp.SwitchContext->ExpCount,
  4139. Context->ExpCount);
  4140. }
  4141. except (AFD_EXCEPTION_FILTER (&status)) {
  4142. }
  4143. return status;
  4144. }
  4145. VOID
  4146. AfdSanInitEndpoint (
  4147. PAFD_ENDPOINT SanHlprEndpoint,
  4148. PFILE_OBJECT SanFileObject,
  4149. PAFD_SWITCH_CONTEXT SwitchContext
  4150. )
  4151. /*++
  4152. Routine Description:
  4153. Initializes SAN endpoint structure
  4154. Arguments:
  4155. SanHlprEndpoint - switch helper endpoint - communication channel
  4156. between the switch and AFD for the owner process.
  4157. SanFile - file object for the endpoint to be initialized.
  4158. Return Value:
  4159. None
  4160. --*/
  4161. {
  4162. PAFD_ENDPOINT sanEndpoint = SanFileObject->FsContext;
  4163. ASSERT (IS_SAN_HELPER(SanHlprEndpoint));
  4164. sanEndpoint->Type = AfdBlockTypeSanEndpoint;
  4165. REFERENCE_ENDPOINT (SanHlprEndpoint);
  4166. sanEndpoint->Common.SanEndp.SanHlpr = SanHlprEndpoint;
  4167. sanEndpoint->Common.SanEndp.FileObject = SanFileObject;
  4168. sanEndpoint->Common.SanEndp.SwitchContext = SwitchContext;
  4169. // sanEndpoint->Common.SanEndp.SavedContext = NULL;
  4170. sanEndpoint->Common.SanEndp.LocalContext = NULL;
  4171. InitializeListHead (&sanEndpoint->Common.SanEndp.IrpList);
  4172. sanEndpoint->Common.SanEndp.SelectEventsActive = 0;
  4173. sanEndpoint->Common.SanEndp.RequestId = 1;
  4174. sanEndpoint->Common.SanEndp.CtxTransferStatus = STATUS_SUCCESS;
  4175. sanEndpoint->Common.SanEndp.ImplicitDup = FALSE;
  4176. //
  4177. // HACKHACK. Force IO subsystem to call us when last handle to the file is closed
  4178. // in any given process.
  4179. //
  4180. SanFileObject->LockOperation = TRUE;
  4181. }
  4182. VOID
  4183. AfdSanAbortConnection (
  4184. PAFD_CONNECTION Connection
  4185. )
  4186. {
  4187. PIRP connectIrp;
  4188. PDRIVER_CANCEL cancelRoutine;
  4189. KIRQL cancelIrql;
  4190. AFD_LOCK_QUEUE_HANDLE lockHandle;
  4191. PAFD_ENDPOINT endpoint = Connection->Endpoint;
  4192. ASSERT (Connection->SanConnection==TRUE);
  4193. //
  4194. // Acquire cancel spinlock and endpoint spinlock in
  4195. // this order and recheck the accept IRP
  4196. //
  4197. IoAcquireCancelSpinLock (&cancelIrql);
  4198. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &lockHandle);
  4199. connectIrp = Connection->ConnectIrp;
  4200. if ((connectIrp!=NULL) &&
  4201. ((cancelRoutine=IoSetCancelRoutine (connectIrp, NULL))!=NULL)) {
  4202. //
  4203. // Accept IRP was still there and was not cancelled/completed
  4204. // cancel it
  4205. //
  4206. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  4207. connectIrp->CancelIrql = cancelIrql;
  4208. connectIrp->Cancel = TRUE;
  4209. (*cancelRoutine) (AfdDeviceObject, connectIrp);
  4210. }
  4211. else {
  4212. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &lockHandle);
  4213. IoReleaseCancelSpinLock (cancelIrql);
  4214. }
  4215. }
  4216. VOID
  4217. AfdSanCleanupEndpoint (
  4218. PAFD_ENDPOINT Endpoint
  4219. )
  4220. /*++
  4221. Routine Description:
  4222. Cleans up SAN specific fields in AFD_ENDPOINT
  4223. Arguments:
  4224. Endpoint - endpoint to cleanup
  4225. Return Value:
  4226. None
  4227. --*/
  4228. {
  4229. PAFD_ENDPOINT sanHlprEndpoint;
  4230. ASSERT (IsListEmpty (&Endpoint->Common.SanEndp.IrpList));
  4231. ASSERT (Endpoint->Common.SanEndp.LocalContext == NULL);
  4232. sanHlprEndpoint = Endpoint->Common.SanEndp.SanHlpr;
  4233. if (sanHlprEndpoint!=NULL) {
  4234. ASSERT (IS_SAN_HELPER (sanHlprEndpoint));
  4235. DEREFERENCE_ENDPOINT (sanHlprEndpoint);
  4236. Endpoint->Common.SanEndp.SanHlpr = NULL;
  4237. }
  4238. }
  4239. VOID
  4240. AfdSanCleanupHelper (
  4241. PAFD_ENDPOINT Endpoint
  4242. )
  4243. /*++
  4244. Routine Description:
  4245. Cleans up SAN helper specific fields in AFD_ENDPOINT
  4246. Arguments:
  4247. Endpoint - endpoint to cleanup
  4248. Return Value:
  4249. None
  4250. --*/
  4251. {
  4252. ASSERT (Endpoint->Common.SanHlpr.IoCompletionPort!=NULL);
  4253. ObDereferenceObject (Endpoint->Common.SanHlpr.IoCompletionPort);
  4254. Endpoint->Common.SanHlpr.IoCompletionPort = NULL;
  4255. ASSERT (Endpoint->Common.SanHlpr.IoCompletionEvent!=NULL);
  4256. ObDereferenceObject (Endpoint->Common.SanHlpr.IoCompletionEvent);
  4257. Endpoint->Common.SanHlpr.IoCompletionEvent = NULL;
  4258. KeEnterCriticalRegion ();
  4259. ExAcquireResourceExclusiveLite( AfdResource, TRUE );
  4260. ASSERT (IS_SAN_HELPER (Endpoint));
  4261. ASSERT (AfdSanServiceHelper!=Endpoint); // Should have been removed in cleanup.
  4262. ASSERT (!IsListEmpty (&Endpoint->Common.SanHlpr.SanListLink));
  4263. RemoveEntryList (&Endpoint->Common.SanHlpr.SanListLink);
  4264. ExReleaseResourceLite( AfdResource );
  4265. KeLeaveCriticalRegion ();
  4266. }
  4267. BOOLEAN
  4268. AfdSanReferenceEndpointObject (
  4269. PAFD_ENDPOINT Endpoint
  4270. )
  4271. /*++
  4272. Routine Description:
  4273. Reference file object with which san endpoint is associated
  4274. Arguments:
  4275. Endpoint - endpoint of interest
  4276. Return Value:
  4277. TRUE - reference successed
  4278. FALSE - endpoint has already been cleaned up and its file object
  4279. is about to be closed.
  4280. --*/
  4281. {
  4282. BOOLEAN res = TRUE;
  4283. AFD_LOCK_QUEUE_HANDLE lockHandle;
  4284. AfdAcquireSpinLock (&Endpoint->SpinLock, &lockHandle);
  4285. if (!Endpoint->EndpointCleanedUp) {
  4286. ObReferenceObject (Endpoint->Common.SanEndp.FileObject);
  4287. }
  4288. else {
  4289. res = FALSE;
  4290. }
  4291. AfdReleaseSpinLock (&Endpoint->SpinLock, &lockHandle);
  4292. return res;
  4293. }
  4294. NTSTATUS
  4295. AfdSanReferenceSwitchSocketByHandle (
  4296. IN HANDLE SocketHandle,
  4297. IN ACCESS_MASK DesiredAccess,
  4298. IN KPROCESSOR_MODE RequestorMode,
  4299. IN PAFD_ENDPOINT SanHlprEndpoint,
  4300. IN PAFD_SWITCH_CONTEXT SwitchContext OPTIONAL,
  4301. OUT PFILE_OBJECT *FileObject
  4302. )
  4303. /*++
  4304. Routine Description:
  4305. Finds and validates AFD endpoint based on the handle/context combination passed in
  4306. by the switch.
  4307. Arguments:
  4308. SocketHandle - Socket handle being referenced
  4309. DesiredAccess - Required access to the object to perform operation
  4310. RequestorMode - Mode of the caller
  4311. SanHlprEndpoint - helper endpoint - communication channel between AFD and switch
  4312. SwitchContext - context associated by the switch with the socket being referenced
  4313. FileObject - file object corresponding to socket handle
  4314. Return Value:
  4315. STATUS_SUCCESS - operation succeeded
  4316. other - failed to find/access endpoint associated with the socket handle/context
  4317. --*/
  4318. {
  4319. NTSTATUS status;
  4320. if (IS_SAN_HELPER (SanHlprEndpoint) &&
  4321. SanHlprEndpoint->OwningProcess==IoGetCurrentProcess ()) {
  4322. status = ObReferenceObjectByHandle (
  4323. SocketHandle,
  4324. DesiredAccess,
  4325. *IoFileObjectType,
  4326. RequestorMode,
  4327. FileObject,
  4328. NULL
  4329. );
  4330. if (NT_SUCCESS (status) &&
  4331. (*FileObject)->DeviceObject==AfdDeviceObject &&
  4332. //
  4333. // Ether socket belongs to the current process and context matches
  4334. // the one supplied by the switch
  4335. //
  4336. ((IS_SAN_ENDPOINT((PAFD_ENDPOINT)(*FileObject)->FsContext) &&
  4337. ((PAFD_ENDPOINT)((*FileObject)->FsContext))->Common.SanEndp.SanHlpr==SanHlprEndpoint &&
  4338. ((PAFD_ENDPOINT)((*FileObject)->FsContext))->Common.SanEndp.SwitchContext==SwitchContext)
  4339. ||
  4340. //
  4341. // Or this is just a non-SAN socket being converted to one or just
  4342. // used for select signalling.
  4343. //
  4344. (SwitchContext==NULL &&
  4345. ((PAFD_ENDPOINT)(*FileObject)->FsContext)->Type==AfdBlockTypeEndpoint)) ){
  4346. NOTHING;
  4347. }
  4348. else {
  4349. if (NT_SUCCESS (status)) {
  4350. //
  4351. // Undo object referencing since it doesn't match the one that switch expects
  4352. //
  4353. ObDereferenceObject (*FileObject);
  4354. status = STATUS_INVALID_HANDLE;
  4355. }
  4356. //
  4357. // If switch supplied the context, try to find the socket
  4358. // in the current process that has the same one.
  4359. //
  4360. if (SwitchContext!=NULL) {
  4361. status = AfdSanFindSwitchSocketByProcessContext (
  4362. status,
  4363. SanHlprEndpoint,
  4364. SwitchContext,
  4365. FileObject);
  4366. }
  4367. }
  4368. }
  4369. else
  4370. status = STATUS_INVALID_HANDLE;
  4371. return status;
  4372. }
  4373. NTSTATUS
  4374. AfdSanFindSwitchSocketByProcessContext (
  4375. IN NTSTATUS Status,
  4376. IN PAFD_ENDPOINT SanHlprEndpoint,
  4377. IN PAFD_SWITCH_CONTEXT SwitchContext,
  4378. OUT PFILE_OBJECT *FileObject
  4379. )
  4380. /*++
  4381. Routine Description:
  4382. Find SAN endpoint given its process (helper endpoint) and switch context.
  4383. Arguments:
  4384. Status - status returned by the ob object reference operation
  4385. (to be propagated to the caller in case of failure).
  4386. SanHlprEndpoint - helper endpoint for the process to look in
  4387. SwitchContext - switch context associated with the endpoint
  4388. FileObject - returns endpont's file object if found
  4389. Return Value:
  4390. STATUS_SUCCESS - san endpoint was found
  4391. other - failed to find endpoint based on the switch context.
  4392. --*/
  4393. {
  4394. PLIST_ENTRY listEntry;
  4395. PAFD_ENDPOINT sanEndpoint = NULL;
  4396. HANDLE socketHandle;
  4397. PVOID context;
  4398. PAGED_CODE ();
  4399. //
  4400. // Walk the global endpoint list and try to find the entry
  4401. // that matches the switch context
  4402. //
  4403. KeEnterCriticalRegion ();
  4404. ExAcquireResourceSharedLite (AfdResource, TRUE);
  4405. listEntry = AfdEndpointListHead.Flink;
  4406. while (listEntry!=&AfdEndpointListHead) {
  4407. sanEndpoint = CONTAINING_RECORD (listEntry, AFD_ENDPOINT, GlobalEndpointListEntry);
  4408. context = AfdLockEndpointContext (sanEndpoint);
  4409. if (IS_SAN_ENDPOINT (sanEndpoint) &&
  4410. sanEndpoint->Common.SanEndp.SanHlpr==SanHlprEndpoint &&
  4411. sanEndpoint->Common.SanEndp.SwitchContext==SwitchContext &&
  4412. AfdSanReferenceEndpointObject (sanEndpoint)) {
  4413. break;
  4414. }
  4415. AfdUnlockEndpointContext (sanEndpoint, context);
  4416. listEntry = listEntry->Flink;
  4417. }
  4418. ExReleaseResourceLite (AfdResource);
  4419. KeLeaveCriticalRegion ();
  4420. if (listEntry==&sanEndpoint->GlobalEndpointListEntry) {
  4421. //
  4422. // Try to find the real handle for the switch to use in the future
  4423. //
  4424. *FileObject = sanEndpoint->Common.SanEndp.FileObject;
  4425. if (ObFindHandleForObject (SanHlprEndpoint->OwningProcess,
  4426. sanEndpoint->Common.SanEndp.FileObject,
  4427. *IoFileObjectType,
  4428. NULL,
  4429. &socketHandle)) {
  4430. UPDATE_ENDPOINT2 (sanEndpoint,
  4431. "AfdSanFindSwitchSocketByProcessContext, handle: %lx",
  4432. HandleToUlong (socketHandle));
  4433. //
  4434. // Notify switch of handle to be used.
  4435. // Ignore failure, the switch will still be able to communicate via
  4436. // slow lookup path.
  4437. //
  4438. IoSetIoCompletion (
  4439. SanHlprEndpoint->Common.SanHlpr.IoCompletionPort,
  4440. SwitchContext,
  4441. AFD_SWITCH_MAKE_REQUEST_CONTEXT (0, AFD_SWITCH_REQUEST_CHCTX),
  4442. STATUS_SUCCESS,
  4443. (ULONG_PTR)socketHandle,
  4444. TRUE // Charge quota
  4445. );
  4446. }
  4447. else {
  4448. UPDATE_ENDPOINT (sanEndpoint);
  4449. }
  4450. AfdUnlockEndpointContext (sanEndpoint, context);
  4451. Status = STATUS_SUCCESS;
  4452. }
  4453. return Status;
  4454. }
  4455. VOID
  4456. AfdSanResetPendingRequests (
  4457. PAFD_ENDPOINT SanEndpoint
  4458. )
  4459. /*++
  4460. Routine Description:
  4461. Reset request pending on SAN endpoint while transfering
  4462. context to service process.
  4463. Arguments:
  4464. SanEndpoint - endpoint on which to reset requests.
  4465. Return Value:
  4466. None
  4467. --*/
  4468. {
  4469. AFD_LOCK_QUEUE_HANDLE lockHandle;
  4470. PLIST_ENTRY listEntry;
  4471. AfdAcquireSpinLock (&SanEndpoint->SpinLock, &lockHandle);
  4472. listEntry = SanEndpoint->Common.SanEndp.IrpList.Flink;
  4473. while (listEntry!=&SanEndpoint->Common.SanEndp.IrpList) {
  4474. PIRP irp = CONTAINING_RECORD (listEntry, IRP, Tail.Overlay.ListEntry);
  4475. irp->AfdSanRequestInfo.AfdSanRequestCtx = NULL;
  4476. listEntry = listEntry->Flink;
  4477. }
  4478. SanEndpoint->Common.SanEndp.CtxTransferStatus = STATUS_MORE_PROCESSING_REQUIRED;
  4479. AfdReleaseSpinLock (&SanEndpoint->SpinLock, &lockHandle);
  4480. }
  4481. NTSTATUS
  4482. AfdSanDupEndpointIntoServiceProcess (
  4483. PFILE_OBJECT SanFileObject,
  4484. PVOID SavedContext,
  4485. ULONG ContextLength
  4486. )
  4487. /*++
  4488. Routine Description:
  4489. Duplicate endpoint into the context of the service process
  4490. and save switch context on it
  4491. Arguments:
  4492. SanFileObject - file object being duplicated
  4493. SaveContext - pointer to switch context data
  4494. ContextLength - length of the context
  4495. Return Value:
  4496. STATUS_SUCCESS - successfully duped
  4497. other - failed.
  4498. --*/
  4499. {
  4500. NTSTATUS status;
  4501. HANDLE handle;
  4502. PAFD_ENDPOINT sanEndpoint = SanFileObject->FsContext;
  4503. PVOID context;
  4504. //
  4505. // Take the lock to make sure that service helper won't
  4506. // exit on us and take the helper endpoint with it.
  4507. //
  4508. KeEnterCriticalRegion ();
  4509. ExAcquireResourceSharedLite (AfdResource, TRUE);
  4510. if (AfdSanServiceHelper!=NULL) {
  4511. //
  4512. // Attach to the process and create handle for the file object.
  4513. //
  4514. KeAttachProcess (PsGetProcessPcb(AfdSanServiceHelper->OwningProcess));
  4515. status = ObOpenObjectByPointer (
  4516. SanFileObject,
  4517. OBJ_CASE_INSENSITIVE,
  4518. NULL,
  4519. MAXIMUM_ALLOWED,
  4520. *IoFileObjectType,
  4521. KernelMode,
  4522. &handle);
  4523. KeDetachProcess ();
  4524. if (NT_SUCCESS (status)) {
  4525. context = AfdLockEndpointContext (sanEndpoint);
  4526. //
  4527. // Notify the service process that it needs to acquire endpoint context.
  4528. //
  4529. if (sanEndpoint->Common.SanEndp.SanHlpr!=AfdSanServiceHelper) {
  4530. status = IoSetIoCompletion (
  4531. AfdSanServiceHelper->Common.SanHlpr.IoCompletionPort,
  4532. NULL,
  4533. AFD_SWITCH_MAKE_REQUEST_CONTEXT (0,AFD_SWITCH_REQUEST_AQCTX),
  4534. STATUS_SUCCESS,
  4535. (ULONG_PTR)handle,
  4536. TRUE // Charge quota
  4537. );
  4538. if (NT_SUCCESS (status)) {
  4539. //
  4540. // Change the process affiliation of the endpoint
  4541. // and suspend the request queue processing until
  4542. // service process comes back at acquires the context.
  4543. //
  4544. UPDATE_ENDPOINT (sanEndpoint);
  4545. DEREFERENCE_ENDPOINT (sanEndpoint->Common.SanEndp.SanHlpr);
  4546. REFERENCE_ENDPOINT(AfdSanServiceHelper);
  4547. sanEndpoint->Common.SanEndp.SanHlpr = AfdSanServiceHelper;
  4548. //sanEndpoint->Common.SanEndp.SwitchContext = NULL;
  4549. sanEndpoint->Common.SanEndp.SavedContext = SavedContext;
  4550. sanEndpoint->Common.SanEndp.SavedContextLength = ContextLength;
  4551. //
  4552. // Note that socket was duplicated implicitly without
  4553. // application request.
  4554. //
  4555. sanEndpoint->Common.SanEndp.ImplicitDup = TRUE;
  4556. AfdSanResetPendingRequests (sanEndpoint);
  4557. AfdUnlockEndpointContext (sanEndpoint, context);
  4558. ExReleaseResourceLite (AfdResource);
  4559. KeLeaveCriticalRegion ();
  4560. return status;
  4561. }
  4562. }
  4563. else {
  4564. //
  4565. // Endpoint is already in the service process.
  4566. //
  4567. status = STATUS_INVALID_PARAMETER;
  4568. }
  4569. AfdUnlockEndpointContext (sanEndpoint, context);
  4570. KeAttachProcess (PsGetProcessPcb(sanEndpoint->Common.SanEndp.SanHlpr->OwningProcess));
  4571. try {
  4572. NtClose (handle);
  4573. }
  4574. finally {
  4575. KeDetachProcess ();
  4576. }
  4577. }
  4578. }
  4579. else {
  4580. status = STATUS_UNSUCCESSFUL;
  4581. }
  4582. ExReleaseResourceLite (AfdResource);
  4583. KeLeaveCriticalRegion ();
  4584. return status;
  4585. }
  4586. VOID
  4587. AfdSanProcessAddrListForProviderChange (
  4588. PAFD_ENDPOINT SpecificEndpoint OPTIONAL
  4589. )
  4590. /*++
  4591. Routine Description:
  4592. Fires address list notifications for SAN helper endpoints
  4593. to inform switch of Winsock provider list change.
  4594. Arguments:
  4595. SpecificEndpoint - optinally indentifies specific
  4596. helper endpoint to fire notifications for
  4597. Return Value:
  4598. None.
  4599. --*/
  4600. {
  4601. AFD_LOCK_QUEUE_HANDLE lockHandle;
  4602. PLIST_ENTRY listEntry;
  4603. LIST_ENTRY completedChangeList;
  4604. PAFD_ADDRESS_CHANGE change;
  4605. PAFD_REQUEST_CONTEXT requestCtx;
  4606. PIRP irp;
  4607. PIO_STACK_LOCATION irpSp;
  4608. PAFD_ENDPOINT endpoint;
  4609. LONG plsn;
  4610. ASSERT (SpecificEndpoint==NULL || IS_SAN_HELPER (SpecificEndpoint));
  4611. //
  4612. // Create local list to process notifications after spinlock is released
  4613. //
  4614. InitializeListHead (&completedChangeList);
  4615. //
  4616. // Walk the list and move matching notifications to the local list
  4617. //
  4618. AfdAcquireSpinLock (&AfdAddressChangeLock, &lockHandle);
  4619. if (SpecificEndpoint==NULL) {
  4620. //
  4621. // General notification, increment provider
  4622. // list change sequence number.
  4623. //
  4624. AfdSanProviderListSeqNum += 1;
  4625. if (AfdSanProviderListSeqNum==0) {
  4626. AfdSanProviderListSeqNum += 1;
  4627. }
  4628. }
  4629. plsn = AfdSanProviderListSeqNum;
  4630. listEntry = AfdAddressChangeList.Flink;
  4631. while (listEntry!=&AfdAddressChangeList) {
  4632. change = CONTAINING_RECORD (listEntry,
  4633. AFD_ADDRESS_CHANGE,
  4634. ChangeListLink);
  4635. listEntry = listEntry->Flink;
  4636. if (!change->NonBlocking) {
  4637. irp = change->Irp;
  4638. irpSp = IoGetCurrentIrpStackLocation (irp);
  4639. requestCtx = (PAFD_REQUEST_CONTEXT)&irpSp->Parameters.DeviceIoControl;
  4640. endpoint = irpSp->FileObject->FsContext;
  4641. ASSERT (change==(PAFD_ADDRESS_CHANGE)irp->Tail.Overlay.DriverContext);
  4642. if (IS_SAN_HELPER (endpoint) &&
  4643. (SpecificEndpoint==NULL ||
  4644. endpoint==SpecificEndpoint)) {
  4645. AFD_LOCK_QUEUE_HANDLE endpointLockHandle;
  4646. ASSERT (change->AddressType==TDI_ADDRESS_TYPE_IP);
  4647. RemoveEntryList (&change->ChangeListLink);
  4648. change->ChangeListLink.Flink = NULL;
  4649. //
  4650. // If request is already canceled, let cancel routine complete it
  4651. //
  4652. if (IoSetCancelRoutine (irp, NULL)==NULL) {
  4653. continue;
  4654. }
  4655. AfdAcquireSpinLockAtDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  4656. if (AfdIsRequestInQueue (requestCtx)) {
  4657. endpoint->Common.SanHlpr.Plsn = plsn;
  4658. //
  4659. // Context is still in the list, just remove it so
  4660. // no-one can see it anymore and complete
  4661. //
  4662. RemoveEntryList (&requestCtx->EndpointListLink);
  4663. InsertTailList (&completedChangeList,
  4664. &change->ChangeListLink);
  4665. }
  4666. else if (!AfdIsRequestCompleted (requestCtx)) {
  4667. //
  4668. // During endpoint cleanup, this context was removed from the
  4669. // list and cleanup routine is about to be called, don't
  4670. // free this IRP until cleanup routine is called
  4671. // Also, indicate to the cleanup routine that we are done
  4672. // with this IRP and it can free it.
  4673. //
  4674. AfdMarkRequestCompleted (requestCtx);
  4675. }
  4676. AfdReleaseSpinLockFromDpcLevel (&endpoint->SpinLock, &endpointLockHandle);
  4677. }
  4678. }
  4679. }
  4680. AfdReleaseSpinLock (&AfdAddressChangeLock, &lockHandle);
  4681. //
  4682. // Signal interested clients and complete IRPs as necessary
  4683. //
  4684. while (!IsListEmpty (&completedChangeList)) {
  4685. listEntry = RemoveHeadList (&completedChangeList);
  4686. change = CONTAINING_RECORD (listEntry,
  4687. AFD_ADDRESS_CHANGE,
  4688. ChangeListLink);
  4689. irp = change->Irp;
  4690. irp->IoStatus.Status = STATUS_SUCCESS;
  4691. //
  4692. // Assigning plsn (can't be 0) distinguishes
  4693. // this from regular address list change
  4694. // notification.
  4695. //
  4696. irp->IoStatus.Information = plsn;
  4697. IF_DEBUG (ADDRESS_LIST) {
  4698. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  4699. "AfdProcessAddressChangeList: Completing change IRP: %p with status: 0 .\n",
  4700. irp));
  4701. }
  4702. IoCompleteRequest (irp, AfdPriorityBoost);
  4703. }
  4704. }
  4705. NTSTATUS
  4706. AfdSanGetCompletionObjectTypePointer (
  4707. VOID
  4708. )
  4709. /*++
  4710. Routine Description:
  4711. Obtains completion port object type pointer for
  4712. completion port handle validation purposes.
  4713. Note, that this type is not exported from kernel like
  4714. most other types that afd uses.
  4715. Arguments:
  4716. None.
  4717. Return Value:
  4718. 0 - success, other - could not obtain reference.
  4719. --*/
  4720. {
  4721. NTSTATUS status;
  4722. UNICODE_STRING obName;
  4723. OBJECT_ATTRIBUTES obAttr;
  4724. HANDLE obHandle;
  4725. PVOID obType;
  4726. RtlInitUnicodeString (&obName, L"\\ObjectTypes\\IoCompletion");
  4727. InitializeObjectAttributes(
  4728. &obAttr,
  4729. &obName, // name
  4730. OBJ_KERNEL_HANDLE, // attributes
  4731. NULL, // root
  4732. NULL // security descriptor
  4733. );
  4734. status = ObOpenObjectByName (
  4735. &obAttr, // ObjectAttributes
  4736. NULL, // ObjectType
  4737. KernelMode, // AccessMode
  4738. NULL, // PassedAccessState
  4739. 0, // DesiredAccess
  4740. NULL, // DesiredAccess
  4741. &obHandle // Handle
  4742. );
  4743. if (NT_SUCCESS (status)) {
  4744. status = ObReferenceObjectByHandle (
  4745. obHandle,
  4746. 0, // DesiredAccess
  4747. NULL, // ObjectType
  4748. KernelMode, // AccessMode
  4749. &obType, // Object
  4750. NULL // HandleInformation
  4751. );
  4752. ZwClose (obHandle);
  4753. if (NT_SUCCESS (status)) {
  4754. //
  4755. // Make sure we only keep one reference to the object type
  4756. //
  4757. if (InterlockedCompareExchangePointer (
  4758. (PVOID *)&IoCompletionObjectType,
  4759. obType,
  4760. NULL)!=NULL) {
  4761. //
  4762. // The reference we have already must be the same
  4763. // is we just obtained - there should be only one
  4764. // completion object type in the system!
  4765. //
  4766. ASSERT (obType==(PVOID)IoCompletionObjectType);
  4767. //
  4768. // Get rid of the extra reference
  4769. //
  4770. ObDereferenceObject (obType);
  4771. }
  4772. }
  4773. }
  4774. return status;
  4775. }