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