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