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