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