e1c1fe2a55a1b76527d02bb05c58be4e314a1140
[reactos.git] / drivers / network / afd / afd / write.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/write.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
7 * UPDATE HISTORY:
8 * 20040708 Created
9 */
10
11 #include "afd.h"
12
13 static IO_COMPLETION_ROUTINE SendComplete;
14 static NTSTATUS NTAPI SendComplete
15 ( PDEVICE_OBJECT DeviceObject,
16 PIRP Irp,
17 PVOID Context ) {
18 NTSTATUS Status = Irp->IoStatus.Status;
19 PAFD_FCB FCB = (PAFD_FCB)Context;
20 PLIST_ENTRY NextIrpEntry;
21 PIRP NextIrp = NULL;
22 PIO_STACK_LOCATION NextIrpSp;
23 PAFD_SEND_INFO SendReq = NULL;
24 PAFD_MAPBUF Map;
25 UINT TotalBytesCopied = 0, TotalBytesProcessed = 0, SpaceAvail, i;
26 UINT SendLength, BytesCopied;
27 BOOLEAN HaltSendQueue;
28
29 UNREFERENCED_PARAMETER(DeviceObject);
30
31 /*
32 * The Irp parameter passed in is the IRP of the stream between AFD and
33 * TDI driver. It's not very useful to us. We need the IRPs of the stream
34 * between usermode and AFD. Those are chained from
35 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
36 * below as "NextIrp" ('cause they are the next usermode IRP to be
37 * processed).
38 */
39
40 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n",
41 Irp->IoStatus.Status,
42 Irp->IoStatus.Information));
43
44 if( !SocketAcquireStateLock( FCB ) )
45 return STATUS_FILE_CLOSED;
46
47 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
48 FCB->SendIrp.InFlightRequest = NULL;
49 /* Request is not in flight any longer */
50
51 if( FCB->State == SOCKET_STATE_CLOSED ) {
52 /* Cleanup our IRP queue because the FCB is being destroyed */
53 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
54 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
55 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
56 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
57 SendReq = GetLockedData(NextIrp, NextIrpSp);
58 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
59 NextIrp->IoStatus.Information = 0;
60 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
61 if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
62 (void)IoSetCancelRoutine(NextIrp, NULL);
63 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
64 }
65
66 RetryDisconnectCompletion(FCB);
67
68 SocketStateUnlock( FCB );
69 return STATUS_FILE_CLOSED;
70 }
71
72 if( !NT_SUCCESS(Status) ) {
73 /* Complete all following send IRPs with error */
74
75 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
76 NextIrpEntry =
77 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
78 NextIrp =
79 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
80 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
81 SendReq = GetLockedData(NextIrp, NextIrpSp);
82
83 UnlockBuffers( SendReq->BufferArray,
84 SendReq->BufferCount,
85 FALSE );
86
87 NextIrp->IoStatus.Status = Status;
88 NextIrp->IoStatus.Information = 0;
89
90 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
91 (void)IoSetCancelRoutine(NextIrp, NULL);
92 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
93 }
94
95 RetryDisconnectCompletion(FCB);
96
97 SocketStateUnlock( FCB );
98
99 return STATUS_SUCCESS;
100 }
101
102 RtlMoveMemory( FCB->Send.Window,
103 FCB->Send.Window + Irp->IoStatus.Information,
104 FCB->Send.BytesUsed - Irp->IoStatus.Information );
105
106 TotalBytesProcessed = 0;
107 SendLength = Irp->IoStatus.Information;
108 HaltSendQueue = FALSE;
109 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && SendLength > 0) {
110 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
111 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
112 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
113 SendReq = GetLockedData(NextIrp, NextIrpSp);
114 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
115
116 TotalBytesCopied = (ULONG_PTR)NextIrp->Tail.Overlay.DriverContext[3];
117 ASSERT(TotalBytesCopied != 0);
118
119 /* If we didn't get enough, keep waiting */
120 if (TotalBytesCopied > SendLength)
121 {
122 /* Update the bytes left to copy */
123 TotalBytesCopied -= SendLength;
124 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)TotalBytesCopied;
125
126 /* Update the state variables */
127 FCB->Send.BytesUsed -= SendLength;
128 TotalBytesProcessed += SendLength;
129 SendLength = 0;
130
131 /* Pend the IRP */
132 InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND],
133 &NextIrp->Tail.Overlay.ListEntry);
134 HaltSendQueue = TRUE;
135 break;
136 }
137
138 ASSERT(NextIrp->IoStatus.Information != 0);
139
140 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
141
142 FCB->Send.BytesUsed -= TotalBytesCopied;
143 TotalBytesProcessed += TotalBytesCopied;
144 SendLength -= TotalBytesCopied;
145
146 (void)IoSetCancelRoutine(NextIrp, NULL);
147
148 UnlockBuffers( SendReq->BufferArray,
149 SendReq->BufferCount,
150 FALSE );
151
152 if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp);
153
154 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
155 }
156
157 ASSERT(SendLength == 0);
158
159 if ( !HaltSendQueue && !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
160 NextIrpEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink;
161 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
162 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
163 SendReq = GetLockedData(NextIrp, NextIrpSp);
164 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
165
166 AFD_DbgPrint(MID_TRACE,("SendReq @ %p\n", SendReq));
167
168 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
169 TotalBytesCopied = 0;
170
171 /* Count the total transfer size */
172 SendLength = 0;
173 for (i = 0; i < SendReq->BufferCount; i++)
174 {
175 SendLength += SendReq->BufferArray[i].len;
176 }
177
178 /* Make sure we've got the space */
179 if (SendLength > SpaceAvail)
180 {
181 /* Blocking sockets have to wait here */
182 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
183 {
184 FCB->PollState &= ~AFD_EVENT_SEND;
185
186 NextIrp = NULL;
187 }
188
189 /* Check if we can send anything */
190 if (SpaceAvail == 0)
191 {
192 FCB->PollState &= ~AFD_EVENT_SEND;
193
194 /* We should never be non-overlapped and get to this point */
195 ASSERT(SendReq->AfdFlags & AFD_OVERLAPPED);
196
197 NextIrp = NULL;
198 }
199 }
200
201 if (NextIrp != NULL)
202 {
203 for( i = 0; i < SendReq->BufferCount; i++ ) {
204 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
205
206 Map[i].BufferAddress =
207 MmMapLockedPages( Map[i].Mdl, KernelMode );
208
209 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
210 Map[i].BufferAddress,
211 BytesCopied );
212
213 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
214
215 TotalBytesCopied += BytesCopied;
216 SpaceAvail -= BytesCopied;
217 FCB->Send.BytesUsed += BytesCopied;
218 }
219
220 NextIrp->IoStatus.Information = TotalBytesCopied;
221 NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)NextIrp->IoStatus.Information;
222 }
223 }
224
225 if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && !FCB->SendClosed &&
226 IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]))
227 {
228 FCB->PollState |= AFD_EVENT_SEND;
229 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
230 PollReeval( FCB->DeviceExt, FCB->FileObject );
231 }
232 else
233 {
234 FCB->PollState &= ~AFD_EVENT_SEND;
235 }
236
237
238 /* Some data is still waiting */
239 if( FCB->Send.BytesUsed )
240 {
241 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
242 FCB->Connection.Object,
243 0,
244 FCB->Send.Window,
245 FCB->Send.BytesUsed,
246 SendComplete,
247 FCB );
248 }
249 else
250 {
251 /* Nothing is waiting so try to complete a pending disconnect */
252 RetryDisconnectCompletion(FCB);
253 }
254
255 SocketStateUnlock( FCB );
256
257 return STATUS_SUCCESS;
258 }
259
260 static IO_COMPLETION_ROUTINE PacketSocketSendComplete;
261 static NTSTATUS NTAPI PacketSocketSendComplete
262 ( PDEVICE_OBJECT DeviceObject,
263 PIRP Irp,
264 PVOID Context ) {
265 PAFD_FCB FCB = (PAFD_FCB)Context;
266 PLIST_ENTRY NextIrpEntry;
267 PIRP NextIrp;
268 PAFD_SEND_INFO SendReq;
269
270 UNREFERENCED_PARAMETER(DeviceObject);
271
272 AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n",
273 Irp->IoStatus.Status,
274 Irp->IoStatus.Information));
275
276 if( !SocketAcquireStateLock( FCB ) )
277 return STATUS_FILE_CLOSED;
278
279 ASSERT(FCB->SendIrp.InFlightRequest == Irp);
280 FCB->SendIrp.InFlightRequest = NULL;
281 /* Request is not in flight any longer */
282
283 if( FCB->State == SOCKET_STATE_CLOSED ) {
284 /* Cleanup our IRP queue because the FCB is being destroyed */
285 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
286 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
287 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
288 SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
289 NextIrp->IoStatus.Status = STATUS_FILE_CLOSED;
290 NextIrp->IoStatus.Information = 0;
291 (void)IoSetCancelRoutine(NextIrp, NULL);
292 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
293 UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
294 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
295 }
296 SocketStateUnlock( FCB );
297 return STATUS_FILE_CLOSED;
298 }
299
300 ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
301
302 /* TDI spec guarantees FIFO ordering on IRPs */
303 NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
304 NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
305
306 SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
307
308 NextIrp->IoStatus.Status = Irp->IoStatus.Status;
309 NextIrp->IoStatus.Information = Irp->IoStatus.Information;
310
311 (void)IoSetCancelRoutine(NextIrp, NULL);
312
313 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
314
315 UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp));
316
317 IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT);
318
319 FCB->PollState |= AFD_EVENT_SEND;
320 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
321 PollReeval(FCB->DeviceExt, FCB->FileObject);
322
323 SocketStateUnlock(FCB);
324
325 return STATUS_SUCCESS;
326 }
327
328 NTSTATUS NTAPI
329 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
330 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
331 NTSTATUS Status = STATUS_SUCCESS;
332 PFILE_OBJECT FileObject = IrpSp->FileObject;
333 PAFD_FCB FCB = FileObject->FsContext;
334 PAFD_SEND_INFO SendReq;
335 UINT TotalBytesCopied = 0, i, SpaceAvail = 0, BytesCopied, SendLength;
336 KPROCESSOR_MODE LockMode;
337
338 UNREFERENCED_PARAMETER(DeviceObject);
339 UNREFERENCED_PARAMETER(Short);
340
341 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
342
343 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
344
345 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
346
347 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
348 {
349 PAFD_SEND_INFO_UDP SendReq;
350 PTDI_CONNECTION_INFORMATION TargetAddress;
351
352 /* Check that the socket is bound */
353 if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress )
354 {
355 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
356 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp,
357 0 );
358 }
359
360 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
361 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 );
362
363 /* Must lock buffers before handing off user data */
364 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
365 SendReq->BufferCount,
366 NULL, NULL,
367 FALSE, FALSE, LockMode );
368
369 if( !SendReq->BufferArray ) {
370 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
371 Irp, 0 );
372 }
373
374 Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
375
376 if( NT_SUCCESS(Status) ) {
377 FCB->PollState &= ~AFD_EVENT_SEND;
378
379 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
380 if (Status == STATUS_PENDING)
381 {
382 Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
383 FCB->AddressFile.Object,
384 SendReq->BufferArray[0].buf,
385 SendReq->BufferArray[0].len,
386 TargetAddress,
387 PacketSocketSendComplete,
388 FCB);
389 if (Status != STATUS_PENDING)
390 {
391 NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry);
392 Irp->IoStatus.Status = Status;
393 Irp->IoStatus.Information = 0;
394 (void)IoSetCancelRoutine(Irp, NULL);
395 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
396 UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp));
397 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
398 }
399 }
400
401 ExFreePool( TargetAddress );
402
403 SocketStateUnlock(FCB);
404
405 return STATUS_PENDING;
406 }
407 else
408 {
409 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
410 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
411 }
412 }
413
414 if (FCB->PollState & AFD_EVENT_CLOSE)
415 {
416 AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n"));
417
418 /* This is an unexpected remote disconnect */
419 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
420 }
421
422 if (FCB->PollState & AFD_EVENT_ABORT)
423 {
424 AFD_DbgPrint(MIN_TRACE,("Connection aborted\n"));
425
426 /* This is an abortive socket closure on our side */
427 return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0);
428 }
429
430 if (FCB->SendClosed)
431 {
432 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
433
434 /* This is a graceful send closure */
435 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
436 }
437
438 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
439 return UnlockAndMaybeComplete
440 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
441
442 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
443 SendReq->BufferCount,
444 NULL, NULL,
445 FALSE, FALSE, LockMode );
446
447 if( !SendReq->BufferArray ) {
448 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
449 Irp, 0 );
450 }
451
452 AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State));
453
454 if( FCB->State != SOCKET_STATE_CONNECTED ) {
455 AFD_DbgPrint(MID_TRACE,("Socket not connected\n"));
456 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
457 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_CONNECTION, Irp, 0 );
458 }
459
460 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n",
461 FCB->Send.BytesUsed));
462
463 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
464
465 AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n",
466 SpaceAvail));
467
468 /* Count the total transfer size */
469 SendLength = 0;
470 for (i = 0; i < SendReq->BufferCount; i++)
471 {
472 SendLength += SendReq->BufferArray[i].len;
473 }
474
475 /* Make sure we've got the space */
476 if (SendLength > SpaceAvail)
477 {
478 /* Blocking sockets have to wait here */
479 if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking)))
480 {
481 FCB->PollState &= ~AFD_EVENT_SEND;
482 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
483 }
484
485 /* Check if we can send anything */
486 if (SpaceAvail == 0)
487 {
488 FCB->PollState &= ~AFD_EVENT_SEND;
489
490 /* Non-overlapped sockets will fail if we can send nothing */
491 if (!(SendReq->AfdFlags & AFD_OVERLAPPED))
492 {
493 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
494 return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 );
495 }
496 else
497 {
498 /* Overlapped sockets just pend */
499 return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND);
500 }
501 }
502 }
503
504 for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ )
505 {
506 BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail);
507
508 AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n",
509 i,
510 SendReq->BufferArray[i].buf,
511 BytesCopied,
512 FCB->Send.Window + FCB->Send.BytesUsed));
513
514 RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed,
515 SendReq->BufferArray[i].buf,
516 BytesCopied);
517
518 TotalBytesCopied += BytesCopied;
519 SpaceAvail -= BytesCopied;
520 FCB->Send.BytesUsed += BytesCopied;
521 }
522
523 Irp->IoStatus.Information = TotalBytesCopied;
524
525 if( TotalBytesCopied == 0 ) {
526 AFD_DbgPrint(MID_TRACE,("Empty send\n"));
527 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
528 return UnlockAndMaybeComplete
529 ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied );
530 }
531
532 if (SpaceAvail)
533 {
534 FCB->PollState |= AFD_EVENT_SEND;
535 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
536 PollReeval( FCB->DeviceExt, FCB->FileObject );
537 }
538 else
539 {
540 FCB->PollState &= ~AFD_EVENT_SEND;
541 }
542
543 /* We use the IRP tail for some temporary storage here */
544 Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information;
545
546 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
547 if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest)
548 {
549 TdiSend(&FCB->SendIrp.InFlightRequest,
550 FCB->Connection.Object,
551 0,
552 FCB->Send.Window,
553 FCB->Send.BytesUsed,
554 SendComplete,
555 FCB);
556 }
557
558 SocketStateUnlock(FCB);
559
560 return STATUS_PENDING;
561 }
562
563 NTSTATUS NTAPI
564 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
565 PIO_STACK_LOCATION IrpSp) {
566 NTSTATUS Status = STATUS_SUCCESS;
567 PTDI_CONNECTION_INFORMATION TargetAddress;
568 PFILE_OBJECT FileObject = IrpSp->FileObject;
569 PAFD_FCB FCB = FileObject->FsContext;
570 PAFD_SEND_INFO_UDP SendReq;
571 KPROCESSOR_MODE LockMode;
572
573 UNREFERENCED_PARAMETER(DeviceObject);
574
575 AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB));
576
577 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
578
579 FCB->EventSelectDisabled &= ~AFD_EVENT_SEND;
580
581 /* Check that the socket is bound */
582 if( FCB->State != SOCKET_STATE_BOUND &&
583 FCB->State != SOCKET_STATE_CREATED)
584 {
585 AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n"));
586 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
587 }
588
589 if (FCB->SendClosed)
590 {
591 AFD_DbgPrint(MIN_TRACE,("No more sends\n"));
592 return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0);
593 }
594
595 if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) )
596 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
597
598 if (FCB->State == SOCKET_STATE_CREATED)
599 {
600 if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress );
601 FCB->LocalAddress =
602 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
603 Address[0].AddressType );
604
605 if( FCB->LocalAddress ) {
606 Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD );
607
608 if( NT_SUCCESS(Status) )
609 FCB->State = SOCKET_STATE_BOUND;
610 else
611 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
612 } else
613 return UnlockAndMaybeComplete
614 ( FCB, STATUS_NO_MEMORY, Irp, 0 );
615 }
616
617 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
618 SendReq->BufferCount,
619 NULL, NULL,
620 FALSE, FALSE, LockMode );
621
622 if( !SendReq->BufferArray )
623 return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION,
624 Irp, 0 );
625
626 AFD_DbgPrint
627 (MID_TRACE,("RemoteAddress #%d Type %u\n",
628 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
629 TAAddressCount,
630 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->
631 Address[0].AddressType));
632
633 Status = TdiBuildConnectionInfo( &TargetAddress,
634 ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) );
635
636 /* Check the size of the Address given ... */
637
638 if( NT_SUCCESS(Status) ) {
639 FCB->PollState &= ~AFD_EVENT_SEND;
640
641 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND);
642 if (Status == STATUS_PENDING)
643 {
644 Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest,
645 FCB->AddressFile.Object,
646 SendReq->BufferArray[0].buf,
647 SendReq->BufferArray[0].len,
648 TargetAddress,
649 PacketSocketSendComplete,
650 FCB);
651 if (Status != STATUS_PENDING)
652 {
653 NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry);
654 Irp->IoStatus.Status = Status;
655 Irp->IoStatus.Information = 0;
656 (void)IoSetCancelRoutine(Irp, NULL);
657 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
658 UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp));
659 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
660 }
661 }
662
663 ExFreePool(TargetAddress);
664
665 SocketStateUnlock(FCB);
666
667 return STATUS_PENDING;
668 }
669 else
670 {
671 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
672 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
673 }
674 }