mswsock.dll: TranmitFile - new way [1/2]
Łukasz Chróst
lukost at gmail.com
Tue Jun 27 18:17:57 CDT 2006
Changelog:
- added non-overlapped TransmitFile based totally on ws2_32 functions
(compiles for windows also).
- all used functions are user-level
Bugs:
- the functions is non-overlapped and blocking only for now
--
Lukasz Chrost
-------------- next part --------------
Index: dlls/mswsock/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/Makefile.in,v
retrieving revision 1.3
diff -u -r1.3 Makefile.in
--- dlls/mswsock/Makefile.in 9 May 2005 14:42:33 -0000 1.3
+++ dlls/mswsock/Makefile.in 27 Jun 2006 23:13:09 -0000
@@ -4,13 +4,16 @@
VPATH = @srcdir@
MODULE = mswsock.dll
IMPORTLIB = libmswsock.$(IMPLIBEXT)
-IMPORTS = ws2_32 iphlpapi kernel32
+IMPORTS = ws2_32 kernel32
+
C_SRCS = \
mswsock.c
RC_SRCS = version.rc
+SUBDIRS = tests
+
@MAKE_DLL_RULES@
### Dependencies:
Index: dlls/mswsock/mswsock.c
===================================================================
RCS file: /home/wine/wine/dlls/mswsock/mswsock.c,v
retrieving revision 1.4
diff -u -r1.4 mswsock.c
--- dlls/mswsock/mswsock.c 23 May 2006 12:48:20 -0000 1.4
+++ dlls/mswsock/mswsock.c 27 Jun 2006 22:56:18 -0000
@@ -29,6 +29,15 @@
#include "wine/debug.h"
+/* ************************************************************************************************ */
+/* Handle validation against INVALID_HANDLE_VALUE */
+#define HANDLE_VALID(x) (!(x==INVALID_HANDLE_VALUE))
+
+/* maximum system-defined data junk we try to post via single read-file-write-socket operation */
+#define FILE_DATA_BUFFER_LENGTH 2048
+
+
+/* ************************************************************************************************ */
WINE_DEFAULT_DEBUG_CHANNEL(mswsock);
/***********************************************************************
@@ -89,33 +98,190 @@
{
FIXME("not implemented\n");
}
+/***********************************************************************
+ * SendDataBuffer (INTERNAL)
+ * send data buffer not longer than maximum allowed, blocks even non-blocking IO */
+
+
+static DWORD SendDataBufferBlock(SOCKET hSocket, LPVOID buf, DWORD buflen,
+ DWORD junksize, DWORD maxwrite)
+{
+ DWORD dwBytesSent = 0;
+ DWORD dwRetVal = 0;
+ DWORD dwBytesLeft = (buflen < maxwrite) ? buflen: maxwrite;
+ fd_set writeset;
+
+ FD_ZERO(&writeset);
+ FD_SET (hSocket, &writeset);
+
+ while(dwBytesLeft)
+ {
+ if((dwRetVal = select(0, 0, &writeset, 0, 0)) == SOCKET_ERROR)
+ goto e_exit;
+ dwRetVal = send(hSocket, &((char *)buf)[dwBytesSent],
+ (dwBytesLeft < junksize) ? dwBytesLeft : junksize,0);
+
+ if(dwRetVal == SOCKET_ERROR)
+ goto e_exit;
+
+ dwBytesLeft -= dwRetVal;
+ dwBytesSent += dwRetVal;
+ }
+ FD_ZERO(&writeset);
+ return dwBytesSent ;
+
+e_exit:
+ FD_ZERO(&writeset);
+ return SOCKET_ERROR;
+}
+
+
/***********************************************************************
- * TransmitFile (MSWSOCK.@)
+ * WSAAddressToStringW (MSWSOCK.@)
*
- * This function is used to transmit a file over socket.
+ * Transmit file via socket. Header / Footer data is also supported.
*
- * TODO
- * This function is currently implemented as a stub.
+ * PARAMS
+ * hSocket [I] Socket for sending the data. Not handle.
+ * hFile [I] file to transmit.
+ * nNumberOfBytesToWrite [I] How much data to write. Optional
+ * nNumberOfBytesPerSend [I] Maximum length of single packet (usefull for communication protocols)
+ * lpOverlapped [I/O] used for overlapped operations
+ * lpTransmitBuffers [I] data to send as header/tail usefull for communication protocols)
+ * dwFlags [I] communication flags.
+ *
+ * RETURNS
+ * Success: non-overlapped: TRUE, overlapped: TRUE/FALSE (check real result with WSAGetOverlappedResult)
+ * Failure: FALSE
+ *
+ * NOTES
+ * Use lpOverlapped->Offset for file offset
+ *
+ * BUGS
+ * lpOverlapped->OffsetHigh is not supported.
+ * limited to ULONG long files size (see above)
+ * doesn't support TF_REUSE_SOCKET and TF_REUSE_SOCKET
+ * doesn't support async IO
*/
-BOOL WINAPI TransmitFile(
- SOCKET hSocket, /* [in] Handle to a connected socket */
- HANDLE hFile, /* [in] Handle to the open file that should be
- transmited */
- DWORD nNumberOfBytesToWrite, /* [in] Number of file bytes to
- transmit */
- DWORD nNumberOfBytesPerSend, /* [in] Size in bytes of each block of
- data sent in each send operation */
- LPOVERLAPPED lpOverlapped, /* [in] Specify in order to achieve an
- overlapped (asynchronous) I/O
- operation */
- LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
- /* [in] Contains pointers to data to send before and after
- the file data is sent */
- DWORD dwFlags) /* [in] Flags */
+BOOL WINAPI TransmitFile(SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite,
+ DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped,
+ LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags)
{
- FIXME("not implemented\n");
+ DWORD dwBytesSent = 0, dwTotalBytesSent = 0;
+ DWORD dwReadLen = 0;
+ DWORD dwRetVal = 0;
+ LPVOID lpstrBuffer = 0;
+
+ TRACE("hSocket %04x, hFile %p, nbytes %ld, npsize %ld, ovl %p, tfbuf %p, flags %ld\n",
+ hSocket, hFile, nNumberOfBytesToWrite, nNumberOfBytesPerSend,
+ lpOverlapped, lpTransmitBuffers, dwFlags);
+
+ if(!HANDLE_VALID(hFile))
+ {
+ WSASetLastError(WSAEINVAL);
+ return FALSE;
+ }
+
+ if(dwFlags & TF_REUSE_SOCKET)
+ FIXME("TF_REUSE_SOCKET has no effect.\n");
+
+
+ if(lpOverlapped)
+ {
+ FIXME("WARNING: Overlapped operation is not supported.\n");
+ if(lpOverlapped->Offset || lpOverlapped->OffsetHigh)
+ {
+ dwRetVal = SetFilePointer( hFile, lpOverlapped->Offset,
+ &lpOverlapped->OffsetHigh, FILE_BEGIN);
+ if(dwRetVal == INVALID_SET_FILE_POINTER)
+ {
+ if(GetLastError() != NO_ERROR)
+ {
+ WSASetLastError(WSAEINVAL);
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ if(nNumberOfBytesPerSend > FILE_DATA_BUFFER_LENGTH) /*we are using local var anyway */
+ nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH;
+ if(!nNumberOfBytesPerSend)
+ nNumberOfBytesPerSend = FILE_DATA_BUFFER_LENGTH;
+ if(!nNumberOfBytesToWrite)
+ nNumberOfBytesToWrite = -1; /* should be OK */
+
+ dwRetVal = SendDataBufferBlock(hSocket, lpTransmitBuffers->Head,
+ lpTransmitBuffers->HeadLength, nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+ if(dwRetVal == SOCKET_ERROR)
+ goto e_exit;
+
+ dwTotalBytesSent += dwBytesSent;
+ if(!(nNumberOfBytesToWrite -= dwBytesSent))
+ goto ok_exit;
+
+ if(hFile)
+ {
+ lpstrBuffer = HeapAlloc( GetProcessHeap(), 0, FILE_DATA_BUFFER_LENGTH);
+ if(!lpstrBuffer)
+ {
+ WSASetLastError(WSAENOBUFS);
+ goto e_exit;
+ }
+
+ while(nNumberOfBytesToWrite)
+ {
+ dwRetVal = ReadFile(hFile, lpstrBuffer,
+ (nNumberOfBytesToWrite < nNumberOfBytesPerSend) ?
+ nNumberOfBytesToWrite : nNumberOfBytesPerSend,
+ &dwReadLen, 0);
+
+ if(!dwRetVal)
+ {
+ WSASetLastError(WSAEACCES);
+ goto e_exit;
+ }
+
+ if(!dwReadLen) /* we are beyond EOF */
+ break;
+
+ dwRetVal = SendDataBufferBlock(hSocket, lpstrBuffer, dwReadLen,
+ nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+
+ if(dwRetVal == SOCKET_ERROR)
+ goto e_exit;
+
+ dwTotalBytesSent += dwBytesSent;
+ if(!(nNumberOfBytesToWrite -= dwBytesSent))
+ goto ok_exit;
+ }
+ }
+
+ dwRetVal = SendDataBufferBlock(hSocket, lpTransmitBuffers->Tail,
+ lpTransmitBuffers->TailLength, nNumberOfBytesPerSend, nNumberOfBytesToWrite);
+ if(dwRetVal == SOCKET_ERROR)
+ goto e_exit;
+
+ dwTotalBytesSent += dwBytesSent;
+ if(dwFlags & TF_DISCONNECT)
+
+
+ok_exit:
+ if(lpOverlapped)
+ lpOverlapped->Internal = dwTotalBytesSent; /* FIXME */
+ if(lpstrBuffer)
+ HeapFree( GetProcessHeap(), 0, lpstrBuffer);
+
+ if(dwFlags & TF_DISCONNECT)
+ closesocket(hSocket);
+
+ return TRUE;
+
+e_exit:
+ if(lpstrBuffer)
+ HeapFree( GetProcessHeap(), 0, lpstrBuffer);
return FALSE;
}
More information about the wine-patches
mailing list