migrate substitution keywords to SVN
[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;
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->SendIrp.InFlightRequest = NULL;
169 /* Request is not in flight any longer */
170
171 if( FCB->State == SOCKET_STATE_CLOSED ) {
172 SocketStateUnlock( FCB );
173 DestroySocket( FCB );
174 return STATUS_SUCCESS;
175 }
176
177 SocketStateUnlock( FCB );
178
179 return STATUS_SUCCESS;
180 }
181
182 NTSTATUS STDCALL
183 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
184 PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
185 NTSTATUS Status = STATUS_SUCCESS;
186 PFILE_OBJECT FileObject = IrpSp->FileObject;
187 PAFD_FCB FCB = FileObject->FsContext;
188 PAFD_SEND_INFO SendReq;
189 UINT TotalBytesCopied = 0, i, CopySize = 0,
190 SpaceAvail = 0, TotalBytesEncountered = 0;
191
192 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
193
194 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
195
196 FCB->EventsFired &= ~AFD_EVENT_SEND;
197
198 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
199 {
200 PAFD_SEND_INFO_UDP SendReq;
201 PTDI_CONNECTION_INFORMATION TargetAddress;
202
203 /* Check that the socket is bound */
204 if( FCB->State != SOCKET_STATE_BOUND )
205 return UnlockAndMaybeComplete( FCB, STATUS_UNSUCCESSFUL, Irp,
206 0, NULL, FALSE );
207
208 if( !(SendReq = LockRequest( Irp, IrpSp )) )
209 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0,
210 NULL, FALSE );
211
212 TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
213
214 SocketCalloutEnter( FCB );
215
216 Status = TdiSendDatagram
217 ( &FCB->SendIrp.InFlightRequest,
218 FCB->AddressFile.Object,
219 SendReq->BufferArray[0].buf,
220 SendReq->BufferArray[0].len,
221 TargetAddress,
222 &FCB->SendIrp.Iosb,
223 PacketSocketSendComplete,
224 FCB );
225
226 SocketCalloutLeave( FCB );
227
228 ExFreePool( TargetAddress );
229
230 if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
231
232 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
233
234 return UnlockAndMaybeComplete( FCB, Status, Irp,
235 SendReq->BufferArray[0].len,
236 NULL, TRUE );
237 }
238
239 if( !(SendReq = LockRequest( Irp, IrpSp )) )
240 return UnlockAndMaybeComplete
241 ( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied, NULL, FALSE );
242
243 AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State));
244
245 if( FCB->State != SOCKET_STATE_CONNECTED ) {
246 if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
247 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
248 return UnlockAndMaybeComplete
249 ( FCB, STATUS_CANT_WAIT, Irp, 0, NULL, TRUE );
250 } else {
251 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
252 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
253 }
254 }
255
256 AFD_DbgPrint(MID_TRACE,("We already have %d bytes waiting.\n",
257 FCB->Send.BytesUsed));
258
259 SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
260 SendReq->BufferCount,
261 NULL, NULL,
262 FALSE, FALSE );
263
264 AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n",
265 FCB->Send.BytesUsed));
266
267 if( !FCB->Send.BytesUsed ) {
268 SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
269
270 AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n",
271 SpaceAvail));
272
273 for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size &&
274 i < SendReq->BufferCount; i++ ) {
275 CopySize = MIN( SpaceAvail,
276 SendReq->BufferArray[i].len );
277
278 TotalBytesEncountered += SendReq->BufferArray[i].len;
279
280 AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
281 i,
282 SendReq->BufferArray[i].buf,
283 CopySize,
284 FCB->Send.Window + FCB->Send.BytesUsed));
285
286 RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
287 SendReq->BufferArray[i].buf,
288 CopySize );
289
290 FCB->Send.BytesUsed += CopySize;
291 TotalBytesCopied += CopySize;
292 SpaceAvail -= CopySize;
293 }
294
295 if( TotalBytesEncountered == 0 ) {
296 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
297
298 AFD_DbgPrint(MID_TRACE,("Empty send\n"));
299 return UnlockAndMaybeComplete
300 ( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE );
301 }
302
303 AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
304
305 if( TotalBytesCopied > 0 ) {
306 UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
307
308 FCB->SendIrp.InFlightRequest = (PVOID)1; /* Placeholder */
309
310 SocketCalloutEnter( FCB );
311
312 Status = TdiSend( &FCB->SendIrp.InFlightRequest,
313 FCB->Connection.Object,
314 0,
315 FCB->Send.Window,
316 FCB->Send.BytesUsed,
317 &FCB->SendIrp.Iosb,
318 SendComplete,
319 FCB );
320
321 SocketCalloutLeave( FCB );
322
323 if( Status == STATUS_PENDING )
324 Status = STATUS_SUCCESS;
325
326 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
327 Status, TotalBytesCopied));
328
329 return UnlockAndMaybeComplete
330 ( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE );
331 }
332 }
333
334 if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
335 AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
336 return UnlockAndMaybeComplete
337 ( FCB, STATUS_CANT_WAIT, Irp, 0, NULL, TRUE );
338 } else {
339 AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
340 return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
341 }
342 }
343
344 NTSTATUS STDCALL
345 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
346 PIO_STACK_LOCATION IrpSp) {
347 NTSTATUS Status = STATUS_SUCCESS;
348 PTDI_CONNECTION_INFORMATION TargetAddress;
349 PFILE_OBJECT FileObject = IrpSp->FileObject;
350 PAFD_FCB FCB = FileObject->FsContext;
351 PAFD_SEND_INFO_UDP SendReq;
352
353 AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
354
355 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
356
357 FCB->EventsFired &= ~AFD_EVENT_SEND;
358
359 /* Check that the socket is bound */
360 if( FCB->State != SOCKET_STATE_BOUND )
361 return UnlockAndMaybeComplete
362 ( FCB, STATUS_UNSUCCESSFUL, Irp, 0, NULL, FALSE );
363 if( !(SendReq = LockRequest( Irp, IrpSp )) )
364 return UnlockAndMaybeComplete
365 ( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, FALSE );
366
367 AFD_DbgPrint
368 (MID_TRACE,("RemoteAddress #%d Type %d\n",
369 ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
370 TAAddressCount,
371 ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
372 Address[0].AddressType));
373
374 TdiBuildConnectionInfo( &TargetAddress,
375 ((PTRANSPORT_ADDRESS)SendReq->RemoteAddress) );
376
377 /* Check the size of the Address given ... */
378
379 if( TargetAddress ) {
380 SocketCalloutEnter( FCB );
381
382 Status = TdiSendDatagram
383 ( &FCB->SendIrp.InFlightRequest,
384 FCB->AddressFile.Object,
385 SendReq->BufferArray[0].buf,
386 SendReq->BufferArray[0].len,
387 TargetAddress,
388 &FCB->SendIrp.Iosb,
389 PacketSocketSendComplete,
390 FCB );
391
392 SocketCalloutLeave( FCB );
393
394 ExFreePool( TargetAddress );
395 } else Status = STATUS_NO_MEMORY;
396
397 if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
398
399 AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
400
401 return UnlockAndMaybeComplete
402 ( FCB, Status, Irp, SendReq->BufferArray[0].len, NULL, TRUE );
403 }
404