2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
5 * PURPOSE: File object dispatch functions
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09-2000 Created
14 PIO_STACK_LOCATION IrpSp
)
16 * FUNCTION: Binds to an address
18 * Irp = Pointer to I/O request packet
19 * IrpSp = Pointer to current stack location of Irp
25 UINT InputBufferLength
;
26 UINT OutputBufferLength
;
27 PFILE_REQUEST_BIND Request
;
28 PFILE_REPLY_BIND Reply
;
31 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
32 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
34 /* Validate parameters */
35 if ((InputBufferLength
>= sizeof(FILE_REQUEST_BIND
)) &&
36 (OutputBufferLength
>= sizeof(FILE_REPLY_BIND
))) {
37 FCB
= IrpSp
->FileObject
->FsContext
;
39 Request
= (PFILE_REQUEST_BIND
)Irp
->AssociatedIrp
.SystemBuffer
;
40 Reply
= (PFILE_REPLY_BIND
)Irp
->AssociatedIrp
.SystemBuffer
;
42 switch (Request
->Name
.sa_family
) {
44 Status
= TdiOpenAddressFileIPv4(&FCB
->TdiDeviceName
,
46 &FCB
->TdiAddressObjectHandle
,
47 &FCB
->TdiAddressObject
);
50 AFD_DbgPrint(MIN_TRACE
, ("Bad address family (%d).\n", Request
->Name
.sa_family
));
51 Status
= STATUS_INVALID_PARAMETER
;
54 if (NT_SUCCESS(Status
)) {
55 AfdRegisterEventHandlers(FCB
);
56 FCB
->State
= SOCKET_STATE_BOUND
;
59 Status
= STATUS_INVALID_PARAMETER
;
61 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
67 NTSTATUS
AfdDispListen(
69 PIO_STACK_LOCATION IrpSp
)
71 * FUNCTION: Starts listening for connections
73 * Irp = Pointer to I/O request packet
74 * IrpSp = Pointer to current stack location of Irp
80 UINT InputBufferLength
;
81 UINT OutputBufferLength
;
82 PFILE_REQUEST_LISTEN Request
;
83 PFILE_REPLY_LISTEN Reply
;
86 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
87 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
89 /* Validate parameters */
90 if ((InputBufferLength
>= sizeof(FILE_REQUEST_LISTEN
)) &&
91 (OutputBufferLength
>= sizeof(FILE_REPLY_LISTEN
))) {
92 FCB
= IrpSp
->FileObject
->FsContext
;
94 Request
= (PFILE_REQUEST_LISTEN
)Irp
->AssociatedIrp
.SystemBuffer
;
95 Reply
= (PFILE_REPLY_LISTEN
)Irp
->AssociatedIrp
.SystemBuffer
;
97 Status
= STATUS_INVALID_PARAMETER
;
99 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
105 NTSTATUS
AfdDispSendTo(
107 PIO_STACK_LOCATION IrpSp
)
109 * FUNCTION: Sends data to an address
111 * Irp = Pointer to I/O request packet
112 * IrpSp = Pointer to current stack location of Irp
114 * Status of operation
118 UINT InputBufferLength
;
119 UINT OutputBufferLength
;
120 PFILE_REQUEST_SENDTO Request
;
121 PFILE_REPLY_SENDTO Reply
;
123 PVOID SystemVirtualAddress
;
124 PVOID DataBufferAddress
;
129 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
130 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
132 /* Validate parameters */
133 if ((InputBufferLength
>= sizeof(FILE_REQUEST_SENDTO
)) &&
134 (OutputBufferLength
>= sizeof(FILE_REPLY_SENDTO
))) {
136 AFD_DbgPrint(MAX_TRACE
, ("FileObject at (0x%X).\n", IrpSp
->FileObject
));
137 AFD_DbgPrint(MAX_TRACE
, ("FCB at (0x%X).\n", IrpSp
->FileObject
->FsContext
));
138 AFD_DbgPrint(MAX_TRACE
, ("CCB at (0x%X).\n", IrpSp
->FileObject
->FsContext2
));
140 FCB
= IrpSp
->FileObject
->FsContext
;
141 Request
= (PFILE_REQUEST_SENDTO
)Irp
->AssociatedIrp
.SystemBuffer
;
142 Reply
= (PFILE_REPLY_SENDTO
)Irp
->AssociatedIrp
.SystemBuffer
;
143 BufferSize
= WSABufferSize(Request
->Buffers
, Request
->BufferCount
);
146 /* FIXME: Should we handle special cases here? */
147 if ((FCB
->SocketType
== SOCK_RAW
) && (FCB
->AddressFamily
== AF_INET
)) {
148 BufferSize
+= sizeof(IPv4_HEADER
);
152 if (BufferSize
!= 0) {
153 AFD_DbgPrint(MAX_TRACE
, ("Allocating %d bytes for send buffer.\n", BufferSize
));
154 SystemVirtualAddress
= ExAllocatePool(NonPagedPool
, BufferSize
);
155 if (!SystemVirtualAddress
) {
156 return STATUS_INSUFFICIENT_RESOURCES
;
159 /* FIXME: Should we handle special cases here? */
160 if ((FCB
->SocketType
== SOCK_RAW
) && (FCB
->AddressFamily
== AF_INET
)) {
161 DataBufferAddress
= SystemVirtualAddress
+ sizeof(IPv4_HEADER
);
163 /* FIXME: Should TCP/IP driver assign source address for raw sockets? */
164 ((PSOCKADDR_IN
)&FCB
->SocketName
)->sin_addr
.S_un
.S_addr
= 0x0100007F;
167 (PIPv4_HEADER
)SystemVirtualAddress
,
173 DataBufferAddress
= SystemVirtualAddress
;
176 Status
= MergeWSABuffers(
178 Request
->BufferCount
,
182 if (!NT_SUCCESS(Status
)) {
183 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
187 SystemVirtualAddress
= NULL
;
192 SystemVirtualAddress
, /* Virtual address of buffer */
193 BufferSize
, /* Length of buffer */
194 FALSE
, /* Not secondary */
195 FALSE
, /* Don't charge quota */
196 NULL
); /* Don't use IRP */
198 ExFreePool(SystemVirtualAddress
);
199 return STATUS_INSUFFICIENT_RESOURCES
;
202 MmBuildMdlForNonPagedPool(Mdl
);
204 AFD_DbgPrint(MAX_TRACE
, ("System virtual address is (0x%X).\n", SystemVirtualAddress
));
205 AFD_DbgPrint(MAX_TRACE
, ("MDL for data buffer is at (0x%X).\n", Mdl
));
207 AFD_DbgPrint(MAX_TRACE
, ("AFD.SYS: NDIS data buffer is at (0x%X).\n", Mdl
));
208 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer MdlFlags is (0x%X).\n", Mdl
->MdlFlags
));
209 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer Next is at (0x%X).\n", Mdl
->Next
));
210 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer Size is (0x%X).\n", Mdl
->Size
));
211 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer MappedSystemVa is (0x%X).\n", Mdl
->MappedSystemVa
));
212 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer StartVa is (0x%X).\n", Mdl
->StartVa
));
213 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer ByteCount is (0x%X).\n", Mdl
->ByteCount
));
214 AFD_DbgPrint(MAX_TRACE
, ("NDIS data buffer ByteOffset is (0x%X).\n", Mdl
->ByteOffset
));
220 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
222 } except(EXCEPTION_EXECUTE_HANDLER
) {
223 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
225 if (BufferSize
!= 0) {
226 ExFreePool(SystemVirtualAddress
);
228 return STATUS_UNSUCCESSFUL
;
233 Status
= TdiSendDatagram(FCB
->TdiAddressObject
,
238 /* FIXME: Assumes synchronous operation */
245 if (BufferSize
!= 0) {
246 ExFreePool(SystemVirtualAddress
);
249 Reply
->NumberOfBytesSent
= BufferSize
;
250 Reply
->Status
= NO_ERROR
;
252 Status
= STATUS_INVALID_PARAMETER
;
254 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
260 NTSTATUS
AfdDispRecvFrom(
262 PIO_STACK_LOCATION IrpSp
)
264 * FUNCTION: Receives data from an address
266 * Irp = Pointer to I/O request packet
267 * IrpSp = Pointer to current stack location of Irp
269 * Status of operation
273 UINT InputBufferLength
;
274 UINT OutputBufferLength
;
275 PFILE_REQUEST_RECVFROM Request
;
276 PFILE_REPLY_RECVFROM Reply
;
277 PAFD_READ_REQUEST ReadRequest
;
278 DWORD NumberOfBytesRecvd
;
282 AFD_DbgPrint(MAX_TRACE
, ("Called.\n"));
284 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
285 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
287 /* Validate parameters */
288 if ((InputBufferLength
>= sizeof(FILE_REQUEST_RECVFROM
)) &&
289 (OutputBufferLength
>= sizeof(FILE_REPLY_RECVFROM
))) {
290 FCB
= IrpSp
->FileObject
->FsContext
;
292 Request
= (PFILE_REQUEST_RECVFROM
)Irp
->AssociatedIrp
.SystemBuffer
;
293 Reply
= (PFILE_REPLY_RECVFROM
)Irp
->AssociatedIrp
.SystemBuffer
;
295 KeAcquireSpinLock(&FCB
->ReceiveQueueLock
, &OldIrql
);
296 if (IsListEmpty(&FCB
->ReceiveQueue
)) {
297 KeReleaseSpinLock(&FCB
->ReceiveQueueLock
, OldIrql
);
299 /* Queue a read request and return STATUS_PENDING */
301 AFD_DbgPrint(MAX_TRACE
, ("Queueing read request.\n"));
303 /*ReadRequest = (PAFD_READ_REQUEST)ExAllocateFromNPagedLookasideList(
304 &ReadRequestLookasideList);*/
305 ReadRequest
= (PAFD_READ_REQUEST
)ExAllocatePool(
307 sizeof(AFD_READ_REQUEST
));
309 ReadRequest
->Irp
= Irp
;
310 ReadRequest
->RecvFromRequest
= Request
;
311 ReadRequest
->RecvFromReply
= Reply
;
313 ExInterlockedInsertTailList(
314 &FCB
->ReadRequestQueue
,
315 &ReadRequest
->ListEntry
,
316 &FCB
->ReadRequestQueueLock
);
317 Status
= STATUS_PENDING
;
319 Status
= STATUS_INSUFFICIENT_RESOURCES
;
322 AFD_DbgPrint(MAX_TRACE
, ("Satisfying read request.\n"));
324 /* Satisfy the request at once */
325 Status
= FillWSABuffers(
328 Request
->BufferCount
,
329 &NumberOfBytesRecvd
);
330 KeReleaseSpinLock(&FCB
->ReceiveQueueLock
, OldIrql
);
331 Reply
->Status
= NO_ERROR
;
332 Reply
->NumberOfBytesRecvd
= NumberOfBytesRecvd
;
333 AFD_DbgPrint(MAX_TRACE
, ("NumberOfBytesRecvd (0x%X).\n",
334 NumberOfBytesRecvd
));
337 Status
= STATUS_INVALID_PARAMETER
;
340 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
353 DWORD
AfdDispSelectEx(
355 SelectOperation Operation
)
363 AFD_DbgPrint(MAX_TRACE
, ("FDSet (0x%X) Operation (0x%X).\n",
366 AFD_DbgPrint(MAX_TRACE
, ("FDSet->fd_count (0x%X).\n", FDSet
->fd_count
));
369 for (i
= 0; i
< FDSet
->fd_count
; i
++) {
370 Status
= ObReferenceObjectByHandle(
371 (HANDLE
)FDSet
->fd_array
[i
],
377 if (NT_SUCCESS(Status
)) {
381 KeAcquireSpinLock(&Current
->ReceiveQueueLock
, &OldIrql
);
382 if (!IsListEmpty(&Current
->ReceiveQueue
)) {
383 AFD_DbgPrint(MAX_TRACE
, ("Socket is readable.\n"));
386 KeReleaseSpinLock(&Current
->ReceiveQueueLock
, OldIrql
);
389 /* FIXME: How can we check for writability? */
393 /* FIXME: What is this? */
398 ObDereferenceObject(Current
);
405 NTSTATUS
AfdDispSelect(
407 PIO_STACK_LOCATION IrpSp
)
409 * FUNCTION: Checks if sockets have data in the receive buffers
411 * Irp = Pointer to I/O request packet
412 * IrpSp = Pointer to current stack location of Irp
414 * Status of operation
418 UINT InputBufferLength
;
419 UINT OutputBufferLength
;
420 PFILE_REQUEST_SELECT Request
;
421 PFILE_REPLY_SELECT Reply
;
425 InputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
426 OutputBufferLength
= IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
;
428 /* Validate parameters */
429 if ((InputBufferLength
>= sizeof(FILE_REQUEST_SELECT
)) &&
430 (OutputBufferLength
>= sizeof(FILE_REPLY_SELECT
))) {
431 FCB
= IrpSp
->FileObject
->FsContext
;
433 Request
= (PFILE_REQUEST_SELECT
)Irp
->AssociatedIrp
.SystemBuffer
;
434 Reply
= (PFILE_REPLY_SELECT
)Irp
->AssociatedIrp
.SystemBuffer
;
436 AFD_DbgPrint(MAX_TRACE
, ("R (0x%X) W (0x%X).\n",
437 Request
->ReadFDSet
, Request
->WriteFDSet
));
441 if (Request
->ReadFDSet
) {
442 AFD_DbgPrint(MAX_TRACE
, ("Read.\n"));
443 SocketCount
+= AfdDispSelectEx(Request
->ReadFDSet
, soRead
);
445 if (Request
->WriteFDSet
) {
446 AFD_DbgPrint(MAX_TRACE
, ("Write.\n"));
447 SocketCount
+= AfdDispSelectEx(Request
->WriteFDSet
, soWrite
);
449 if (Request
->ExceptFDSet
) {
450 SocketCount
+= AfdDispSelectEx(Request
->ExceptFDSet
, soExcept
);
453 AFD_DbgPrint(MAX_TRACE
, ("Sockets selected (0x%X).\n", SocketCount
));
455 Reply
->Status
= NO_ERROR
;
456 Reply
->SocketCount
= SocketCount
;
457 Status
= STATUS_SUCCESS
;
459 Status
= STATUS_INVALID_PARAMETER
;
461 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));