Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

221 lines
7.3 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
tranfile.c
Abstract:
This module contains support TransmitFile() extended
WinSock API.
Author:
David Treadwell (davidtr) 3-Aug-1994
Revision History:
--*/
#include "winsockp.h"
BOOL
TransmitFile (
IN SOCKET hSocket,
IN HANDLE hFile,
IN DWORD nNumberOfBytesToWrite,
IN DWORD nNumberOfBytesPerSend,
IN LPOVERLAPPED lpOverlapped,
IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
IN DWORD dwFlags
)
/*++
Routine Description:
Transmits file data over a connected socket handle by interfacing
with the cache manager to retrieve the file data. Use this routine
when high performance file data transfer over sockets is required.
Arguments:
hSocket - a connected socket handle. The socket may be a datagram
socket or a virtual circuit socket.
hFile - an open file handle. Since the file data is read
sequentially, it is recommended that the handle be opened with
FILE_FLAG_SEQUENTIAL_SCAN to improve caching performance.
nNumberOfBytesToWrite - the count of bytes to send from the file.
This request will not complete until the entire requested amount
has been sent, or until an error is encountered. If this
parameter is equal to zero, then the entire file is transmited.
nNumberOfBytesPerSend - informs the sockets layer of the size to use
for each send it performs. The value 0 indicates that an
intelligent default should be used. This is mainly useful for
datagram or message protocols that have limitations of the size
of individual send requests.
lpOverlapped - specify this parameter when the socket handle is
opened as overlapped to achieve overlapped I/O. Note that by
default sockets are opened as overlapped.
Also use this parameter to specify an offset within the file at
which to start the file data transfer. The file pointer is
ignored by this API, so if lpOverlapped is NULL the transmission
always starts at offset 0 in the file.
When lpOverlapped is non-NULL, TransmitFile() may return
ERROR_IO_PENDING to allow the calling function to continue
processing while the operation completes. The event (or hSocket
if hEvent is NULL) will be set to the signalled state upon
completion of the request.
lpTransmitBuffers - an optional pointer to a TRANSMIT_FILE_BUFFERS
structure which contains pointers to data to send before the
file (the head buffer) and after the file (the tail buffer). If
only the file is to be sent, this parameter may be specified as
NULL.
dwFlags - any combination of the following:
TF_DISCONNECT - start a transport-level disconnect after all the
file data has been queued to the transport.
TF_REUSE_SOCKET - prepare the socket handle to be reused. When
the TransmitFile request completes, the socket handle may be
passed to the SuperAccept API. Only valid if TF_DISCONNECT
is also specified.
TF_WRITE_BEHIND - complete the TransmitFile request immediately,
without pending. If this flag is specified and TransmitFile
succeeds, then the data has been accepted by the system but not
necessarily acknowledged by the remote end. Do not use this
setting with the other two settings.
Return Value:
TRUE - The operation was successul.
FALSE - The operation failed. Extended error status is available
using GetLastError().
--*/
{
AFD_TRANSMIT_FILE_INFO transmitInfo;
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;
//
// Set up general imformation about the request.
//
transmitInfo.WriteLength.QuadPart = nNumberOfBytesToWrite;
transmitInfo.SendPacketLength = nNumberOfBytesPerSend;
transmitInfo.FileHandle = hFile;
transmitInfo.Flags = dwFlags;
if ( ARGUMENT_PRESENT( lpTransmitBuffers ) ) {
transmitInfo.Head = lpTransmitBuffers->Head;
transmitInfo.HeadLength = lpTransmitBuffers->HeadLength;
transmitInfo.Tail = lpTransmitBuffers->Tail;
transmitInfo.TailLength = lpTransmitBuffers->TailLength;
} else {
transmitInfo.Head = NULL;
transmitInfo.HeadLength = 0;
transmitInfo.Tail = NULL;
transmitInfo.TailLength = 0;
}
//
// Handle the request differently based on whether an lpOverlapped
// structure was specified. If it was specified, then the socket
// handle must have been opened for asynchronous access.
//
if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
lpOverlapped->Internal = (DWORD)STATUS_PENDING;
transmitInfo.Offset.LowPart = lpOverlapped->Offset;
transmitInfo.Offset.HighPart = lpOverlapped->OffsetHigh;
//
// Call AFD to transmit the file. Note that we pass a smaller
// input buffer than the full structure in order to save the
// input buffer copy in the I/O system. Also note that we do
// pass an output buffer: this ensures that the I/O system
// allocates a large enough system buffer for AFD to use as a
// scratch buffer.
//
status = NtDeviceIoControlFile(
(HANDLE)hSocket,
lpOverlapped->hEvent,
NULL,
(DWORD)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
(PIO_STATUS_BLOCK)(&lpOverlapped->Internal),
IOCTL_AFD_TRANSMIT_FILE,
&transmitInfo,
sizeof(transmitInfo),
NULL,
0
);
if ( NT_SUCCESS(status) && status != STATUS_PENDING) {
return TRUE;
} else {
SetLastError( SockNtStatusToSocketError(status) );
return FALSE;
}
} else {
transmitInfo.Offset.LowPart = 0;
transmitInfo.Offset.HighPart = 0;
//
// Call AFD to transmit the file. Note that we pass a smaller
// input buffer than the full structure in order to save the
// input buffer copy in the I/O system. Also note that we do
// pass an output buffer: this ensures that the I/O system
// allocates a large enough system buffer for AFD to use as a
// scratch buffer.
//
status = NtDeviceIoControlFile(
(HANDLE)hSocket,
NULL,
NULL,
NULL,
&ioStatusBlock,
IOCTL_AFD_TRANSMIT_FILE,
&transmitInfo,
sizeof(transmitInfo),
NULL,
0
);
if ( status == STATUS_PENDING) {
// Operation must complete before return & IoStatusBlock destroyed
status = NtWaitForSingleObject( (HANDLE)hSocket, FALSE, NULL );
if ( NT_SUCCESS(status)) {
status = ioStatusBlock.Status;
}
}
if ( NT_SUCCESS(status) ) {
return TRUE;
} else {
SetLastError( SockNtStatusToSocketError(status) );
return FALSE;
}
}
} // TransmitFile