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