Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1705 lines
57 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. socket.c
  5. Abstract:
  6. This module implements socket file object for ws2ifsl.sys driver.
  7. Author:
  8. Vadim Eydelman (VadimE) Dec-1996
  9. Revision History:
  10. Vadim Eydelman (VadimE) Oct-1997, rewrite to properly handle IRP
  11. cancellation
  12. --*/
  13. #include "precomp.h"
  14. VOID
  15. SetSocketContext (
  16. IN PFILE_OBJECT SocketFile,
  17. IN KPROCESSOR_MODE RequestorMode,
  18. IN PVOID InputBuffer,
  19. IN ULONG InputBufferLength,
  20. OUT PVOID OutputBuffer,
  21. IN ULONG OutputBufferLength,
  22. OUT PIO_STATUS_BLOCK IoStatus
  23. );
  24. VOID
  25. CompletePvdRequest (
  26. IN PFILE_OBJECT SocketFile,
  27. IN KPROCESSOR_MODE RequestorMode,
  28. IN PVOID InputBuffer,
  29. IN ULONG InputBufferLength,
  30. OUT PVOID OutputBuffer,
  31. IN ULONG OutputBufferLength,
  32. OUT PIO_STATUS_BLOCK IoStatus
  33. );
  34. VOID
  35. ProcessedCancelRoutine (
  36. IN PDEVICE_OBJECT DeviceObject,
  37. IN PIRP Irp
  38. );
  39. PIRP
  40. GetProcessedRequest (
  41. PIFSL_SOCKET_CTX SocketCtx,
  42. ULONG UniqueId
  43. );
  44. VOID
  45. CleanupProcessedRequests (
  46. PIFSL_SOCKET_CTX SocketCtx,
  47. PLIST_ENTRY IrpList
  48. );
  49. VOID
  50. CancelSocketIo (
  51. PFILE_OBJECT SocketFile
  52. );
  53. PFILE_OBJECT
  54. GetSocketProcessReference (
  55. IN PIFSL_SOCKET_CTX SocketCtx
  56. );
  57. PFILE_OBJECT
  58. SetSocketProcessReference (
  59. IN PIFSL_SOCKET_CTX SocketCtx,
  60. IN PFILE_OBJECT NewProcessFile,
  61. IN PVOID NewDllContext
  62. );
  63. NTSTATUS
  64. CompleteTargetQuery (
  65. IN PDEVICE_OBJECT DeviceObject,
  66. IN PIRP Irp,
  67. IN PVOID Context
  68. );
  69. #ifdef ALLOC_PRAGMA
  70. #pragma alloc_text(PAGE, CreateSocketFile)
  71. #pragma alloc_text(PAGE, CleanupSocketFile)
  72. #pragma alloc_text(PAGE, CloseSocketFile)
  73. #pragma alloc_text(PAGE, DoSocketReadWrite)
  74. #pragma alloc_text(PAGE, DoSocketAfdIoctl)
  75. #pragma alloc_text(PAGE, SetSocketContext)
  76. #pragma alloc_text(PAGE, CompleteDrvRequest)
  77. #pragma alloc_text(PAGE, CompletePvdRequest)
  78. #pragma alloc_text(PAGE, SocketPnPTargetQuery)
  79. //#pragma alloc_text (PAGE, CompleteTargetQuery) - should never be paged.
  80. #endif
  81. ULONG SocketIoctlCodeMap[2] = {
  82. #if WS2IFSL_IOCTL_FUNCTION(SOCKET,IOCTL_WS2IFSL_SET_SOCKET_CONTEXT)!=0
  83. #error Mismatch between IOCTL function code and SocketIoControlMap
  84. #endif
  85. IOCTL_WS2IFSL_SET_SOCKET_CONTEXT,
  86. #if WS2IFSL_IOCTL_FUNCTION(SOCKET,IOCTL_WS2IFSL_COMPLETE_PVD_REQ)!=1
  87. #error Mismatch between IOCTL function code and SocketIoControlMap
  88. #endif
  89. IOCTL_WS2IFSL_COMPLETE_PVD_REQ
  90. };
  91. PSOCKET_DEVICE_CONTROL SocketIoControlMap[2] = {
  92. SetSocketContext,
  93. CompletePvdRequest
  94. };
  95. #define GenerateUniqueId(curId) \
  96. ((ULONG)InterlockedIncrement (&(curId)))
  97. NTSTATUS
  98. CreateSocketFile (
  99. IN PFILE_OBJECT SocketFile,
  100. IN KPROCESSOR_MODE RequestorMode,
  101. IN PFILE_FULL_EA_INFORMATION eaInfo
  102. )
  103. /*++
  104. Routine Description:
  105. Allocates and initializes socket file context structure.
  106. Arguments:
  107. SocketFile - socket file object
  108. eaInfo - EA for socket file
  109. Return Value:
  110. STATUS_SUCCESS - operation completed OK
  111. STATUS_INSUFFICIENT_RESOURCES - not enough memory to allocate context
  112. --*/
  113. {
  114. NTSTATUS status = STATUS_SUCCESS;
  115. PIFSL_SOCKET_CTX SocketCtx;
  116. HANDLE hProcessFile;
  117. PFILE_OBJECT ProcessFile;
  118. PVOID DllContext;
  119. PAGED_CODE ();
  120. if (eaInfo->EaValueLength!=WS2IFSL_SOCKET_EA_VALUE_LENGTH) {
  121. WsPrint (DBG_SOCKET|DBG_FAILURES,
  122. ("WS2IFSL-%04lx CreateSocketFile: Invalid ea info size (%ld)"
  123. " for process file %p.\n",
  124. PsGetCurrentProcessId(),
  125. eaInfo->EaValueLength,
  126. SocketFile));
  127. return STATUS_INVALID_PARAMETER;
  128. }
  129. hProcessFile = GET_WS2IFSL_SOCKET_EA_VALUE(eaInfo)->ProcessFile;
  130. DllContext = GET_WS2IFSL_SOCKET_EA_VALUE(eaInfo)->DllContext;
  131. // Get reference to the process file with which this context is associated
  132. status = ObReferenceObjectByHandle(
  133. hProcessFile,
  134. FILE_ALL_ACCESS,
  135. *IoFileObjectType,
  136. RequestorMode,
  137. (PVOID *)&ProcessFile,
  138. NULL
  139. );
  140. if (NT_SUCCESS (status)) {
  141. // Verify that the file pointer is really our driver's process file
  142. // and that it created for the current process
  143. if ((IoGetRelatedDeviceObject (ProcessFile)
  144. ==DeviceObject)
  145. && ((*((PULONG)ProcessFile->FsContext))
  146. ==PROCESS_FILE_EANAME_TAG)
  147. && (((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId
  148. ==PsGetCurrentProcessId())) {
  149. // Allocate socket context and charge it to the process
  150. try {
  151. SocketCtx = (PIFSL_SOCKET_CTX) ExAllocatePoolWithQuotaTag (
  152. NonPagedPool,
  153. sizeof (IFSL_SOCKET_CTX),
  154. SOCKET_FILE_CONTEXT_TAG);
  155. }
  156. except (EXCEPTION_EXECUTE_HANDLER) {
  157. SocketCtx = NULL;
  158. status = GetExceptionCode ();
  159. }
  160. if (SocketCtx!=NULL) {
  161. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_SOCKET,
  162. ("WS2IFSL-%04lx CreateSocketFile: Created socket %p (ctx:%p)\n",
  163. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, SocketFile, SocketCtx));
  164. // Initialize socket context structure
  165. SocketCtx->EANameTag = SOCKET_FILE_EANAME_TAG;
  166. SocketCtx->DllContext = DllContext;
  167. SocketCtx->ProcessRef = ProcessFile;
  168. InitializeListHead (&SocketCtx->ProcessedIrps);
  169. KeInitializeSpinLock (&SocketCtx->SpinLock);
  170. SocketCtx->CancelCtx = NULL;
  171. SocketCtx->IrpId = 0;
  172. // Associate socket context with socket file
  173. SocketFile->FsContext = SocketCtx;
  174. return status;
  175. }
  176. else {
  177. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_FAILURES|DBG_SOCKET,
  178. ("WS2IFSL-%04lx CreateSocketFile: Could not allocate socket context\n",
  179. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId));
  180. if (NT_SUCCESS (status)) {
  181. ASSERT (FALSE);
  182. status = STATUS_INSUFFICIENT_RESOURCES;
  183. }
  184. }
  185. }
  186. else {
  187. // Handle refers to random file object
  188. WsPrint (DBG_SOCKET|DBG_FAILURES,
  189. ("WS2IFSL-%04lx CreateSocketFile: Procees file handle %p (File:%p)"
  190. " is not valid\n",
  191. PsGetCurrentProcessId(),
  192. ProcessFile, hProcessFile));
  193. status = STATUS_INVALID_PARAMETER;
  194. }
  195. ObDereferenceObject (ProcessFile);
  196. }
  197. else {
  198. WsPrint (DBG_SOCKET|DBG_FAILURES,
  199. ("WS2IFSL-%04lx CreateSocketFile: Could not get process file from handle %p,"
  200. " status:%lx.\n",
  201. PsGetCurrentProcessId(),
  202. hProcessFile,
  203. status));
  204. }
  205. return status;
  206. } // CreateSocketFile
  207. NTSTATUS
  208. CleanupSocketFile (
  209. IN PFILE_OBJECT SocketFile,
  210. IN PIRP Irp
  211. )
  212. /*++
  213. Routine Description:
  214. Initiates socket file cleanup in context of current process.
  215. Arguments:
  216. SocketFile - socket file object
  217. Irp - cleanup request
  218. Return Value:
  219. STATUS_PENDING - operation initiated OK
  220. STATUS_INVALID_HANDLE - socket has not been initialized
  221. in current process
  222. --*/
  223. {
  224. NTSTATUS status;
  225. PIFSL_SOCKET_CTX SocketCtx;
  226. PFILE_OBJECT ProcessFile;
  227. LIST_ENTRY irpList;
  228. PIFSL_CANCEL_CTX cancelCtx;
  229. PAGED_CODE ();
  230. SocketCtx = SocketFile->FsContext;
  231. ProcessFile = GetSocketProcessReference (SocketCtx);
  232. WsProcessPrint ((PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext, DBG_SOCKET,
  233. ("WS2IFSL-%04lx CleanupSocketFile: Socket %p \n",
  234. GET_SOCKET_PROCESSID(SocketCtx), SocketFile));
  235. //
  236. // Build the list of IRPS still panding on this socket
  237. //
  238. InitializeListHead (&irpList);
  239. CleanupQueuedRequests (ProcessFile->FsContext,
  240. SocketFile,
  241. &irpList);
  242. CleanupProcessedRequests (SocketCtx, &irpList);
  243. //
  244. // Complete the cancelled IRPS
  245. //
  246. while (!IsListEmpty (&irpList)) {
  247. PLIST_ENTRY entry;
  248. PIRP irp;
  249. entry = RemoveHeadList (&irpList);
  250. irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
  251. irp->IoStatus.Status = STATUS_CANCELLED;
  252. irp->IoStatus.Information = 0;
  253. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_SOCKET,
  254. ("WS2IFSL-%04lx CleanupSocketFile: Cancelling Irp %p on socket %p \n",
  255. GET_SOCKET_PROCESSID(SocketCtx), irp, SocketFile));
  256. CompleteSocketIrp (irp);
  257. }
  258. //
  259. // Indicate that cleanup routine is going to take care of the
  260. // pending cancel request if any.
  261. //
  262. cancelCtx = InterlockedExchangePointer (
  263. (PVOID *)&SocketCtx->CancelCtx,
  264. NULL);
  265. if (cancelCtx!=NULL) {
  266. //
  267. // We are going to try to free this request if it is still in the queue
  268. //
  269. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_SOCKET,
  270. ("WS2IFSL-%04lx CleanupSocketFile: Removing cancel ctx %p on socket %p \n",
  271. GET_SOCKET_PROCESSID(SocketCtx), cancelCtx, SocketFile));
  272. if (RemoveQueuedCancel (ProcessFile->FsContext, cancelCtx)) {
  273. //
  274. // Request was in the queue, it is safe to call regular free routine
  275. // (no-one else will find it now, so it is safe to put the pointer
  276. // back in place so that FreeSocketCancel can free it)
  277. //
  278. SocketCtx->CancelCtx = cancelCtx;
  279. FreeSocketCancel (cancelCtx);
  280. }
  281. else {
  282. //
  283. // Someone else managed to remove the request from the queue before
  284. // we did, let them or close routine free it. We aren't going to
  285. // touch it after this.
  286. //
  287. SocketCtx->CancelCtx = cancelCtx;
  288. }
  289. }
  290. status = STATUS_SUCCESS;
  291. ObDereferenceObject (ProcessFile);
  292. return status;
  293. } // CleanupSocketFile
  294. VOID
  295. CloseSocketFile (
  296. IN PFILE_OBJECT SocketFile
  297. )
  298. /*++
  299. Routine Description:
  300. Deallocates all resources associated with socket file
  301. Arguments:
  302. SocketFile - socket file object
  303. Return Value:
  304. None
  305. --*/
  306. {
  307. PIFSL_SOCKET_CTX SocketCtx = SocketFile->FsContext;
  308. PAGED_CODE ();
  309. WsProcessPrint ((PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext, DBG_SOCKET,
  310. ("WS2IFSL-%04lx CloseSocketFile: Socket %p \n",
  311. GET_SOCKET_PROCESSID(SocketCtx), SocketFile));
  312. // First dereference process file
  313. ObDereferenceObject (SocketCtx->ProcessRef);
  314. if (SocketCtx->CancelCtx!=NULL) {
  315. ExFreePool (SocketCtx->CancelCtx);
  316. }
  317. // Free context
  318. ExFreePool (SocketCtx);
  319. } // CloseSocketFile
  320. NTSTATUS
  321. DoSocketReadWrite (
  322. IN PFILE_OBJECT SocketFile,
  323. IN PIRP Irp
  324. )
  325. /*++
  326. Routine Description:
  327. Initiates read and write request processing on socket file.
  328. Arguments:
  329. SocketFile - socket file object
  330. Irp - read/write request
  331. Return Value:
  332. STATUS_PENDING - operation initiated OK
  333. STATUS_INVALID_HANDLE - socket has not been initialized
  334. in current process
  335. --*/
  336. {
  337. NTSTATUS status;
  338. PIFSL_SOCKET_CTX SocketCtx;
  339. PFILE_OBJECT ProcessFile;
  340. PIO_STACK_LOCATION irpSp;
  341. PAGED_CODE ();
  342. irpSp = IoGetCurrentIrpStackLocation (Irp);
  343. SocketCtx = SocketFile->FsContext;
  344. ProcessFile = GetSocketProcessReference (SocketCtx);
  345. if (((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId==PsGetCurrentProcessId()) {
  346. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_READWRITE,
  347. ("WS2IFSL-%04lx DoSocketReadWrite: %s irp %p on socket %p, len %ld.\n",
  348. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId,
  349. irpSp->MajorFunction==IRP_MJ_READ ? "Read" : "Write",
  350. Irp, SocketFile,
  351. irpSp->MajorFunction==IRP_MJ_READ
  352. ? irpSp->Parameters.Read.Length
  353. : irpSp->Parameters.Write.Length));
  354. //
  355. // Allocate MDL to describe the user buffer.
  356. //
  357. Irp->MdlAddress = IoAllocateMdl(
  358. Irp->UserBuffer, // VirtualAddress
  359. irpSp->Parameters.DeviceIoControl.OutputBufferLength,
  360. // Length
  361. FALSE, // SecondaryBuffer
  362. TRUE, // ChargeQuota
  363. NULL // Irp
  364. );
  365. if (Irp->MdlAddress!=NULL) {
  366. // We are going to pend this request
  367. IoMarkIrpPending (Irp);
  368. // Prepare IRP for insertion into the queue
  369. Irp->Tail.Overlay.IfslRequestId = UlongToPtr(GenerateUniqueId (SocketCtx->IrpId));
  370. Irp->Tail.Overlay.IfslRequestFlags = (PVOID)0;
  371. Irp->Tail.Overlay.IfslAddressLenPtr = NULL;
  372. Irp->Tail.Overlay.IfslRequestQueue = NULL;
  373. if (!QueueRequest (ProcessFile->FsContext, Irp)) {
  374. Irp->IoStatus.Status = STATUS_CANCELLED;
  375. Irp->IoStatus.Information = 0;
  376. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_READWRITE,
  377. ("WS2IFSL-%04lx DoSocketReadWrite: Cancelling Irp %p on socket %p.\n",
  378. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId,
  379. Irp, SocketFile));
  380. CompleteSocketIrp (Irp);
  381. }
  382. status = STATUS_PENDING;
  383. }
  384. else {
  385. WsPrint (DBG_SOCKET|DBG_READWRITE|DBG_FAILURES,
  386. ("WS2IFSL-%04lx DoSocketReadWrite: Failed to allocate Mdl for Irp %p"
  387. " on socket %p, status %lx.\n",
  388. PsGetCurrentProcessId(), Irp, SocketFile));;
  389. status = STATUS_INSUFFICIENT_RESOURCES;
  390. }
  391. }
  392. else {
  393. status = STATUS_INVALID_HANDLE;
  394. WsPrint (DBG_SOCKET|DBG_READWRITE|DBG_FAILURES,
  395. ("WS2IFSL-%04lx DoSocketReadWrite: Socket %p has not"
  396. " been setup in the process.\n",
  397. PsGetCurrentProcessId(), SocketFile));
  398. }
  399. ObDereferenceObject (ProcessFile);
  400. return status;
  401. } // DoSocketReadWrite
  402. NTSTATUS
  403. DoSocketAfdIoctl (
  404. IN PFILE_OBJECT SocketFile,
  405. IN PIRP Irp
  406. )
  407. /*++
  408. Routine Description:
  409. Initiates read and write request processing on socket file.
  410. Arguments:
  411. SocketFile - socket file object
  412. Irp - afd IOCTL request
  413. Return Value:
  414. STATUS_PENDING - operation initiated OK
  415. STATUS_INVALID_HANDLE - socket has not been initialized
  416. in current process
  417. --*/
  418. {
  419. NTSTATUS status;
  420. PIO_STACK_LOCATION irpSp;
  421. PIFSL_SOCKET_CTX SocketCtx;
  422. PFILE_OBJECT ProcessFile;
  423. LPWSABUF bufferArray = NULL;
  424. ULONG bufferCount = 0, length = 0, flags = 0;
  425. PVOID address = NULL;
  426. PULONG lengthPtr = NULL;
  427. PAGED_CODE ();
  428. irpSp = IoGetCurrentIrpStackLocation (Irp);
  429. Irp->IoStatus.Information = 0;
  430. SocketCtx = SocketFile->FsContext;
  431. ProcessFile = GetSocketProcessReference (SocketCtx);
  432. if (((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId==PsGetCurrentProcessId()) {
  433. try {
  434. if (Irp->RequestorMode!=KernelMode) {
  435. ProbeForRead (
  436. irpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  437. irpSp->Parameters.DeviceIoControl.InputBufferLength,
  438. sizeof (ULONG));
  439. }
  440. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  441. case IOCTL_AFD_RECEIVE_DATAGRAM: {
  442. PAFD_RECV_DATAGRAM_INFO info;
  443. if (irpSp->Parameters.DeviceIoControl.InputBufferLength
  444. < sizeof (*info)) {
  445. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  446. }
  447. info = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  448. bufferArray = info->BufferArray;
  449. bufferCount = info->BufferCount;
  450. address = info->Address;
  451. lengthPtr = info->AddressLength;
  452. if ((address == NULL) ^ (lengthPtr == NULL)) {
  453. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  454. }
  455. if (Irp->RequestorMode!=KernelMode) {
  456. ProbeForRead (
  457. lengthPtr,
  458. sizeof (*lengthPtr),
  459. sizeof (ULONG));
  460. }
  461. length = *lengthPtr;
  462. if (address != NULL ) {
  463. //
  464. // Bomb off if the user is trying to do something bad, like
  465. // specify a zero-length address, or one that's unreasonably
  466. // huge. Here, we (arbitrarily) define "unreasonably huge" as
  467. // anything 64K or greater.
  468. //
  469. if( length == 0 ||
  470. length >= 65536 ) {
  471. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  472. }
  473. }
  474. flags = info->TdiFlags;
  475. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_AFDIOCTL,
  476. ("WS2IFSL-%04lx DoSocketAfdIoctl: RecvFrom irp %p, socket %p,"
  477. " arr %p, cnt %ld, addr %p, lenp %p, len %ld, flags %lx.\n",
  478. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, Irp, SocketFile,
  479. bufferArray, bufferCount, address, lengthPtr, length, flags));
  480. break;
  481. }
  482. case IOCTL_AFD_RECEIVE: {
  483. PAFD_RECV_INFO info;
  484. if (irpSp->Parameters.DeviceIoControl.InputBufferLength
  485. < sizeof (*info)) {
  486. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  487. }
  488. info = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  489. bufferArray = info->BufferArray;
  490. bufferCount = info->BufferCount;
  491. flags = info->TdiFlags;
  492. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_AFDIOCTL,
  493. ("WS2IFSL-%04lx DoSocketAfdIoctl: Recv irp %p, socket %p,"
  494. " arr %p, cnt %ld, flags %lx.\n",
  495. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, Irp, SocketFile,
  496. bufferArray, bufferCount, flags));
  497. break;
  498. }
  499. case IOCTL_AFD_SEND_DATAGRAM: {
  500. PAFD_SEND_DATAGRAM_INFO info;
  501. if (irpSp->Parameters.DeviceIoControl.InputBufferLength
  502. < sizeof (*info)) {
  503. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  504. }
  505. info = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  506. bufferArray = info->BufferArray;
  507. bufferCount = info->BufferCount;
  508. address = &(((PTRANSPORT_ADDRESS)
  509. info->TdiConnInfo.RemoteAddress)->Address[0].AddressType);
  510. length = info->TdiConnInfo.RemoteAddressLength
  511. - FIELD_OFFSET (TRANSPORT_ADDRESS, Address[0].AddressType);
  512. //
  513. // Bomb off if the user is trying to do something bad, like
  514. // specify a zero-length address, or one that's unreasonably
  515. // huge. Here, we (arbitrarily) define "unreasonably huge" as
  516. // anything 64K or greater.
  517. //
  518. if( length == 0 ||
  519. length >= 65536 ) {
  520. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  521. }
  522. if( Irp->RequestorMode != KernelMode ) {
  523. ProbeForRead (
  524. address,
  525. length,
  526. sizeof (UCHAR));
  527. }
  528. flags = 0;
  529. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_AFDIOCTL,
  530. ("WS2IFSL-%04lx DoSocketAfdIoctl: SendTo irp %p, socket %p,"
  531. " arr %p, cnt %ld, addr %p, len %ld, flags %lx.\n",
  532. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, Irp, SocketFile,
  533. bufferArray, bufferCount, address, length, flags));
  534. break;
  535. }
  536. default:
  537. ASSERTMSG ("Unknown IOCTL!!!", FALSE);
  538. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  539. }
  540. AllocateMdlChain (Irp,
  541. bufferArray,
  542. bufferCount,
  543. &irpSp->Parameters.DeviceIoControl.OutputBufferLength);
  544. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_AFDIOCTL,
  545. ("WS2IFSL-%04lx DoSocketAfdIoctl: %s irp %p, socket %p,"
  546. " arr %p, cnt %ld, addr %p, lenp %p, len %ld, flags %lx.\n",
  547. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId,
  548. irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_RECEIVE_DATAGRAM
  549. ? "RecvFrom"
  550. : (irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_RECEIVE
  551. ? "Recv"
  552. : "SendTo"
  553. ),
  554. Irp, SocketFile,
  555. bufferArray, bufferCount, address, lengthPtr, length, flags));
  556. }
  557. except (EXCEPTION_EXECUTE_HANDLER) {
  558. status = GetExceptionCode ();
  559. WsPrint (DBG_SOCKET|DBG_AFDIOCTL|DBG_FAILURES,
  560. ("WS2IFSL-%04lx DoSocketAfdIoctl: Failed to process Irp %p"
  561. " on socket %p, status %lx.\n",
  562. PsGetCurrentProcessId(), Irp, SocketFile, status));;
  563. goto Exit;
  564. }
  565. // We are going to pend this request
  566. IoMarkIrpPending (Irp);
  567. // Prepare IRP for insertion into the queue
  568. irpSp->Parameters.DeviceIoControl.IfslAddressBuffer = address;
  569. irpSp->Parameters.DeviceIoControl.IfslAddressLength = length;
  570. Irp->Tail.Overlay.IfslRequestId = UlongToPtr(GenerateUniqueId (SocketCtx->IrpId));
  571. Irp->Tail.Overlay.IfslAddressLenPtr = lengthPtr;
  572. Irp->Tail.Overlay.IfslRequestFlags = UlongToPtr(flags);
  573. Irp->Tail.Overlay.IfslRequestQueue = NULL;
  574. if (!QueueRequest (ProcessFile->FsContext, Irp)) {
  575. Irp->IoStatus.Status = STATUS_CANCELLED;
  576. Irp->IoStatus.Information = 0;
  577. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_AFDIOCTL,
  578. ("WS2IFSL-%04lx DoAfdIoctl: Cancelling Irp %p on socket %p.\n",
  579. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId,
  580. Irp, SocketFile));
  581. CompleteSocketIrp (Irp);
  582. }
  583. status = STATUS_PENDING;
  584. }
  585. else {
  586. status = STATUS_INVALID_HANDLE;
  587. WsPrint (DBG_SOCKET|DBG_AFDIOCTL|DBG_FAILURES,
  588. ("WS2IFSL-%04lx DoSocketAfdIoctl: Socket %p has not"
  589. " been setup in the process\n",
  590. PsGetCurrentProcessId(), SocketFile));
  591. }
  592. Exit:
  593. ObDereferenceObject (ProcessFile);
  594. return status;
  595. } // DoSocketAfdIoctl
  596. VOID
  597. SetSocketContext (
  598. IN PFILE_OBJECT SocketFile,
  599. IN KPROCESSOR_MODE RequestorMode,
  600. IN PVOID InputBuffer,
  601. IN ULONG InputBufferLength,
  602. OUT PVOID OutputBuffer,
  603. IN ULONG OutputBufferLength,
  604. OUT PIO_STATUS_BLOCK IoStatus
  605. )
  606. /*++
  607. Routine Description:
  608. Sets up socket file in context of a current process: associates it with
  609. process file and assigns context supplied by the caller
  610. Arguments:
  611. SocketFile - Socket file on which to operate
  612. InputBuffer - input buffer pointer
  613. InputBufferLength - size of the input buffer
  614. OutputBuffer - output buffer pointer
  615. OutputBufferLength - size of output buffer
  616. IoStatus - IO status information block
  617. Return Value:
  618. None (result returned via IoStatus block)
  619. --*/
  620. {
  621. PIFSL_SOCKET_CTX SocketCtx;
  622. HANDLE hProcessFile;
  623. PFILE_OBJECT ProcessFile;
  624. PVOID DllContext;
  625. PAGED_CODE ();
  626. IoStatus->Information = 0;
  627. SocketCtx = SocketFile->FsContext;
  628. // First check arguments
  629. if (InputBufferLength<sizeof (WS2IFSL_SOCKET_CTX)) {
  630. IoStatus->Status = STATUS_INVALID_PARAMETER;
  631. WsPrint (DBG_SOCKET|DBG_FAILURES,
  632. ("WS2IFSL-%04lx SetSocketContext: Invalid input buffer size (%ld)"
  633. " for socket file %p.\n",
  634. PsGetCurrentProcessId(),
  635. InputBufferLength,
  636. SocketFile));
  637. return;
  638. }
  639. try {
  640. if (RequestorMode!=KernelMode) {
  641. ProbeForRead (InputBuffer,
  642. sizeof (WS2IFSL_SOCKET_CTX),
  643. sizeof (ULONG));
  644. }
  645. hProcessFile = ((PWS2IFSL_SOCKET_CTX)InputBuffer)->ProcessFile;
  646. DllContext = ((PWS2IFSL_SOCKET_CTX)InputBuffer)->DllContext;
  647. }
  648. except(EXCEPTION_EXECUTE_HANDLER) {
  649. IoStatus->Status = GetExceptionCode ();
  650. WsPrint (DBG_SOCKET|DBG_FAILURES,
  651. ("WS2IFSL-%04lx SetSocketContext: Invalid input buffer (%p)"
  652. " for socket file %p.\n",
  653. PsGetCurrentProcessId(),
  654. InputBuffer,
  655. SocketFile));
  656. return;
  657. }
  658. // Get reference to the process file with which this context is associated
  659. IoStatus->Status = ObReferenceObjectByHandle(
  660. hProcessFile,
  661. FILE_ALL_ACCESS,
  662. *IoFileObjectType,
  663. RequestorMode,
  664. (PVOID *)&ProcessFile,
  665. NULL
  666. );
  667. if (NT_SUCCESS (IoStatus->Status)) {
  668. // Verify that the file pointer is really our driver's process file
  669. // and that it created for the current process
  670. if ((IoGetRelatedDeviceObject (ProcessFile)
  671. ==DeviceObject)
  672. && ((*((PULONG)ProcessFile->FsContext))
  673. ==PROCESS_FILE_EANAME_TAG)
  674. && (((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId
  675. ==PsGetCurrentProcessId())) {
  676. PFILE_OBJECT oldProcessFile;
  677. oldProcessFile = SetSocketProcessReference (
  678. SocketCtx,
  679. ProcessFile,
  680. DllContext);
  681. if (oldProcessFile==ProcessFile) {
  682. // Old socket, just reset DLL context
  683. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_SOCKET,
  684. ("WS2IFSL-%04lx ResetSocketContext:"
  685. " Socket %p (h:%p->%p)\n",
  686. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, SocketFile,
  687. SocketCtx->DllContext, DllContext));
  688. }
  689. else {
  690. LIST_ENTRY irpList;
  691. // Socket moved to a different process
  692. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_SOCKET,
  693. ("WS2IFSL-%04lx ResetSocketContext:"
  694. " Socket %p (f:%p->%p(h:%p)\n",
  695. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, SocketFile,
  696. oldProcessFile, ProcessFile, DllContext));
  697. InitializeListHead (&irpList);
  698. // Make sure we do not keep IRPs that are queued to
  699. // the old object as it may go away as soon as we
  700. // dereference it below. Note that processed IRPs
  701. // do not reference process file object in any way.
  702. CleanupQueuedRequests (oldProcessFile->FsContext, SocketFile, &irpList);
  703. while (!IsListEmpty (&irpList)) {
  704. PLIST_ENTRY entry;
  705. PIRP irp;
  706. entry = RemoveHeadList (&irpList);
  707. irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
  708. irp->IoStatus.Status = STATUS_CANCELLED;
  709. irp->IoStatus.Information = 0;
  710. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_SOCKET,
  711. ("WS2IFSL-%04lx ResetSocketContext: Cancelling Irp %p on socket %p \n",
  712. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId, irp, SocketFile));
  713. CompleteSocketIrp (irp);
  714. }
  715. // Dereference the old object below
  716. ProcessFile = oldProcessFile;
  717. }
  718. }
  719. else {
  720. // Handle refers to random file object
  721. WsPrint (DBG_SOCKET|DBG_FAILURES,
  722. ("WS2IFSL-%04lx SetSocketContext: Procees file handle %p (File:%p)"
  723. " is not valid in the process.\n",
  724. PsGetCurrentProcessId(),
  725. ProcessFile, hProcessFile));
  726. IoStatus->Status = STATUS_INVALID_PARAMETER;
  727. }
  728. ObDereferenceObject (ProcessFile);
  729. }
  730. else {
  731. WsPrint (DBG_SOCKET|DBG_FAILURES,
  732. ("WS2IFSL-%04lx SetSocketContext: Could not get process file from handle %p,"
  733. " status:%lx.\n",
  734. PsGetCurrentProcessId(),
  735. hProcessFile,
  736. IoStatus->Status));
  737. }
  738. } //SetSocketContext
  739. VOID
  740. CompletePvdRequest (
  741. IN PFILE_OBJECT SocketFile,
  742. IN KPROCESSOR_MODE RequestorMode,
  743. IN PVOID InputBuffer,
  744. IN ULONG InputBufferLength,
  745. OUT PVOID OutputBuffer,
  746. IN ULONG OutputBufferLength,
  747. OUT PIO_STATUS_BLOCK IoStatus
  748. )
  749. /*++
  750. Routine Description:
  751. Completes this IOCTL to allow completion port usage by non-IFS providers
  752. Arguments:
  753. SocketFile - Socket file on which to operate
  754. InputBuffer - input buffer pointer
  755. contains IoStatus structure to be returned
  756. as the result of this call
  757. InputBufferLength - size of the input buffer
  758. OutputBuffer - NULL
  759. OutputBufferLength - 0
  760. IoStatus - IO status information block
  761. Return Value:
  762. None (result returned via IoStatus block)
  763. --*/
  764. {
  765. PIFSL_SOCKET_CTX SocketCtx;
  766. PFILE_OBJECT ProcessFile;
  767. PAGED_CODE();
  768. IoStatus->Information = 0;
  769. // First check arguments
  770. if (InputBufferLength<sizeof (IO_STATUS_BLOCK)) {
  771. IoStatus->Status = STATUS_INVALID_PARAMETER;
  772. WsPrint (DBG_PVD_COMPLETE|DBG_FAILURES,
  773. ("WS2IFSL-%04lx CompletePvdRequest: Invalid input buffer size (%ld)"
  774. " for socket file %p.\n",
  775. PsGetCurrentProcessId(),
  776. InputBufferLength,
  777. SocketFile));
  778. return;
  779. }
  780. SocketCtx = SocketFile->FsContext;
  781. ProcessFile = GetSocketProcessReference (SocketCtx);
  782. if (((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId==PsGetCurrentProcessId()) {
  783. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_PVD_COMPLETE,
  784. ("WS2IFSL-%04lx CompletePvdRequest: Socket %p (h:%p,cport:%p)\n",
  785. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId,
  786. SocketFile, SocketCtx->DllContext,
  787. SocketFile->CompletionContext));
  788. // Carefully write status info
  789. try {
  790. if (RequestorMode!=KernelMode)
  791. ProbeForRead (InputBuffer,
  792. sizeof (IO_STATUS_BLOCK),
  793. sizeof (ULONG));
  794. *IoStatus = *((PIO_STATUS_BLOCK)InputBuffer);
  795. }
  796. except(EXCEPTION_EXECUTE_HANDLER) {
  797. IoStatus->Status = GetExceptionCode ();
  798. WsPrint (DBG_SOCKET|DBG_FAILURES,
  799. ("WS2IFSL-%04lx CompletePvdRequest: Invalid input buffer (%p)"
  800. " for socket file %p.\n",
  801. PsGetCurrentProcessId(),
  802. InputBuffer,
  803. SocketFile));
  804. }
  805. }
  806. else {
  807. IoStatus->Status = STATUS_INVALID_HANDLE;
  808. WsPrint (DBG_SOCKET|DBG_PVD_COMPLETE|DBG_FAILURES,
  809. ("WS2IFSL-%04lx CompletePvdRequest: Socket %p has not"
  810. " been setup in the process\n",
  811. PsGetCurrentProcessId(), SocketFile));
  812. }
  813. ObDereferenceObject (ProcessFile);
  814. } //CompletePvdRequest
  815. VOID
  816. CompleteDrvRequest (
  817. IN PFILE_OBJECT SocketFile,
  818. IN PWS2IFSL_CMPL_PARAMS Params,
  819. IN PVOID OutputBuffer,
  820. IN ULONG OutputBufferLength,
  821. OUT PIO_STATUS_BLOCK IoStatus
  822. )
  823. /*++
  824. Routine Description:
  825. Complete request that was prviously passed to user mode DLL
  826. Arguments:
  827. SocketFile - Socket file on which to operate
  828. Params - description of the parameters
  829. OutputBuffer - Request results (data and address)
  830. OutputBufferLength - sizeof result buffer
  831. IoStatus - IO status information block
  832. Status: STATUS_SUCCESS - request was completed OK
  833. STATUS_CANCELLED - request was already cancelled
  834. Return Value:
  835. None (result returned via IoStatus block)
  836. --*/
  837. {
  838. PIFSL_SOCKET_CTX SocketCtx;
  839. PIRP irp = NULL;
  840. PIO_STACK_LOCATION irpSp;
  841. PAGED_CODE();
  842. SocketCtx = SocketFile->FsContext;
  843. // Check and copy parameters
  844. try {
  845. //
  846. // Try to find matching IRP in the processed list.
  847. //
  848. irp = GetProcessedRequest (SocketCtx, Params->UniqueId);
  849. if (irp!=NULL) {
  850. NTSTATUS status = Params->Status , status2 = 0;
  851. ULONG bytesCopied;
  852. irpSp = IoGetCurrentIrpStackLocation (irp);
  853. //
  854. // Copy data based on the function we performed
  855. //
  856. switch (irpSp->MajorFunction) {
  857. case IRP_MJ_DEVICE_CONTROL:
  858. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  859. case IOCTL_AFD_RECEIVE_DATAGRAM:
  860. //
  861. // Copy address buffer and length
  862. //
  863. if (irpSp->Parameters.DeviceIoControl.IfslAddressBuffer!=NULL) {
  864. ULONG addrOffset = ADDR_ALIGN(irpSp->Parameters.DeviceIoControl.OutputBufferLength);
  865. if (addrOffset+Params->AddrLen > OutputBufferLength) {
  866. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  867. }
  868. if (Params->AddrLen
  869. <=irpSp->Parameters.DeviceIoControl.IfslAddressLength) {
  870. RtlCopyMemory (
  871. irpSp->Parameters.DeviceIoControl.IfslAddressBuffer,
  872. (PUCHAR)OutputBuffer+addrOffset,
  873. Params->AddrLen);
  874. }
  875. else {
  876. RtlCopyMemory (
  877. irpSp->Parameters.DeviceIoControl.IfslAddressBuffer,
  878. (PUCHAR)OutputBuffer+addrOffset,
  879. irpSp->Parameters.DeviceIoControl.IfslAddressLength);
  880. status2 = STATUS_BUFFER_OVERFLOW;
  881. }
  882. }
  883. if (NT_SUCCESS (status2) && irp->UserBuffer) {
  884. *((PULONG)(irp->Tail.Overlay.IfslAddressLenPtr)) = Params->AddrLen;
  885. }
  886. //
  887. // Drop through to copy data as well
  888. //
  889. case IOCTL_AFD_RECEIVE:
  890. break;
  891. case IOCTL_AFD_SEND_DATAGRAM:
  892. goto NoCopy;
  893. break;
  894. default:
  895. ASSERTMSG ("Unsupported IOCTL!!!", FALSE);
  896. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  897. break;
  898. }
  899. //
  900. // Drop through to copy data as well
  901. //
  902. case IRP_MJ_READ:
  903. if (irp->MdlAddress!=NULL) {
  904. bytesCopied = CopyBufferToMdlChain (
  905. OutputBuffer,
  906. Params->DataLen,
  907. irp->MdlAddress);
  908. }
  909. else
  910. bytesCopied = 0;
  911. if ((bytesCopied<Params->DataLen)
  912. && NT_SUCCESS (status))
  913. status = STATUS_BUFFER_OVERFLOW;
  914. break;
  915. case IRP_MJ_WRITE:
  916. bytesCopied = Params->DataLen;
  917. // goto NoCopy; // same as break;
  918. break;
  919. case IRP_MJ_PNP:
  920. if (OutputBufferLength>=sizeof (HANDLE)) {
  921. PDEVICE_OBJECT targetDevice;
  922. PIRP targetIrp;
  923. PIO_STACK_LOCATION targetSp;
  924. status = ObReferenceObjectByHandle (
  925. *((PHANDLE)OutputBuffer),
  926. MAXIMUM_ALLOWED,
  927. *IoFileObjectType,
  928. irp->RequestorMode,
  929. (PVOID *)&irpSp->FileObject,
  930. NULL
  931. );
  932. if (NT_SUCCESS (status)) {
  933. targetDevice = IoGetRelatedDeviceObject (irpSp->FileObject);
  934. targetIrp = IoBuildAsynchronousFsdRequest (
  935. IRP_MJ_PNP,
  936. targetDevice,
  937. NULL,
  938. 0,
  939. NULL,
  940. NULL
  941. );
  942. if (targetIrp!=NULL) {
  943. targetSp = IoGetNextIrpStackLocation (targetIrp);
  944. *targetSp = *irpSp;
  945. targetSp->FileObject = irpSp->FileObject;
  946. IoSetCompletionRoutine( targetIrp, CompleteTargetQuery, irp, TRUE, TRUE, TRUE );
  947. IoCallDriver (targetDevice, targetIrp);
  948. goto NoCompletion;
  949. }
  950. else {
  951. ObDereferenceObject (irpSp->FileObject);
  952. status = STATUS_INSUFFICIENT_RESOURCES;
  953. }
  954. }
  955. }
  956. else {
  957. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  958. }
  959. break;
  960. default:
  961. ASSERTMSG ("Unsupported MJ code!!!", FALSE);
  962. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  963. break;
  964. }
  965. NoCopy:
  966. irp->IoStatus.Information = bytesCopied;
  967. if (NT_SUCCESS (status)) {
  968. irp->IoStatus.Status = status2;
  969. }
  970. else {
  971. irp->IoStatus.Status = status;
  972. }
  973. WsProcessPrint (
  974. (PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext,
  975. DBG_DRV_COMPLETE,
  976. ("WS2IFSL-%04lx CompleteDrvRequest: Irp %p, status %lx, info %ld,"
  977. " on socket %p (h:%p).\n",
  978. GET_SOCKET_PROCESSID(SocketCtx),
  979. irp, irp->IoStatus.Status,
  980. irp->IoStatus.Information,
  981. SocketFile, SocketCtx->DllContext));
  982. CompleteSocketIrp (irp);
  983. NoCompletion:
  984. IoStatus->Status = STATUS_SUCCESS;
  985. }
  986. else {
  987. IoStatus->Status = STATUS_CANCELLED;
  988. WsProcessPrint (
  989. (PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext,
  990. DBG_DRV_COMPLETE|DBG_FAILURES,
  991. ("WS2IFSL-%04lx CompleteDrvRequest:"
  992. " Request id %ld is not in the list"
  993. " for socket %p.\n",
  994. GET_SOCKET_PROCESSID(SocketCtx),
  995. Params->UniqueId,
  996. SocketFile));
  997. }
  998. }
  999. except(EXCEPTION_EXECUTE_HANDLER) {
  1000. IoStatus->Status = GetExceptionCode ();
  1001. WsProcessPrint (
  1002. (PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext,
  1003. DBG_DRV_COMPLETE|DBG_FAILURES,
  1004. ("WS2IFSL-%04lx CompleteDrvRequest: Failed to process"
  1005. " Irp %p (id %ld) for socket %p, status %lx.\n",
  1006. GET_SOCKET_PROCESSID(SocketCtx),
  1007. irp, Params->UniqueId,
  1008. SocketFile, IoStatus->Status));
  1009. if (irp!=NULL) {
  1010. //
  1011. // Cleanup and complete the irp
  1012. //
  1013. irp->IoStatus.Status = IoStatus->Status;
  1014. irp->IoStatus.Information = 0;
  1015. if (irpSp->MajorFunction==IRP_MJ_DEVICE_CONTROL) {
  1016. irp->UserBuffer = NULL;
  1017. }
  1018. CompleteSocketIrp (irp);
  1019. }
  1020. }
  1021. } //CompleteDrvRequest
  1022. NTSTATUS
  1023. CompleteTargetQuery (
  1024. IN PDEVICE_OBJECT DeviceObject,
  1025. IN PIRP Irp,
  1026. IN PVOID Context
  1027. )
  1028. {
  1029. PIRP irp = Context;
  1030. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
  1031. //
  1032. // If pending has be returned for this irp then mark the current
  1033. // stack as pending.
  1034. //
  1035. if ( Irp->PendingReturned ) {
  1036. IoMarkIrpPending(Irp);
  1037. }
  1038. ObDereferenceObject (irpSp->FileObject);
  1039. //
  1040. // Copy the status info returned by target device
  1041. //
  1042. irp->IoStatus = Irp->IoStatus;
  1043. //
  1044. // Free the target irp;
  1045. //
  1046. IoFreeIrp (Irp);
  1047. //
  1048. // Complete the original IRP.
  1049. //
  1050. CompleteSocketIrp (irp);
  1051. //
  1052. // Make sure IO subsystem does not touch the IRP we freed
  1053. //
  1054. return STATUS_MORE_PROCESSING_REQUIRED;
  1055. }
  1056. NTSTATUS
  1057. SocketPnPTargetQuery (
  1058. IN PFILE_OBJECT SocketFile,
  1059. IN PIRP Irp
  1060. )
  1061. /*++
  1062. Routine Description:
  1063. Passes target device relation query to the underlying
  1064. socket if any.
  1065. Arguments:
  1066. SocketFile - socket file object
  1067. Irp - query target device relation request
  1068. Return Value:
  1069. STATUS_PENDING - operation initiated OK
  1070. --*/
  1071. {
  1072. NTSTATUS status;
  1073. PIO_STACK_LOCATION irpSp;
  1074. PIFSL_SOCKET_CTX SocketCtx;
  1075. PFILE_OBJECT ProcessFile;
  1076. PAGED_CODE ();
  1077. irpSp = IoGetCurrentIrpStackLocation (Irp);
  1078. Irp->IoStatus.Information = 0;
  1079. SocketCtx = SocketFile->FsContext;
  1080. ProcessFile = GetSocketProcessReference (SocketCtx);
  1081. // We are going to pend this request
  1082. IoMarkIrpPending (Irp);
  1083. // Prepare IRP for insertion into the queue
  1084. irpSp->Parameters.DeviceIoControl.IfslAddressBuffer = NULL;
  1085. irpSp->Parameters.DeviceIoControl.IfslAddressLength = 0;
  1086. Irp->Tail.Overlay.IfslRequestId = UlongToPtr(GenerateUniqueId (SocketCtx->IrpId));
  1087. Irp->Tail.Overlay.IfslAddressLenPtr = NULL;
  1088. Irp->Tail.Overlay.IfslRequestFlags = (PVOID)0;
  1089. Irp->Tail.Overlay.IfslRequestQueue = NULL;
  1090. if (!QueueRequest (ProcessFile->FsContext, Irp)) {
  1091. Irp->IoStatus.Status = STATUS_CANCELLED;
  1092. Irp->IoStatus.Information = 0;
  1093. WsProcessPrint ((PIFSL_PROCESS_CTX)ProcessFile->FsContext, DBG_AFDIOCTL,
  1094. ("WS2IFSL-%04lx DoAfdIoctl: Cancelling Irp %p on socket %p.\n",
  1095. ((PIFSL_PROCESS_CTX)ProcessFile->FsContext)->UniqueId,
  1096. Irp, SocketFile));
  1097. CompleteSocketIrp (Irp);
  1098. }
  1099. status = STATUS_PENDING;
  1100. ObDereferenceObject (ProcessFile);
  1101. return status;
  1102. }
  1103. BOOLEAN
  1104. InsertProcessedRequest (
  1105. PIFSL_SOCKET_CTX SocketCtx,
  1106. PIRP Irp
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Inserts request that was processed to be passed to user mode
  1111. DLL into socket list. Checks if request is cancelled
  1112. Arguments:
  1113. SocketCtx - contex of the socket into which insert the request
  1114. Irp - request to insert
  1115. Return Value:
  1116. TRUE - request was inserted
  1117. FALSE - request is being cancelled
  1118. --*/
  1119. {
  1120. KIRQL oldIRQL;
  1121. IoSetCancelRoutine (Irp, ProcessedCancelRoutine);
  1122. KeAcquireSpinLock (&SocketCtx->SpinLock, &oldIRQL);
  1123. if (!Irp->Cancel) {
  1124. InsertTailList (&SocketCtx->ProcessedIrps,
  1125. &Irp->Tail.Overlay.ListEntry);
  1126. Irp->Tail.Overlay.IfslRequestQueue = &SocketCtx->ProcessedIrps;
  1127. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1128. return TRUE;
  1129. }
  1130. else {
  1131. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1132. return FALSE;
  1133. }
  1134. }
  1135. VOID
  1136. ProcessedCancelRoutine (
  1137. IN PDEVICE_OBJECT DeviceObject,
  1138. IN PIRP Irp
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. Driver cancel routine for socket request waiting in the list
  1143. (being processed by the user mode DLL).
  1144. Arguments:
  1145. DeviceObject - WS2IFSL device object
  1146. Irp - Irp to be cancelled
  1147. Return Value:
  1148. None
  1149. --*/
  1150. {
  1151. PIO_STACK_LOCATION irpSp;
  1152. PIFSL_SOCKET_CTX SocketCtx;
  1153. irpSp = IoGetCurrentIrpStackLocation (Irp);
  1154. SocketCtx = irpSp->FileObject->FsContext;
  1155. WsProcessPrint ((PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext,
  1156. DBG_SOCKET,
  1157. ("WS2IFSL-%04lx ProcessedCancel: Socket %p, Irp %p\n",
  1158. GET_SOCKET_PROCESSID(SocketCtx),
  1159. irpSp->FileObject, Irp));
  1160. KeAcquireSpinLockAtDpcLevel (&SocketCtx->SpinLock);
  1161. if (Irp->Tail.Overlay.IfslRequestQueue!=NULL) {
  1162. ASSERT (Irp->Tail.Overlay.IfslRequestQueue==&SocketCtx->ProcessedIrps);
  1163. RemoveEntryList (&Irp->Tail.Overlay.ListEntry);
  1164. Irp->Tail.Overlay.IfslRequestQueue = NULL;
  1165. KeReleaseSpinLockFromDpcLevel (&SocketCtx->SpinLock);
  1166. IoReleaseCancelSpinLock (Irp->CancelIrql);
  1167. CancelSocketIo (irpSp->FileObject);
  1168. Irp->IoStatus.Information = 0;
  1169. Irp->IoStatus.Status = STATUS_CANCELLED;
  1170. CompleteSocketIrp (Irp);
  1171. }
  1172. else {
  1173. KeReleaseSpinLockFromDpcLevel (&SocketCtx->SpinLock);
  1174. IoReleaseCancelSpinLock (Irp->CancelIrql);
  1175. //
  1176. // Don't touch IRP after this as we do not own it anymore
  1177. //
  1178. }
  1179. }
  1180. VOID
  1181. CleanupProcessedRequests (
  1182. IN PIFSL_SOCKET_CTX SocketCtx,
  1183. OUT PLIST_ENTRY IrpList
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. Cleans up all requests on the socket which are being
  1188. processed by the user mode DLL
  1189. Arguments:
  1190. SocketCtx - context of the socket
  1191. IrpList - list to insert cleaned up request (to be completed
  1192. by the caller)
  1193. Return Value:
  1194. None
  1195. --*/
  1196. {
  1197. PIRP irp;
  1198. PLIST_ENTRY entry;
  1199. KIRQL oldIRQL;
  1200. KeAcquireSpinLock (&SocketCtx->SpinLock, &oldIRQL);
  1201. while (!IsListEmpty(&SocketCtx->ProcessedIrps)) {
  1202. entry = RemoveHeadList (&SocketCtx->ProcessedIrps);
  1203. irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
  1204. ASSERT (irp->Tail.Overlay.IfslRequestQueue==&SocketCtx->ProcessedIrps);
  1205. irp->Tail.Overlay.IfslRequestQueue = NULL;
  1206. InsertTailList (IrpList, &irp->Tail.Overlay.ListEntry);
  1207. }
  1208. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1209. }
  1210. VOID
  1211. CompleteSocketIrp (
  1212. PIRP Irp
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. Completes IRP and properly synchronizes with cancel routine
  1217. if necessary (it has already been called).
  1218. Arguments:
  1219. Irp - irp to complete
  1220. Return Value:
  1221. None
  1222. --*/
  1223. {
  1224. //
  1225. // Reset cancel routine (it wont complete the IRP as it
  1226. // won't be able to find it)
  1227. //
  1228. if (IoSetCancelRoutine (Irp, NULL)==NULL) {
  1229. KIRQL oldIRQL;
  1230. //
  1231. // Cancel routine has been called.
  1232. // Synchronize with cancel routine (it won't touch the
  1233. // IRP after it releases cancel spinlock)
  1234. IoAcquireCancelSpinLock (&oldIRQL);
  1235. IoReleaseCancelSpinLock (oldIRQL);
  1236. }
  1237. if (Irp->MdlAddress!=NULL) {
  1238. ASSERT ((Irp->MdlAddress->MdlFlags & MDL_PAGES_LOCKED) == 0);
  1239. IoFreeMdl (Irp->MdlAddress);
  1240. Irp->MdlAddress = NULL;
  1241. }
  1242. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  1243. }
  1244. PIRP
  1245. GetProcessedRequest (
  1246. PIFSL_SOCKET_CTX SocketCtx,
  1247. ULONG UniqueId
  1248. )
  1249. /*++
  1250. Routine Description:
  1251. Finds and returns matching IRP from the processed IRP list
  1252. Arguments:
  1253. SocketCtx - socket context to search for the IRP in
  1254. UniqueId - id assigned to the request to distinguish identify
  1255. it case it was cancelled and IRP was reused
  1256. Return Value:
  1257. IRP
  1258. NULL - irp was not found
  1259. --*/
  1260. {
  1261. PIRP irp;
  1262. PLIST_ENTRY entry;
  1263. KIRQL oldIRQL;
  1264. //
  1265. // We do not usually have many request sumulteneously pending
  1266. // on a socket, so the linear search should suffice.
  1267. //
  1268. KeAcquireSpinLock (&SocketCtx->SpinLock, &oldIRQL);
  1269. entry = SocketCtx->ProcessedIrps.Flink;
  1270. while (entry!=&SocketCtx->ProcessedIrps) {
  1271. irp = CONTAINING_RECORD (entry, IRP, Tail.Overlay.ListEntry);
  1272. entry = entry->Flink;
  1273. if (irp->Tail.Overlay.IfslRequestId==UlongToPtr(UniqueId)) {
  1274. ASSERT (irp->Tail.Overlay.IfslRequestQueue==&SocketCtx->ProcessedIrps);
  1275. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  1276. irp->Tail.Overlay.IfslRequestQueue = NULL;
  1277. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1278. return irp;
  1279. }
  1280. }
  1281. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1282. return NULL;
  1283. }
  1284. VOID
  1285. CancelSocketIo (
  1286. PFILE_OBJECT SocketFile
  1287. )
  1288. /*++
  1289. Routine Description:
  1290. Queue a request to user mode DLL to cancel all io on the socket
  1291. Arguments:
  1292. SocketCtx - socket context on which IO is to be cancelled
  1293. Return Value:
  1294. None
  1295. --*/
  1296. {
  1297. PIFSL_SOCKET_CTX SocketCtx = SocketFile->FsContext;
  1298. PIFSL_PROCESS_CTX ProcessCtx = SocketCtx->ProcessRef->FsContext;
  1299. PIFSL_CANCEL_CTX cancelCtx;
  1300. try {
  1301. cancelCtx = (PIFSL_CANCEL_CTX) ExAllocatePoolWithQuotaTag (
  1302. NonPagedPool,
  1303. sizeof (IFSL_CANCEL_CTX),
  1304. CANCEL_CTX_TAG);
  1305. }
  1306. except (EXCEPTION_EXECUTE_HANDLER) {
  1307. cancelCtx = NULL;
  1308. }
  1309. if (cancelCtx!=NULL) {
  1310. //
  1311. // Make sure socket does not go away while this request exists
  1312. //
  1313. ObReferenceObject (SocketFile);
  1314. cancelCtx->SocketFile = SocketFile;
  1315. cancelCtx->UniqueId = GenerateUniqueId (ProcessCtx->CancelId);
  1316. //
  1317. // We do not want to queue another cancel request if we have
  1318. // one pending or being executed
  1319. //
  1320. if (InterlockedCompareExchangePointer ((PVOID *)&SocketCtx->CancelCtx,
  1321. cancelCtx,
  1322. NULL)==NULL) {
  1323. WsProcessPrint (
  1324. ProcessCtx,
  1325. DBG_CANCEL,
  1326. ("WS2IFSL-%04lx CancelSocketIo: Context %p, socket %p\n",
  1327. ProcessCtx->UniqueId,
  1328. cancelCtx, SocketFile));
  1329. QueueCancel (ProcessCtx, cancelCtx);
  1330. return;
  1331. }
  1332. WsProcessPrint (
  1333. ProcessCtx,
  1334. DBG_CANCEL,
  1335. ("WS2IFSL-%04lx CancelSocketIo: Another cancel active"
  1336. " context %p, socket %p\n",
  1337. ProcessCtx->UniqueId,
  1338. SocketCtx->CancelCtx, SocketFile));
  1339. ObDereferenceObject (SocketFile);
  1340. ExFreePool (cancelCtx);
  1341. }
  1342. else {
  1343. WsPrint (DBG_SOCKET|DBG_CANCEL|DBG_FAILURES,
  1344. ("WS2IFSL-%04lx CancelSocketIo: Could not allocate cancel"
  1345. " context for socket %p\n",
  1346. PsGetCurrentProcessId(),
  1347. SocketFile));
  1348. }
  1349. }
  1350. VOID
  1351. FreeSocketCancel (
  1352. PIFSL_CANCEL_CTX CancelCtx
  1353. )
  1354. /*++
  1355. Routine Description:
  1356. Frees resources associated with cancel request
  1357. Arguments:
  1358. CancelCtx - cancel request context
  1359. Return Value:
  1360. None
  1361. --*/
  1362. {
  1363. PFILE_OBJECT SocketFile = CancelCtx->SocketFile;
  1364. PIFSL_SOCKET_CTX SocketCtx = SocketFile->FsContext;
  1365. ASSERT (IoGetRelatedDeviceObject (SocketFile)==DeviceObject);
  1366. ASSERT (SocketCtx->EANameTag==SOCKET_FILE_EANAME_TAG);
  1367. ASSERT (CancelCtx->ListEntry.Flink==NULL);
  1368. //
  1369. // We are going to dereference the file object whether
  1370. // free the structure or not
  1371. //
  1372. CancelCtx->SocketFile = NULL;
  1373. ObDereferenceObject (SocketFile);
  1374. //
  1375. // During socket closure, the cleanup routine may be in
  1376. // process of freeing this cancel context and will set
  1377. // the pointer to it to NULL to indicate the fact
  1378. //
  1379. if (InterlockedCompareExchangePointer ((PVOID *)&SocketCtx->CancelCtx,
  1380. NULL,
  1381. CancelCtx)) {
  1382. WsProcessPrint (
  1383. (PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext,
  1384. DBG_CANCEL,
  1385. ("WS2IFSL-%04lx FreeSocketCancel: Freeing cancel"
  1386. " context %p, socket %p\n",
  1387. GET_SOCKET_PROCESSID(SocketCtx),
  1388. CancelCtx, SocketFile));
  1389. ExFreePool (CancelCtx);
  1390. }
  1391. else {
  1392. //
  1393. // The close routine will take care of freeing the request
  1394. //
  1395. WsProcessPrint (
  1396. (PIFSL_PROCESS_CTX)SocketCtx->ProcessRef->FsContext,
  1397. DBG_CANCEL,
  1398. ("WS2IFSL-%04lx FreeSocketCancel: Cleanup owns cancel"
  1399. " context %p, socket %p\n",
  1400. GET_SOCKET_PROCESSID(SocketCtx),
  1401. CancelCtx, SocketFile));
  1402. }
  1403. }
  1404. PFILE_OBJECT
  1405. GetSocketProcessReference (
  1406. IN PIFSL_SOCKET_CTX SocketCtx
  1407. )
  1408. /*++
  1409. Routine Description:
  1410. Reads and references process file currently associated with
  1411. the socket under the lock to protect in case socket is moved
  1412. to a different process
  1413. Arguments:
  1414. SocketCtx - socket context to read process file from
  1415. Return Value:
  1416. Referenced pointer to process file object currently associated
  1417. with the socket.
  1418. --*/
  1419. {
  1420. KIRQL oldIRQL;
  1421. PFILE_OBJECT ProcessFile;
  1422. KeAcquireSpinLock (&SocketCtx->SpinLock, &oldIRQL);
  1423. ObReferenceObject (SocketCtx->ProcessRef);
  1424. ProcessFile = SocketCtx->ProcessRef;
  1425. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1426. return ProcessFile;
  1427. }
  1428. PFILE_OBJECT
  1429. SetSocketProcessReference (
  1430. IN PIFSL_SOCKET_CTX SocketCtx,
  1431. IN PFILE_OBJECT NewProcessFile,
  1432. IN PVOID NewDllContext
  1433. )
  1434. /*++
  1435. Routine Description:
  1436. Sets new process context for the socket object under the protection
  1437. of a lock.
  1438. Arguments:
  1439. SocketCtx - socket context to set
  1440. NewProcessFile - process file reference
  1441. NewDllContext - context to be associated with the socket
  1442. in the process
  1443. Return Value:
  1444. Previous process file reference
  1445. --*/
  1446. {
  1447. KIRQL oldIRQL;
  1448. PFILE_OBJECT ProcessFile;
  1449. KeAcquireSpinLock (&SocketCtx->SpinLock, &oldIRQL);
  1450. ProcessFile = SocketCtx->ProcessRef;
  1451. SocketCtx->ProcessRef = NewProcessFile;
  1452. SocketCtx->DllContext = NewDllContext;
  1453. KeReleaseSpinLock (&SocketCtx->SpinLock, oldIRQL);
  1454. return ProcessFile;
  1455. }