- Only call LockBuffers() if we must
[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 #include "afd.h"
11 #include "tdi_proto.h"
12 #include "tdiconn.h"
13 #include "debug.h"
14
15 static NTSTATUS NTAPI SendComplete
16 ( PDEVICE_OBJECT DeviceObject,
17 PIRP Irp,
18 PVOID Context ) {
19 NTSTATUS Status = Irp->IoStatus.Status;
20 PAFD_FCB FCB = (PAFD_FCB)Context;
21 PLIST_ENTRY NextIrpEntry;
22 PIRP NextIrp = NULL;
23 PIO_STACK_LOCATION NextIrpSp;
24 PAFD_SEND_INFO SendReq = NULL;
25 PAFD_MAPBUF Map;
26 UINT TotalBytesCopied = 0, SpaceAvail, i, CopySize = 0;
27
28 /*
29 * The Irp parameter passed in is the IRP of the stream between AFD and
30 * TDI driver. It's not very usefull to us. We need the IRPs of the stream
31 * between usermode and AFD. Those are chained from
32 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
33 * below as "NextIrp" ('cause they are the next usermode IRP to be
34 * processed).
35 */
36
37 AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
38 Irp->IoStatus.Status,
39 Irp->IoStatus.Information));
40
41 ASSERT_IRQL(APC_LEVEL);
42
43 if( !SocketAcquireStateLock( FCB ) ) return Status;
44
45 FCB->SendIrp.InFlightRequest = NULL;
46 /* Request is not in flight any longer */
47
48 if( FCB->State == SOCKET_STATE_CLOSED ) {
49 SocketStateUnlock( FCB );
50 DestroySocket( FCB );
51 return STATUS_SUCCESS;
52 }
53
54 if( !NT_SUCCESS(Status) ) {
55 /* Complete all following send IRPs with error */
56
57 while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
58 NextIrpEntry =
59 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
60 NextIrp =
61 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
62 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
63 SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
64
65 UnlockBuffers( SendReq->BufferArray,
66 SendReq->BufferCount,
67 FALSE );
68
69 NextIrp->IoStatus.Status = Status;
70 NextIrp->IoStatus.Information = 0;
71
72 if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) );
73
74 IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
75 }
76
77 SocketStateUnlock( FCB );
78
79 return STATUS_SUCCESS;
80 }
81
82 RtlMoveMemory( FCB->Send.Window,
83 FCB->Send.Window + FCB->Send.BytesUsed,
84 FCB->Send.BytesUsed - Irp->IoStatus.Information );
85 FCB->Send.BytesUsed -= Irp->IoStatus.Information;
86
87 if( !FCB->Send.BytesUsed &&
88 !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
89 NextIrpEntry =
90 RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
91 NextIrp =
92 CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
93 NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
94 SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
95 Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
96
97 AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq));
98
99 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
100
101 for( i = 0; i < SendReq->BufferCount; i++ ) {
102 Map[i].BufferAddress =
103 MmMapLockedPages( Map[i].Mdl, KernelMode );
104
105 CopySize = MIN( SpaceAvail,
106 SendReq->BufferArray[i].len );
107
108 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
109 Map[i].BufferAddress,
110 CopySize );
111
112 MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
113
114 FCB->Send.BytesUsed += CopySize;
115 TotalBytesCopied += CopySize;
116 SpaceAvail -= CopySize;
117 }
118 }
119
120 /* Some data is still waiting */
121 if( FCB->Send.BytesUsed ) {
122 FCB->PollState &= ~AFD_EVENT_SEND;
123
124 SocketCalloutEnter( FCB );
125
126 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
127 FCB->Connection.Object,
128 0,
129 FCB->Send.Window,
130 FCB->Send.BytesUsed,
131 &FCB->SendIrp.Iosb,
132 SendComplete,
133 FCB );
134
135 SocketCalloutLeave( FCB );
136 } else {
137 FCB->PollState |= AFD_EVENT_SEND;
138 PollReeval( FCB->DeviceExt, FCB->FileObject );
139 }
140
141 if( TotalBytesCopied > 0 ) {
142 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
143
144 if( Status == STATUS_PENDING )
145 Status = STATUS_SUCCESS;
146
147 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
148
149 return UnlockAndMaybeComplete( FCB, Status, NextIrp, TotalBytesCopied,
150 NULL );
151 } else if( NextIrp ) {
152 AFD_DbgPrint(MID_TRACE,("Could not do any more with Irp %x\n",
153 NextIrp));
154 InsertHeadList( &FCB->PendingIrpList[FUNCTION_SEND],
155 &NextIrp->Tail.Overlay.ListEntry );
156 }
157
158 SocketStateUnlock( FCB );
159
160 return STATUS_SUCCESS;
161 }
162
163 static NTSTATUS NTAPI PacketSocketSendComplete
164 ( PDEVICE_OBJECT DeviceObject,
165 PIRP Irp,
166 PVOID Context ) {
167 PAFD_FCB FCB = (PAFD_FCB)Context;
168
169 AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
170 Irp->IoStatus.Status,
171 Irp->IoStatus.Information));
172
173 /* It's ok if the FCB already died */
174 if( !SocketAcquireStateLock( FCB ) ) return STATUS_SUCCESS;
175
176 FCB->PollState |= AFD_EVENT_SEND;
177 PollReeval( FCB->DeviceExt, FCB->FileObject );
178
179 FCB->SendIrp.InFlightRequest = NULL;
180 /* Request is not in flight any longer */
181
182 if( FCB->State == SOCKET_STATE_CLOSED ) {
183 SocketStateUnlock( FCB );
184 DestroySocket( FCB );
185 return STATUS_SUCCESS;
186 }
187
188 SocketStateUnlock( FCB );
189
190 return STATUS_SUCCESS;
191 }
192
193 NTSTATUS STDCALL
194 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
195 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
196 NTSTATUS Status = STATUS_SUCCESS;
197 PFILE_OBJECT FileObject = IrpSp->FileObject;
198 PAFD_FCB FCB = FileObject->FsContext;
199 PAFD_SEND_INFO SendReq;
200 UINT TotalBytesCopied = 0, i, CopySize = 0,
201 SpaceAvail = 0, TotalBytesEncountered = 0;
202
203 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
204
205 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
206
207 FCB->EventsFired &= ~AFD_EVENT_SEND;
208
209 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
210 {
211 PAFD_SEND_INFO_UDP SendReq;
212 PTDI_CONNECTION_INFORMATION TargetAddress;
213
214 /* Check that the socket is bound */
215 if( FCB->State != SOCKET_STATE_BOUND )
216 return UnlockAndMaybeComplete( FCB, STATUS_UNSUCCESSFUL, Irp,
217 0, NULL );
218
219 if( !(SendReq = LockRequest( Irp, IrpSp )) )
220 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0,
221 NULL );
222
223 /* Must lock buffers before handing off user data */
224 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
225 SendReq->BufferCount,
226 NULL, NULL,
227 FALSE, FALSE );
228
229 TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
230
231 SocketCalloutEnter( FCB );
232
233 Status = TdiSendDatagram
234 ( &FCB->SendIrp.InFlightRequest,
235 FCB->AddressFile.Object,
236 SendReq->BufferArray[0].buf,
237 SendReq->BufferArray[0].len,
238 TargetAddress,
239 &FCB->SendIrp.Iosb,
240 PacketSocketSendComplete,
241 FCB );
242
243 SocketCalloutLeave( FCB );
244
245 ExFreePool( TargetAddress );
246
247 if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
248
249 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
250
251 return UnlockAndMaybeComplete( FCB, Status, Irp,
252 SendReq->BufferArray[0].len,
253 NULL );
254 }
255
256 if( !(SendReq = LockRequest( Irp, IrpSp )) )
257 return UnlockAndMaybeComplete
258 ( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied, NULL );
259
260 AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State));
261
262 if( FCB->State != SOCKET_STATE_CONNECTED ) {
263 if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
264 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
265 return UnlockAndMaybeComplete
266 ( FCB, STATUS_CANT_WAIT, Irp, 0, NULL );
267 } else {
268 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
269 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
270 }
271 }
272
273 AFD_DbgPrint(MID_TRACE,("We already have %d bytes waiting.\n",
274 FCB->Send.BytesUsed));
275
276 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n",
277 FCB->Send.BytesUsed));
278
279 if( !FCB->Send.BytesUsed ) {
280 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
281
282 AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n",
283 SpaceAvail));
284
285 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
286 SendReq->BufferCount,
287 NULL, NULL,
288 FALSE, FALSE );
289
290 for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size &&
291 i < SendReq->BufferCount; i++ ) {
292 CopySize = MIN( SpaceAvail,
293 SendReq->BufferArray[i].len );
294
295 TotalBytesEncountered += SendReq->BufferArray[i].len;
296
297 AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
298 i,
299 SendReq->BufferArray[i].buf,
300 CopySize,
301 FCB->Send.Window + FCB->Send.BytesUsed));
302
303 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
304 SendReq->BufferArray[i].buf,
305 CopySize );
306
307 FCB->Send.BytesUsed += CopySize;
308 TotalBytesCopied += CopySize;
309 SpaceAvail -= CopySize;
310 }
311
312 if( TotalBytesEncountered == 0 ) {
313 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
314
315 AFD_DbgPrint(MID_TRACE,("Empty send\n"));
316 return UnlockAndMaybeComplete
317 ( FCB, Status, Irp, TotalBytesCopied, NULL );
318 }
319
320 AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
321
322 if( TotalBytesCopied > 0 ) {
323 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
324
325 FCB->SendIrp.InFlightRequest = (PVOID)1; /* Placeholder */
326
327 SocketCalloutEnter( FCB );
328
329 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
330 FCB->Connection.Object,
331 0,
332 FCB->Send.Window,
333 FCB->Send.BytesUsed,
334 &FCB->SendIrp.Iosb,
335 SendComplete,
336 FCB );
337
338 SocketCalloutLeave( FCB );
339
340 if( Status == STATUS_PENDING )
341 Status = STATUS_SUCCESS;
342
343 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
344 Status, TotalBytesCopied));
345
346 return UnlockAndMaybeComplete
347 ( FCB, Status, Irp, TotalBytesCopied, NULL );
348 }
349 }
350
351 if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
352 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
353 return UnlockAndMaybeComplete
354 ( FCB, STATUS_CANT_WAIT, Irp, 0, NULL );
355 } else {
356 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
357 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
358 }
359 }
360
361 NTSTATUS STDCALL
362 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
363 PIO_STACK_LOCATION IrpSp) {
364 NTSTATUS Status = STATUS_SUCCESS;
365 PTDI_CONNECTION_INFORMATION TargetAddress;
366 PFILE_OBJECT FileObject = IrpSp->FileObject;
367 PAFD_FCB FCB = FileObject->FsContext;
368 PAFD_SEND_INFO_UDP SendReq;
369
370 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
371
372 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
373
374 FCB->EventsFired &= ~AFD_EVENT_SEND;
375 FCB->PollState &= ~AFD_EVENT_SEND;
376
377 /* Check that the socket is bound */
378 if( FCB->State != SOCKET_STATE_BOUND )
379 return UnlockAndMaybeComplete
380 ( FCB, STATUS_UNSUCCESSFUL, Irp, 0, NULL );
381 if( !(SendReq = LockRequest( Irp, IrpSp )) )
382 return UnlockAndMaybeComplete
383 ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL );
384
385 AFD_DbgPrint
386 (MID_TRACE,("RemoteAddress #%d Type %d\n",
387 ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
388 TAAddressCount,
389 ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
390 Address[0].AddressType));
391
392 TdiBuildConnectionInfo( &TargetAddress,
393 ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress) );
394
395 /* Check the size of the Address given ... */
396
397 if( TargetAddress ) {
398 SocketCalloutEnter( FCB );
399
400 Status = TdiSendDatagram
401 ( &FCB->SendIrp.InFlightRequest,
402 FCB->AddressFile.Object,
403 SendReq->BufferArray[0].buf,
404 SendReq->BufferArray[0].len,
405 TargetAddress,
406 &FCB->SendIrp.Iosb,
407 PacketSocketSendComplete,
408 FCB );
409
410 SocketCalloutLeave( FCB );
411
412 ExFreePool( TargetAddress );
413 } else Status = STATUS_NO_MEMORY;
414
415 if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
416
417 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
418
419 return UnlockAndMaybeComplete
420 ( FCB, Status, Irp, SendReq->BufferArray[0].len, NULL );
421 }
422