Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
4d081f36
Commit
4d081f36
authored
Oct 07, 2015
by
Erich E. Hoover
Committed by
Alexandre Julliard
Oct 20, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ws2_32: Implement a basic synchronous TransmitFile.
Signed-off-by:
Erich E. Hoover
<
erich.e.hoover@wine-staging.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
966827bb
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
222 additions
and
7 deletions
+222
-7
socket.c
dlls/ws2_32/socket.c
+187
-6
sock.c
dlls/ws2_32/tests/sock.c
+35
-1
No files found.
dlls/ws2_32/socket.c
View file @
4d081f36
...
...
@@ -514,6 +514,18 @@ struct ws2_accept_async
struct
ws2_async
*
read
;
};
struct
ws2_transmitfile_async
{
struct
ws2_async_io
io
;
char
*
buffer
;
HANDLE
file
;
DWORD
file_read
;
DWORD
file_bytes
;
DWORD
bytes_per_send
;
DWORD
flags
;
struct
ws2_async
write
;
};
static
struct
ws2_async_io
*
async_io_freelist
;
static
void
release_async_io
(
struct
ws2_async_io
*
io
)
...
...
@@ -2725,6 +2737,117 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
}
/***********************************************************************
* WS2_ReadFile (INTERNAL)
*
* Perform an APC-safe ReadFile operation
*/
static
NTSTATUS
WS2_ReadFile
(
HANDLE
hFile
,
PIO_STATUS_BLOCK
io_status
,
char
*
buffer
,
ULONG
length
)
{
int
result
,
unix_handle
;
unsigned
int
options
;
NTSTATUS
status
;
TRACE
(
"(%p,%p,0x%08x)
\n
"
,
hFile
,
buffer
,
length
);
status
=
wine_server_handle_to_fd
(
hFile
,
FILE_READ_DATA
,
&
unix_handle
,
&
options
);
if
(
status
)
return
status
;
while
((
result
=
read
(
unix_handle
,
buffer
,
length
))
==
-
1
)
{
if
(
errno
!=
EINTR
)
break
;
}
if
(
!
result
)
status
=
(
length
?
STATUS_END_OF_FILE
:
STATUS_SUCCESS
);
else
if
(
result
!=
-
1
)
status
=
STATUS_SUCCESS
;
else
if
(
errno
!=
EAGAIN
)
status
=
wsaErrStatus
();
else
status
=
STATUS_PENDING
;
close
(
unix_handle
);
TRACE
(
"= 0x%08x (%d)
\n
"
,
status
,
result
);
if
(
status
==
STATUS_SUCCESS
||
status
==
STATUS_END_OF_FILE
)
{
io_status
->
u
.
Status
=
status
;
io_status
->
Information
=
result
;
}
return
status
;
}
/***********************************************************************
* WS2_transmitfile_getbuffer (INTERNAL)
*
* Pick the appropriate buffer for a TransmitFile send operation.
*/
static
NTSTATUS
WS2_transmitfile_getbuffer
(
int
fd
,
struct
ws2_transmitfile_async
*
wsa
)
{
/* send any incomplete writes from a previous iteration */
if
(
wsa
->
write
.
first_iovec
<
wsa
->
write
.
n_iovecs
)
return
STATUS_PENDING
;
/* process the main file */
if
(
wsa
->
file
)
{
DWORD
bytes_per_send
=
wsa
->
bytes_per_send
;
IO_STATUS_BLOCK
iosb
;
NTSTATUS
status
;
/* when the size of the transfer is limited ensure that we don't go past that limit */
if
(
wsa
->
file_bytes
!=
0
)
bytes_per_send
=
min
(
bytes_per_send
,
wsa
->
file_bytes
-
wsa
->
file_read
);
status
=
WS2_ReadFile
(
wsa
->
file
,
&
iosb
,
wsa
->
buffer
,
bytes_per_send
);
if
(
status
==
STATUS_END_OF_FILE
)
return
STATUS_SUCCESS
;
else
if
(
status
!=
STATUS_SUCCESS
)
return
status
;
else
{
if
(
iosb
.
Information
)
{
wsa
->
write
.
first_iovec
=
0
;
wsa
->
write
.
n_iovecs
=
1
;
wsa
->
write
.
iovec
[
0
].
iov_base
=
wsa
->
buffer
;
wsa
->
write
.
iovec
[
0
].
iov_len
=
iosb
.
Information
;
wsa
->
file_read
+=
iosb
.
Information
;
}
if
(
wsa
->
file_bytes
!=
0
&&
wsa
->
file_read
>=
wsa
->
file_bytes
)
wsa
->
file
=
NULL
;
return
STATUS_PENDING
;
}
}
return
STATUS_SUCCESS
;
}
/***********************************************************************
* WS2_transmitfile_base (INTERNAL)
*
* Shared implementation for both synchronous and asynchronous TransmitFile.
*/
static
NTSTATUS
WS2_transmitfile_base
(
int
fd
,
struct
ws2_transmitfile_async
*
wsa
)
{
NTSTATUS
status
;
status
=
WS2_transmitfile_getbuffer
(
fd
,
wsa
);
if
(
status
==
STATUS_PENDING
)
{
int
n
;
n
=
WS2_send
(
fd
,
&
wsa
->
write
,
convert_flags
(
wsa
->
write
.
flags
)
);
if
(
n
==
-
1
&&
errno
!=
EAGAIN
)
return
wsaErrStatus
();
}
return
status
;
}
/***********************************************************************
* TransmitFile
*/
static
BOOL
WINAPI
WS2_TransmitFile
(
SOCKET
s
,
HANDLE
h
,
DWORD
file_bytes
,
DWORD
bytes_per_send
,
...
...
@@ -2733,12 +2856,22 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
{
union
generic_unix_sockaddr
uaddr
;
unsigned
int
uaddrlen
=
sizeof
(
uaddr
);
struct
ws2_transmitfile_async
*
wsa
;
NTSTATUS
status
;
int
fd
;
FIXME
(
"(%lx, %p, %d, %d, %p, %p, %d): stub !
\n
"
,
s
,
h
,
file_bytes
,
bytes_per_send
,
overlapped
,
buffers
,
flags
);
if
(
overlapped
||
buffers
)
{
FIXME
(
"(%lx, %p, %d, %d, %p, %p, %d): stub !
\n
"
,
s
,
h
,
file_bytes
,
bytes_per_send
,
overlapped
,
buffers
,
flags
);
WSASetLastError
(
WSAEOPNOTSUPP
);
return
FALSE
;
}
fd
=
get_sock_fd
(
s
,
0
,
NULL
);
TRACE
(
"(%lx, %p, %d, %d, %p, %p, %d)
\n
"
,
s
,
h
,
file_bytes
,
bytes_per_send
,
overlapped
,
buffers
,
flags
);
fd
=
get_sock_fd
(
s
,
FILE_WRITE_DATA
,
NULL
);
if
(
fd
==
-
1
)
{
WSASetLastError
(
WSAENOTSOCK
);
...
...
@@ -2750,12 +2883,60 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
WSASetLastError
(
WSAENOTCONN
);
return
FALSE
;
}
release_sock_fd
(
s
,
fd
);
if
(
flags
)
FIXME
(
"Flags are not currently supported (0x%x).
\n
"
,
flags
);
WSASetLastError
(
WSAEOPNOTSUPP
);
return
FALSE
;
if
(
h
&&
GetFileType
(
h
)
!=
FILE_TYPE_DISK
)
{
FIXME
(
"Non-disk file handles are not currently supported.
\n
"
);
release_sock_fd
(
s
,
fd
);
WSASetLastError
(
WSAEOPNOTSUPP
);
return
FALSE
;
}
/* set reasonable defaults when requested */
if
(
!
bytes_per_send
)
bytes_per_send
=
(
1
<<
16
);
/* Depends on OS version: PAGE_SIZE, 2*PAGE_SIZE, or 2^16 */
if
(
!
(
wsa
=
(
struct
ws2_transmitfile_async
*
)
alloc_async_io
(
sizeof
(
*
wsa
)
+
bytes_per_send
)))
{
release_sock_fd
(
s
,
fd
);
WSASetLastError
(
WSAEFAULT
);
return
FALSE
;
}
wsa
->
buffer
=
(
char
*
)(
wsa
+
1
);
wsa
->
file
=
h
;
wsa
->
file_read
=
0
;
wsa
->
file_bytes
=
file_bytes
;
wsa
->
bytes_per_send
=
bytes_per_send
;
wsa
->
flags
=
flags
;
wsa
->
write
.
hSocket
=
SOCKET2HANDLE
(
s
);
wsa
->
write
.
addr
=
NULL
;
wsa
->
write
.
addrlen
.
val
=
0
;
wsa
->
write
.
flags
=
0
;
wsa
->
write
.
lpFlags
=
&
wsa
->
flags
;
wsa
->
write
.
control
=
NULL
;
wsa
->
write
.
n_iovecs
=
0
;
wsa
->
write
.
first_iovec
=
0
;
wsa
->
write
.
user_overlapped
=
NULL
;
do
{
status
=
WS2_transmitfile_base
(
fd
,
wsa
);
if
(
status
==
STATUS_PENDING
)
{
/* block here */
do_block
(
fd
,
POLLOUT
,
-
1
);
_sync_sock_state
(
s
);
/* let wineserver notice connection */
}
}
while
(
status
==
STATUS_PENDING
);
release_sock_fd
(
s
,
fd
);
if
(
status
!=
STATUS_SUCCESS
)
WSASetLastError
(
NtStatusToWSAError
(
status
)
);
HeapFree
(
GetProcessHeap
(),
0
,
wsa
);
return
(
status
==
STATUS_SUCCESS
);
}
/***********************************************************************
...
...
dlls/ws2_32/tests/sock.c
View file @
4d081f36
...
...
@@ -7429,6 +7429,32 @@ end:
closesocket
(
connector2
);
}
#define compare_file(h,s) compare_file2(h,s,__FILE__,__LINE__)
static
void
compare_file2
(
HANDLE
handle
,
SOCKET
sock
,
const
char
*
file
,
int
line
)
{
char
buf1
[
256
],
buf2
[
256
];
BOOL
success
;
int
i
=
0
;
SetFilePointer
(
handle
,
0
,
NULL
,
FILE_BEGIN
);
while
(
1
)
{
DWORD
n1
=
0
,
n2
=
0
;
success
=
ReadFile
(
handle
,
buf1
,
sizeof
(
buf1
),
&
n1
,
NULL
);
ok_
(
file
,
line
)(
success
,
"Failed to read from file.
\n
"
);
if
(
success
&&
n1
==
0
)
break
;
else
if
(
!
success
)
return
;
n2
=
recv
(
sock
,
buf2
,
n1
,
0
);
ok_
(
file
,
line
)(
n1
==
n2
,
"Block %d size mismatch (%d != %d)
\n
"
,
i
,
n1
,
n2
);
ok_
(
file
,
line
)(
memcmp
(
buf1
,
buf2
,
n2
)
==
0
,
"Block %d failed
\n
"
,
i
);
i
++
;
}
}
static
void
test_TransmitFile
(
void
)
{
GUID
transmitFileGuid
=
WSAID_TRANSMITFILE
;
...
...
@@ -7438,6 +7464,7 @@ static void test_TransmitFile(void)
struct
sockaddr_in
bindAddress
;
SOCKET
client
,
server
,
dest
;
DWORD
num_bytes
,
err
;
char
buf
[
256
];
int
iret
,
len
;
BOOL
bret
;
...
...
@@ -7515,7 +7542,14 @@ static void test_TransmitFile(void)
/* Test TransmitFile with no possible buffer */
bret
=
pTransmitFile
(
client
,
NULL
,
0
,
0
,
NULL
,
NULL
,
0
);
todo_wine
ok
(
bret
,
"TransmitFile failed unexpectedly.
\n
"
);
ok
(
bret
,
"TransmitFile failed unexpectedly.
\n
"
);
iret
=
recv
(
dest
,
buf
,
sizeof
(
buf
),
0
);
ok
(
iret
==
-
1
,
"Returned an unexpected buffer from TransmitFile (%d != -1).
\n
"
,
iret
);
/* Test TransmitFile with only file data */
bret
=
pTransmitFile
(
client
,
file
,
0
,
0
,
NULL
,
NULL
,
0
);
ok
(
bret
,
"TransmitFile failed unexpectedly.
\n
"
);
compare_file
(
file
,
dest
);
/* Test TransmitFile with a UDP datagram socket */
closesocket
(
client
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment