Added afd/tdiconn.c with corrections by filip navara
[reactos.git] / reactos / drivers / net / afd / afd / dispatch.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
4 * FILE: afd/dispatch.c
5 * PURPOSE: File object dispatch functions
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <afd.h>
11
12 NTSTATUS AfdpDispRecv(
13 PIRP Irp,
14 PAFDFCB FCB,
15 PFILE_REQUEST_RECVFROM Request,
16 PFILE_REPLY_RECVFROM Reply)
17 /*
18 * FUNCTION: Receives data
19 * ARGUMENTS:
20 * Irp = Pointer to I/O request packet
21 * FCB = Pointer to file control block
22 * Request = Address of request buffer
23 * Reply = Address of reply buffer (same as request buffer)
24 * RETURNS:
25 * Status of operation
26 */
27 {
28 PAFD_READ_REQUEST ReadRequest;
29 NTSTATUS Status;
30 KIRQL OldIrql;
31 ULONG Count;
32
33 KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql);
34 if (IsListEmpty(&FCB->ReceiveQueue)) {
35 KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql);
36
37 /* Queue a read request and return STATUS_PENDING */
38
39 AFD_DbgPrint(MAX_TRACE, ("Queueing read request.\n"));
40
41 /*ReadRequest = (PAFD_READ_REQUEST)ExAllocateFromNPagedLookasideList(
42 &ReadRequestLookasideList);*/
43 ReadRequest = (PAFD_READ_REQUEST)ExAllocatePool(
44 NonPagedPool,
45 sizeof(AFD_READ_REQUEST));
46 if (ReadRequest) {
47 ReadRequest->Irp = Irp;
48 ReadRequest->RecvFromRequest = Request;
49 ReadRequest->RecvFromReply = Reply;
50
51 ExInterlockedInsertTailList(
52 &FCB->ReadRequestQueue,
53 &ReadRequest->ListEntry,
54 &FCB->ReadRequestQueueLock);
55 Status = STATUS_PENDING;
56 } else {
57 Status = STATUS_INSUFFICIENT_RESOURCES;
58 }
59 } else {
60 AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n"));
61
62 /* Satisfy the request at once */
63 Status = FillWSABuffers(
64 FCB,
65 Request->Buffers,
66 Request->BufferCount,
67 &Count);
68 KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql);
69
70 Reply->NumberOfBytesRecvd = Count;
71 Reply->Status = NO_ERROR;
72
73 AFD_DbgPrint(MAX_TRACE, ("Bytes received (0x%X).\n", Count));
74 }
75
76 return Status;
77 }
78
79
80 NTSTATUS AfdDispBind(
81 PIRP Irp,
82 PIO_STACK_LOCATION IrpSp)
83 /*
84 * FUNCTION: Binds to an address
85 * ARGUMENTS:
86 * Irp = Pointer to I/O request packet
87 * IrpSp = Pointer to current stack location of Irp
88 * RETURNS:
89 * Status of operation
90 */
91 {
92 NTSTATUS Status;
93 UINT InputBufferLength;
94 UINT OutputBufferLength;
95 PFILE_REQUEST_BIND Request;
96 PFILE_REPLY_BIND Reply;
97 PAFDFCB FCB;
98
99 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
100 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
101
102 /* Validate parameters */
103 if ((InputBufferLength >= sizeof(FILE_REQUEST_BIND)) &&
104 (OutputBufferLength >= sizeof(FILE_REPLY_BIND))) {
105 FCB = IrpSp->FileObject->FsContext;
106
107 Request = (PFILE_REQUEST_BIND)Irp->AssociatedIrp.SystemBuffer;
108 Reply = (PFILE_REPLY_BIND)Irp->AssociatedIrp.SystemBuffer;
109
110 Status = TdiOpenAddressFile(
111 &FCB->TdiDeviceName,
112 &Request->Name,
113 &FCB->TdiAddressObjectHandle,
114 &FCB->TdiAddressObject);
115
116 if (NT_SUCCESS(Status)) {
117 AfdRegisterEventHandlers(FCB);
118 FCB->State = SOCKET_STATE_BOUND;
119 Reply->Status = NO_ERROR;
120 } else {
121 //FIXME: WSAEADDRNOTAVAIL
122 Reply->Status = WSAEINVAL;
123 }
124 } else
125 Status = STATUS_INVALID_PARAMETER;
126
127 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
128
129 return Status;
130 }
131
132
133 NTSTATUS
134 STDCALL
135 AfdDispCompleteListen(
136 PDEVICE_OBJECT DeviceObject,
137 PIRP Irp,
138 PVOID Context)
139 {
140 PAFD_LISTEN_REQUEST ListenRequest = (PAFD_LISTEN_REQUEST) Context;
141
142 AFD_DbgPrint(MAX_TRACE, ("Called. ListenRequest (0x%X).\n", ListenRequest));
143
144 AFD_DbgPrint(MAX_TRACE, ("Fcb (0x%X).\n", ListenRequest->Fcb));
145
146 return STATUS_SUCCESS;
147 }
148
149
150 NTSTATUS AfdDispListen(
151 PIRP Irp,
152 PIO_STACK_LOCATION IrpSp)
153 /*
154 * FUNCTION: Starts listening for connections
155 * ARGUMENTS:
156 * Irp = Pointer to I/O request packet
157 * IrpSp = Pointer to current stack location of Irp
158 * RETURNS:
159 * Status of operation
160 */
161 {
162 NTSTATUS Status;
163 UINT InputBufferLength;
164 UINT OutputBufferLength;
165 PFILE_REQUEST_LISTEN Request;
166 PFILE_REPLY_LISTEN Reply;
167 PAFDFCB FCB;
168 PAFD_LISTEN_REQUEST ListenRequest;
169
170 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
171 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
172
173 /* Validate parameters */
174 Status = STATUS_INVALID_PARAMETER;
175 if ((InputBufferLength >= sizeof(FILE_REQUEST_LISTEN)) &&
176 (OutputBufferLength >= sizeof(FILE_REPLY_LISTEN))) {
177 FCB = IrpSp->FileObject->FsContext;
178
179 Request = (PFILE_REQUEST_LISTEN)Irp->AssociatedIrp.SystemBuffer;
180 Reply = (PFILE_REPLY_LISTEN)Irp->AssociatedIrp.SystemBuffer;
181
182 if (FCB->State == SOCKET_STATE_BOUND)
183 {
184 /* We have a bound socket so go ahead and create a connection endpoint
185 and associate it with the address file object */
186
187 Status = TdiOpenConnectionEndpointFile(
188 &FCB->TdiDeviceName,
189 &FCB->TdiConnectionObjectHandle,
190 &FCB->TdiConnectionObject);
191
192 if (NT_SUCCESS(Status))
193 {
194 Status = TdiAssociateAddressFile(
195 FCB->TdiAddressObjectHandle,
196 FCB->TdiConnectionObject);
197
198 if (NT_SUCCESS(Status))
199 {
200 ListenRequest = ExAllocateFromNPagedLookasideList(&ListenRequestLookasideList);
201 if (ListenRequest != NULL)
202 {
203 ListenRequest->Fcb = FCB;
204 /* FIXME: Protect ListenRequestQueue */
205 InsertTailList(&FCB->ListenRequestQueue, &ListenRequest->ListEntry);
206
207 Status = TdiListen(FCB->TdiConnectionObject, AfdDispCompleteListen, ListenRequest);
208 if ((Status == STATUS_PENDING) || NT_SUCCESS(Status))
209 {
210 if (Status != STATUS_PENDING)
211 {
212 AFD_DbgPrint(MIN_TRACE, ("FIXME: Status (0x%X).\n", Status));
213 }
214 Status = STATUS_SUCCESS;
215 }
216 else
217 {
218 /* FIXME: Cleanup ListenRequest */
219 /* FIXME: Cleanup from TdiOpenConnectionEndpointFile */
220 }
221 }
222 else
223 {
224 /* FIXME: Cleanup from TdiOpenConnectionEndpointFile */
225 Status = STATUS_NO_MEMORY;
226 }
227 }
228 else
229 {
230 /* FIXME: Cleanup from TdiOpenConnectionEndpointFile */
231 }
232 }
233
234 if (NT_SUCCESS(Status)) {
235 Reply->Status = NO_ERROR;
236 } else {
237 Reply->Status = WSAEINVAL;
238 }
239 }
240 else if (FCB->State == SOCKET_STATE_CONNECTED)
241 {
242 Reply->Status = WSAEISCONN;
243 }
244 else
245 {
246 Reply->Status = WSAEINVAL;
247 }
248 }
249
250 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
251
252 return Status;
253 }
254
255
256 NTSTATUS AfdDispSendTo(
257 PIRP Irp,
258 PIO_STACK_LOCATION IrpSp)
259 /*
260 * FUNCTION: Sends data to an address
261 * ARGUMENTS:
262 * Irp = Pointer to I/O request packet
263 * IrpSp = Pointer to current stack location of Irp
264 * RETURNS:
265 * Status of operation
266 */
267 {
268 NTSTATUS Status;
269 UINT InputBufferLength;
270 UINT OutputBufferLength;
271 PFILE_REQUEST_SENDTO Request;
272 PFILE_REPLY_SENDTO Reply;
273 PAFDFCB FCB;
274 PVOID SystemVirtualAddress;
275 PVOID DataBufferAddress;
276 ULONG BufferSize;
277 ULONG BytesCopied;
278 PMDL Mdl;
279
280 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
281 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
282
283 /* Validate parameters */
284 if ((InputBufferLength >= sizeof(FILE_REQUEST_SENDTO)) &&
285 (OutputBufferLength >= sizeof(FILE_REPLY_SENDTO))) {
286
287 AFD_DbgPrint(MAX_TRACE, ("FileObject at (0x%X).\n", IrpSp->FileObject));
288 AFD_DbgPrint(MAX_TRACE, ("FCB at (0x%X).\n", IrpSp->FileObject->FsContext));
289 AFD_DbgPrint(MAX_TRACE, ("CCB at (0x%X).\n", IrpSp->FileObject->FsContext2));
290
291 FCB = IrpSp->FileObject->FsContext;
292 Request = (PFILE_REQUEST_SENDTO)Irp->AssociatedIrp.SystemBuffer;
293 Reply = (PFILE_REPLY_SENDTO)Irp->AssociatedIrp.SystemBuffer;
294
295 /* Since we're using bufferred I/O */
296 Request->Buffers = (LPWSABUF)(Request + 1);
297 BufferSize = WSABufferSize(Request->Buffers, Request->BufferCount);
298
299
300 /* FIXME: Should we handle special cases here? */
301 if ((FCB->SocketType == SOCK_RAW) && (FCB->AddressFamily == AF_INET)) {
302 BufferSize += sizeof(IPv4_HEADER);
303 }
304
305
306 if (BufferSize != 0) {
307 AFD_DbgPrint(MAX_TRACE, ("Allocating %d bytes for send buffer.\n", BufferSize));
308 SystemVirtualAddress = ExAllocatePool(NonPagedPool, BufferSize);
309 if (!SystemVirtualAddress) {
310 return STATUS_INSUFFICIENT_RESOURCES;
311 }
312
313 /* FIXME: Should we handle special cases here? */
314 if ((FCB->SocketType == SOCK_RAW) && (FCB->AddressFamily == AF_INET)) {
315 DataBufferAddress = ((PCHAR)SystemVirtualAddress) + sizeof(IPv4_HEADER);
316
317 /* FIXME: Should TCP/IP driver assign source address for raw sockets? */
318 ((PSOCKADDR_IN)&FCB->SocketName)->sin_addr.S_un.S_addr = 0x0100007F;
319
320 BuildIPv4Header(
321 (PIPv4_HEADER)SystemVirtualAddress,
322 BufferSize,
323 FCB->Protocol,
324 &FCB->SocketName,
325 &Request->To);
326 } else {
327 DataBufferAddress = SystemVirtualAddress;
328 }
329
330 Status = MergeWSABuffers(
331 Request->Buffers,
332 Request->BufferCount,
333 DataBufferAddress,
334 BufferSize,
335 &BytesCopied);
336 if (!NT_SUCCESS(Status)) {
337 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
338 return Status;
339 }
340 } else {
341 SystemVirtualAddress = NULL;
342 BytesCopied = 0;
343 }
344
345 Mdl = IoAllocateMdl(
346 SystemVirtualAddress, /* Virtual address of buffer */
347 BufferSize, /* Length of buffer */
348 FALSE, /* Not secondary */
349 FALSE, /* Don't charge quota */
350 NULL); /* Don't use IRP */
351 if (!Mdl) {
352 ExFreePool(SystemVirtualAddress);
353 return STATUS_INSUFFICIENT_RESOURCES;
354 }
355
356 MmBuildMdlForNonPagedPool(Mdl);
357
358 AFD_DbgPrint(MAX_TRACE, ("System virtual address is (0x%X).\n", SystemVirtualAddress));
359 AFD_DbgPrint(MAX_TRACE, ("MDL for data buffer is at (0x%X).\n", Mdl));
360
361 AFD_DbgPrint(MAX_TRACE, ("AFD.SYS: NDIS data buffer is at (0x%X).\n", Mdl));
362 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer MdlFlags is (0x%X).\n", Mdl->MdlFlags));
363 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer Next is at (0x%X).\n", Mdl->Next));
364 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer Size is (0x%X).\n", Mdl->Size));
365 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer MappedSystemVa is (0x%X).\n", Mdl->MappedSystemVa));
366 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer StartVa is (0x%X).\n", Mdl->StartVa));
367 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteCount is (0x%X).\n", Mdl->ByteCount));
368 AFD_DbgPrint(MAX_TRACE, ("NDIS data buffer ByteOffset is (0x%X).\n", Mdl->ByteOffset));
369
370 #if 0
371 #ifdef _MSC_VER
372 try {
373 #endif
374 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
375 #ifdef _MSC_VER
376 } except(EXCEPTION_EXECUTE_HANDLER) {
377 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
378 IoFreeMdl(Mdl);
379 if (BufferSize != 0) {
380 ExFreePool(SystemVirtualAddress);
381 }
382 return STATUS_UNSUCCESSFUL;
383 }
384 #endif
385 #endif
386
387 if (!FCB->TdiAddressObject) {
388 struct sockaddr_in BindName;
389
390 RtlZeroMemory(&BindName,sizeof(BindName));
391 BindName.sin_family = AF_INET;
392
393 Status = TdiOpenAddressFile
394 (&FCB->TdiDeviceName,
395 (SOCKADDR *)&BindName,
396 &FCB->TdiAddressObjectHandle,
397 &FCB->TdiAddressObject);
398
399 if (NT_SUCCESS(Status)) {
400 AfdRegisterEventHandlers(FCB);
401 FCB->State = SOCKET_STATE_BOUND;
402 Reply->Status = NO_ERROR;
403 } else {
404 //FIXME: WSAEADDRNOTAVAIL
405 Reply->Status = WSAEINVAL;
406 MmUnlockPages(Mdl);
407 IoFreeMdl(Mdl);
408 return Status;
409 }
410 }
411
412 Status = TdiSendDatagram(FCB->TdiAddressObject,
413 &Request->To,
414 Mdl,
415 BufferSize);
416
417 /* FIXME: Assumes synchronous operation */
418 #if 0
419 MmUnlockPages(Mdl);
420 #endif
421
422 IoFreeMdl(Mdl);
423
424 if (BufferSize != 0) {
425 ExFreePool(SystemVirtualAddress);
426 }
427
428 Reply->NumberOfBytesSent = BufferSize;
429 Reply->Status = NO_ERROR;
430 } else
431 Status = STATUS_INVALID_PARAMETER;
432
433 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
434
435 return Status;
436 }
437
438
439 NTSTATUS AfdDispRecvFrom(
440 PIRP Irp,
441 PIO_STACK_LOCATION IrpSp)
442 /*
443 * FUNCTION: Receives data from an address
444 * ARGUMENTS:
445 * Irp = Pointer to I/O request packet
446 * IrpSp = Pointer to current stack location of Irp
447 * RETURNS:
448 * Status of operation
449 */
450 {
451 NTSTATUS Status;
452 UINT InputBufferLength;
453 UINT OutputBufferLength;
454 PFILE_REQUEST_RECVFROM Request;
455 PFILE_REPLY_RECVFROM Reply;
456 PAFDFCB FCB;
457
458 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
459
460 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
461 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
462
463 /* Validate parameters */
464 if ((InputBufferLength >= sizeof(FILE_REQUEST_RECVFROM)) &&
465 (OutputBufferLength >= sizeof(FILE_REPLY_RECVFROM))) {
466 FCB = IrpSp->FileObject->FsContext;
467
468 Request = (PFILE_REQUEST_RECVFROM)Irp->AssociatedIrp.SystemBuffer;
469 Reply = (PFILE_REPLY_RECVFROM)Irp->AssociatedIrp.SystemBuffer;
470 /* Since we're using bufferred I/O */
471 Request->Buffers = (LPWSABUF)(Request + 1);
472
473 Status = AfdpDispRecv(
474 Irp,
475 FCB,
476 Request,
477 Reply);
478 } else {
479 Status = STATUS_INVALID_PARAMETER;
480 }
481
482 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
483
484 return Status;
485 }
486
487
488 typedef enum {
489 soRead,
490 soWrite,
491 soExcept
492 } SelectOperation;
493
494
495 DWORD AfdpDispSelectEx(
496 LPFD_SET FDSet,
497 SelectOperation Operation)
498 {
499 PFILE_OBJECT FileObject;
500 NTSTATUS Status;
501 PAFDFCB Current;
502 KIRQL OldIrql;
503 DWORD Count;
504 ULONG i;
505
506 AFD_DbgPrint(MAX_TRACE, ("FDSet (0x%X) Operation (0x%X).\n",
507 FDSet, Operation));
508
509 AFD_DbgPrint(MAX_TRACE, ("FDSet->fd_count (0x%X).\n", FDSet->fd_count));
510
511 Count = 0;
512 for (i = 0; i < FDSet->fd_count; i++) {
513
514 AFD_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", FDSet->fd_array[i]));
515
516 Status = ObReferenceObjectByHandle(
517 (HANDLE)FDSet->fd_array[i],
518 0,
519 IoFileObjectType,
520 KernelMode,
521 (PVOID*)&FileObject,
522 NULL);
523 if (NT_SUCCESS(Status)) {
524 AFD_DbgPrint(MAX_TRACE, ("File object is at (0x%X).\n", FileObject));
525
526 Current = FileObject->FsContext;
527
528 switch (Operation) {
529 case soRead:
530 KeAcquireSpinLock(&Current->ReceiveQueueLock, &OldIrql);
531 if (!IsListEmpty(&Current->ReceiveQueue)) {
532 AFD_DbgPrint(MAX_TRACE, ("Socket is readable.\n"));
533 Count++;
534 }
535 KeReleaseSpinLock(&Current->ReceiveQueueLock, OldIrql);
536 break;
537 case soWrite:
538 /* FIXME: How can we check for writability? */
539 Count++;
540 break;
541 case soExcept:
542 /* FIXME: What is this? */
543 Count++;
544 break;
545 }
546
547 ObDereferenceObject(FileObject);
548 }
549 }
550
551 return Count;
552 }
553
554 NTSTATUS AfdDispSelect(
555 PIRP Irp,
556 PIO_STACK_LOCATION IrpSp)
557 /*
558 * FUNCTION: Checks if sockets have data in the receive buffers
559 * and/or if client can send data
560 * ARGUMENTS:
561 * Irp = Pointer to I/O request packet
562 * IrpSp = Pointer to current stack location of Irp
563 * RETURNS:
564 * Status of operation
565 */
566 {
567 NTSTATUS Status;
568 UINT InputBufferLength;
569 UINT OutputBufferLength;
570 PFILE_REQUEST_SELECT Request;
571 PFILE_REPLY_SELECT Reply;
572 DWORD SocketCount;
573 PAFDFCB FCB;
574
575 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
576 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
577
578 /* Validate parameters */
579 if ((InputBufferLength >= sizeof(FILE_REQUEST_SELECT)) &&
580 (OutputBufferLength >= sizeof(FILE_REPLY_SELECT))) {
581 FCB = IrpSp->FileObject->FsContext;
582
583 Request = (PFILE_REQUEST_SELECT)Irp->AssociatedIrp.SystemBuffer;
584 Reply = (PFILE_REPLY_SELECT)Irp->AssociatedIrp.SystemBuffer;
585
586 AFD_DbgPrint(MAX_TRACE, ("R (0x%X) W (0x%X).\n",
587 Request->ReadFDSet, Request->WriteFDSet));
588
589 SocketCount = 0;
590
591 if (Request->WriteFDSet) {
592 AFD_DbgPrint(MAX_TRACE, ("Write.\n"));
593 SocketCount += AfdpDispSelectEx(Request->WriteFDSet, soWrite);
594 }
595 if (Request->ReadFDSet) {
596 AFD_DbgPrint(MAX_TRACE, ("Read.\n"));
597 SocketCount += AfdpDispSelectEx(Request->ReadFDSet, soRead);
598 }
599 if (Request->ExceptFDSet) {
600 SocketCount += AfdpDispSelectEx(Request->ExceptFDSet, soExcept);
601 }
602
603 AFD_DbgPrint(MAX_TRACE, ("Sockets selected (0x%X).\n", SocketCount));
604
605 Reply->Status = NO_ERROR;
606 Reply->SocketCount = SocketCount;
607 Status = STATUS_SUCCESS;
608 } else
609 Status = STATUS_INVALID_PARAMETER;
610
611 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
612
613 return Status;
614 }
615
616 NTSTATUS AfdDispEventSelect(
617 PIRP Irp,
618 PIO_STACK_LOCATION IrpSp)
619 /*
620 * FUNCTION: Associate an event object with one or more network events
621 * ARGUMENTS:
622 * Irp = Pointer to I/O request packet
623 * IrpSp = Pointer to current stack location of Irp
624 * RETURNS:
625 * Status of operation
626 */
627 {
628 NTSTATUS Status;
629 UINT InputBufferLength;
630 UINT OutputBufferLength;
631 PFILE_REQUEST_EVENTSELECT Request;
632 PFILE_REPLY_EVENTSELECT Reply;
633 PAFDFCB FCB;
634 ULONG i;
635
636 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
637 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
638
639 /* Validate parameters */
640 if ((InputBufferLength >= sizeof(FILE_REQUEST_EVENTSELECT)) &&
641 (OutputBufferLength >= sizeof(FILE_REPLY_EVENTSELECT))) {
642 FCB = IrpSp->FileObject->FsContext;
643
644 Request = (PFILE_REQUEST_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer;
645 Reply = (PFILE_REPLY_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer;
646
647 FCB->NetworkEvents.lNetworkEvents = Request->lNetworkEvents;
648 for (i = 0; i < FD_MAX_EVENTS; i++) {
649 if ((Request->lNetworkEvents & (1 << i)) > 0) {
650 FCB->EventObjects[i] = Request->hEventObject;
651 } else {
652 /* The effect of any previous call to this function is cancelled */
653 FCB->EventObjects[i] = (WSAEVENT)0;
654 }
655 }
656
657 Reply->Status = NO_ERROR;
658 Status = STATUS_SUCCESS;
659 } else
660 Status = STATUS_INVALID_PARAMETER;
661
662 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
663
664 return Status;
665 }
666
667 NTSTATUS AfdDispEnumNetworkEvents(
668 PIRP Irp,
669 PIO_STACK_LOCATION IrpSp)
670 /*
671 * FUNCTION: Reports network events
672 * ARGUMENTS:
673 * Irp = Pointer to I/O request packet
674 * IrpSp = Pointer to current stack location of Irp
675 * RETURNS:
676 * Status of operation
677 */
678 {
679 NTSTATUS Status;
680 UINT InputBufferLength;
681 UINT OutputBufferLength;
682 PFILE_REQUEST_ENUMNETWORKEVENTS Request;
683 PFILE_REPLY_ENUMNETWORKEVENTS Reply;
684 HANDLE EventObject;
685 PAFDFCB FCB;
686
687 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
688 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
689
690 /* Validate parameters */
691 if ((InputBufferLength >= sizeof(FILE_REQUEST_ENUMNETWORKEVENTS)) &&
692 (OutputBufferLength >= sizeof(FILE_REPLY_ENUMNETWORKEVENTS))) {
693 FCB = IrpSp->FileObject->FsContext;
694
695 Request = (PFILE_REQUEST_ENUMNETWORKEVENTS)Irp->AssociatedIrp.SystemBuffer;
696 Reply = (PFILE_REPLY_ENUMNETWORKEVENTS)Irp->AssociatedIrp.SystemBuffer;
697
698 EventObject = (HANDLE)Request->hEventObject;
699
700 RtlCopyMemory(
701 &Reply->NetworkEvents,
702 &FCB->NetworkEvents,
703 sizeof(WSANETWORKEVENTS));
704
705 RtlZeroMemory(
706 &FCB->NetworkEvents,
707 sizeof(WSANETWORKEVENTS));
708
709 if (EventObject != NULL) {
710 ZwClearEvent(EventObject);
711 }
712
713 Reply->Status = NO_ERROR;
714 Status = STATUS_SUCCESS;
715 } else
716 Status = STATUS_INVALID_PARAMETER;
717
718 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
719
720 return Status;
721 }
722
723
724 NTSTATUS AfdDispRecv(
725 PIRP Irp,
726 PIO_STACK_LOCATION IrpSp)
727 /*
728 * FUNCTION: Receives data from an address
729 * ARGUMENTS:
730 * Irp = Pointer to I/O request packet
731 * IrpSp = Pointer to current stack location of Irp
732 * RETURNS:
733 * Status of operation
734 */
735 {
736 #if 0
737 NTSTATUS Status;
738 UINT InputBufferLength;
739 UINT OutputBufferLength;
740 PFILE_REQUEST_RECV Request;
741 PFILE_REPLY_RECV Reply;
742 DWORD NumberOfBytesRecvd;
743 PAFDFCB FCB;
744
745 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
746
747 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
748 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
749
750 /* Validate parameters */
751 if ((InputBufferLength >= sizeof(FILE_REQUEST_RECV)) &&
752 (OutputBufferLength >= sizeof(FILE_REPLY_RECV))) {
753 FCB = IrpSp->FileObject->FsContext;
754
755 Request = (PFILE_REQUEST_RECV)Irp->AssociatedIrp.SystemBuffer;
756 Reply = (PFILE_REPLY_RECV)Irp->AssociatedIrp.SystemBuffer;
757
758 Status = AfdpDispRecv(
759 Irp,
760 FCB,
761 Request->Buffers,
762 Request->BufferCount,
763 &NumberOfBytesRecvd);
764 Reply->NumberOfBytesRecvd = NumberOfBytesRecvd;
765 Reply->Status = NO_ERROR;
766 } else {
767 Status = STATUS_INVALID_PARAMETER;
768 }
769
770 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
771
772 return Status;
773 #else
774 return STATUS_SUCCESS;
775 #endif
776 }
777
778
779 NTSTATUS AfdDispSend(
780 PIRP Irp,
781 PIO_STACK_LOCATION IrpSp)
782 /*
783 * FUNCTION: Sends data
784 * ARGUMENTS:
785 * Irp = Pointer to I/O request packet
786 * IrpSp = Pointer to current stack location of Irp
787 * RETURNS:
788 * Status of operation
789 */
790 {
791 NTSTATUS Status;
792 UINT InputBufferLength;
793 UINT OutputBufferLength;
794 PFILE_REQUEST_SEND Request;
795 PFILE_REPLY_SEND Reply;
796 PAFDFCB FCB;
797
798 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
799 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
800
801 /* Validate parameters */
802 if ((InputBufferLength >= sizeof(FILE_REQUEST_SEND)) &&
803 (OutputBufferLength >= sizeof(FILE_REPLY_SEND))) {
804 FCB = IrpSp->FileObject->FsContext;
805
806 Request = (PFILE_REQUEST_SEND)Irp->AssociatedIrp.SystemBuffer;
807 Reply = (PFILE_REPLY_SEND)Irp->AssociatedIrp.SystemBuffer;
808
809 Reply->NumberOfBytesSent = 0;
810 Reply->Status = NO_ERROR;
811 } else
812 Status = STATUS_INVALID_PARAMETER;
813
814 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
815
816 return Status;
817 }
818
819
820 NTSTATUS AfdDispConnect(
821 PIRP Irp,
822 PIO_STACK_LOCATION IrpSp)
823 /*
824 * FUNCTION: Connect to a remote peer
825 * ARGUMENTS:
826 * Irp = Pointer to I/O request packet
827 * IrpSp = Pointer to current stack location of Irp
828 * RETURNS:
829 * Status of operation
830 */
831 {
832 NTSTATUS Status;
833 UINT InputBufferLength;
834 UINT OutputBufferLength;
835 PFILE_REQUEST_CONNECT Request;
836 PFILE_REPLY_CONNECT Reply;
837 PAFDFCB FCB;
838 SOCKADDR_IN LocalAddress;
839
840 AFD_DbgPrint(MIN_TRACE, ("\n"));
841
842 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
843 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
844
845 /* Validate parameters */
846 Status = STATUS_INVALID_PARAMETER;
847 if ((InputBufferLength >= sizeof(FILE_REQUEST_CONNECT)) &&
848 (OutputBufferLength >= sizeof(FILE_REPLY_CONNECT))) {
849 FCB = IrpSp->FileObject->FsContext;
850
851 Request = (PFILE_REQUEST_CONNECT)Irp->AssociatedIrp.SystemBuffer;
852 Reply = (PFILE_REPLY_CONNECT)Irp->AssociatedIrp.SystemBuffer;
853
854 AFD_DbgPrint(MIN_TRACE, ("\n"));
855
856 if (FCB->State == SOCKET_STATE_BOUND) {
857 Reply->Status = WSAEADDRINUSE;
858 } else if (FCB->State == SOCKET_STATE_CONNECTED) {
859 Reply->Status = WSAEISCONN;
860 } else {
861 /* We have an unbound socket so go ahead and create an address
862 file object and a connection endpoint and associate the two */
863
864 AFD_DbgPrint(MIN_TRACE, ("\n"));
865
866 /* FIXME: Get from client */
867 LocalAddress.sin_family = AF_INET;
868 LocalAddress.sin_port = 1700;
869 LocalAddress.sin_addr.S_un.S_addr = 0x0; /* Dynamically allocate */
870
871 Status = TdiOpenAddressFile(
872 &FCB->TdiDeviceName,
873 (LPSOCKADDR)&LocalAddress,
874 &FCB->TdiAddressObjectHandle,
875 &FCB->TdiAddressObject);
876
877 if (NT_SUCCESS(Status)) {
878 AfdRegisterEventHandlers(FCB);
879 FCB->State = SOCKET_STATE_BOUND;
880 }
881
882 AFD_DbgPrint(MIN_TRACE, ("\n"));
883
884 if (NT_SUCCESS(Status)) {
885 Status = TdiOpenConnectionEndpointFile(
886 &FCB->TdiDeviceName,
887 &FCB->TdiConnectionObjectHandle,
888 &FCB->TdiConnectionObject);
889 }
890
891 AFD_DbgPrint(MIN_TRACE, ("\n"));
892
893 if (NT_SUCCESS(Status)) {
894 Status = TdiAssociateAddressFile(
895 FCB->TdiAddressObjectHandle,
896 FCB->TdiConnectionObject);
897 }
898
899 AFD_DbgPrint(MIN_TRACE, ("\n"));
900
901 if (NT_SUCCESS(Status)) {
902 /* Now attempt to connect to the remote peer */
903 Status = TdiConnect(
904 FCB->TdiConnectionObject,
905 Request->name);
906 }
907
908 AFD_DbgPrint(MIN_TRACE, ("\n"));
909
910 if (NT_SUCCESS(Status)) {
911 FCB->State = SOCKET_STATE_CONNECTED;
912 Reply->Status = NO_ERROR;
913 } else {
914 Reply->Status = WSAEINVAL;
915 }
916 }
917 }
918
919 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
920
921 return Status;
922 }
923
924 /* EOF */