40b9c875ea1fc470f0e344ecc80896060e76c640
[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 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 */