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
effd2c41
Commit
effd2c41
authored
Oct 07, 2015
by
Erich E. Hoover
Committed by
Alexandre Julliard
Oct 21, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ws2_32: Add asynchronous support for TransmitFile.
Signed-off-by:
Erich E. Hoover
<
erich.e.hoover@wine-staging.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b9d8c2b1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
161 additions
and
20 deletions
+161
-20
socket.c
dlls/ws2_32/socket.c
+76
-14
sock.c
dlls/ws2_32/tests/sock.c
+85
-6
No files found.
dlls/ws2_32/socket.c
View file @
effd2c41
...
...
@@ -177,6 +177,8 @@
#define TCP_KEEPIDLE TCP_KEEPALIVE
#endif
#define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
WINE_DEFAULT_DEBUG_CHANNEL
(
winsock
);
WINE_DECLARE_DEBUG_CHANNEL
(
winediag
);
...
...
@@ -524,6 +526,7 @@ struct ws2_transmitfile_async
DWORD
bytes_per_send
;
TRANSMIT_FILE_BUFFERS
buffers
;
DWORD
flags
;
LARGE_INTEGER
offset
;
struct
ws2_async
write
;
};
...
...
@@ -2742,9 +2745,10 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
*
* Perform an APC-safe ReadFile operation
*/
static
NTSTATUS
WS2_ReadFile
(
HANDLE
hFile
,
PIO_STATUS_BLOCK
io_status
,
char
*
buffer
,
ULONG
length
)
static
NTSTATUS
WS2_ReadFile
(
HANDLE
hFile
,
PIO_STATUS_BLOCK
io_status
,
char
*
buffer
,
ULONG
length
,
PLARGE_INTEGER
offset
)
{
int
result
,
unix_handle
;
int
result
=
-
1
,
unix_handle
;
unsigned
int
options
;
NTSTATUS
status
;
...
...
@@ -2753,8 +2757,12 @@ static NTSTATUS WS2_ReadFile(HANDLE hFile, PIO_STATUS_BLOCK io_status, char* buf
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
)
while
(
result
==
-
1
)
{
if
(
offset
->
QuadPart
!=
FILE_USE_FILE_POINTER_POSITION
)
result
=
pread
(
unix_handle
,
buffer
,
length
,
offset
->
QuadPart
);
else
result
=
read
(
unix_handle
,
buffer
,
length
);
if
(
errno
!=
EINTR
)
break
;
}
...
...
@@ -2808,10 +2816,13 @@ static NTSTATUS WS2_transmitfile_getbuffer( int fd, struct ws2_transmitfile_asyn
IO_STATUS_BLOCK
iosb
;
NTSTATUS
status
;
iosb
.
Information
=
0
;
/* 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
);
status
=
WS2_ReadFile
(
wsa
->
file
,
&
iosb
,
wsa
->
buffer
,
bytes_per_send
,
&
wsa
->
offset
);
if
(
wsa
->
offset
.
QuadPart
!=
FILE_USE_FILE_POINTER_POSITION
)
wsa
->
offset
.
QuadPart
+=
iosb
.
Information
;
if
(
status
==
STATUS_END_OF_FILE
)
wsa
->
file
=
NULL
;
/* continue on to the footer */
else
if
(
status
!=
STATUS_SUCCESS
)
...
...
@@ -2860,10 +2871,15 @@ static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *ws
status
=
WS2_transmitfile_getbuffer
(
fd
,
wsa
);
if
(
status
==
STATUS_PENDING
)
{
IO_STATUS_BLOCK
*
iosb
=
(
IO_STATUS_BLOCK
*
)
wsa
->
write
.
user_overlapped
;
int
n
;
n
=
WS2_send
(
fd
,
&
wsa
->
write
,
convert_flags
(
wsa
->
write
.
flags
)
);
if
(
n
==
-
1
&&
errno
!=
EAGAIN
)
if
(
n
>=
0
)
{
if
(
iosb
)
iosb
->
Information
+=
n
;
}
else
if
(
errno
!=
EAGAIN
)
return
wsaErrStatus
();
}
...
...
@@ -2871,6 +2887,33 @@ static NTSTATUS WS2_transmitfile_base( int fd, struct ws2_transmitfile_async *ws
}
/***********************************************************************
* WS2_async_transmitfile (INTERNAL)
*
* Asynchronous callback for overlapped TransmitFile operations.
*/
static
NTSTATUS
WS2_async_transmitfile
(
void
*
user
,
IO_STATUS_BLOCK
*
iosb
,
NTSTATUS
status
,
void
**
apc
,
void
**
arg
)
{
struct
ws2_transmitfile_async
*
wsa
=
user
;
int
fd
;
if
(
status
==
STATUS_ALERTED
)
{
if
(
!
(
status
=
wine_server_handle_to_fd
(
wsa
->
write
.
hSocket
,
FILE_WRITE_DATA
,
&
fd
,
NULL
)))
{
status
=
WS2_transmitfile_base
(
fd
,
wsa
);
wine_server_release_fd
(
wsa
->
write
.
hSocket
,
fd
);
}
if
(
status
==
STATUS_PENDING
)
return
status
;
}
iosb
->
u
.
Status
=
status
;
release_async_io
(
&
wsa
->
io
);
return
status
;
}
/***********************************************************************
* TransmitFile
*/
static
BOOL
WINAPI
WS2_TransmitFile
(
SOCKET
s
,
HANDLE
h
,
DWORD
file_bytes
,
DWORD
bytes_per_send
,
...
...
@@ -2883,14 +2926,6 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
NTSTATUS
status
;
int
fd
;
if
(
overlapped
)
{
FIXME
(
"(%lx, %p, %d, %d, %p, %p, %d): stub !
\n
"
,
s
,
h
,
file_bytes
,
bytes_per_send
,
overlapped
,
buffers
,
flags
);
WSASetLastError
(
WSAEOPNOTSUPP
);
return
FALSE
;
}
TRACE
(
"(%lx, %p, %d, %d, %p, %p, %d)
\n
"
,
s
,
h
,
file_bytes
,
bytes_per_send
,
overlapped
,
buffers
,
flags
);
...
...
@@ -2937,6 +2972,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
wsa
->
file_bytes
=
file_bytes
;
wsa
->
bytes_per_send
=
bytes_per_send
;
wsa
->
flags
=
flags
;
wsa
->
offset
.
QuadPart
=
FILE_USE_FILE_POINTER_POSITION
;
wsa
->
write
.
hSocket
=
SOCKET2HANDLE
(
s
);
wsa
->
write
.
addr
=
NULL
;
wsa
->
write
.
addrlen
.
val
=
0
;
...
...
@@ -2945,7 +2981,33 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD file_bytes, DWORD
wsa
->
write
.
control
=
NULL
;
wsa
->
write
.
n_iovecs
=
0
;
wsa
->
write
.
first_iovec
=
0
;
wsa
->
write
.
user_overlapped
=
NULL
;
wsa
->
write
.
user_overlapped
=
overlapped
;
if
(
overlapped
)
{
IO_STATUS_BLOCK
*
iosb
=
(
IO_STATUS_BLOCK
*
)
overlapped
;
int
status
;
wsa
->
offset
.
u
.
LowPart
=
overlapped
->
u
.
s
.
Offset
;
wsa
->
offset
.
u
.
HighPart
=
overlapped
->
u
.
s
.
OffsetHigh
;
iosb
->
u
.
Status
=
STATUS_PENDING
;
iosb
->
Information
=
0
;
SERVER_START_REQ
(
register_async
)
{
req
->
type
=
ASYNC_TYPE_WRITE
;
req
->
async
.
handle
=
wine_server_obj_handle
(
SOCKET2HANDLE
(
s
)
);
req
->
async
.
event
=
wine_server_obj_handle
(
overlapped
->
hEvent
);
req
->
async
.
callback
=
wine_server_client_ptr
(
WS2_async_transmitfile
);
req
->
async
.
iosb
=
wine_server_client_ptr
(
iosb
);
req
->
async
.
arg
=
wine_server_client_ptr
(
wsa
);
status
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
if
(
status
!=
STATUS_PENDING
)
HeapFree
(
GetProcessHeap
(),
0
,
wsa
);
release_sock_fd
(
s
,
fd
);
WSASetLastError
(
NtStatusToWSAError
(
status
)
);
return
FALSE
;
}
do
{
...
...
dlls/ws2_32/tests/sock.c
View file @
effd2c41
...
...
@@ -7429,15 +7429,15 @@ end:
closesocket
(
connector2
);
}
#define compare_file(h,s
) compare_file2(h,s
,__FILE__,__LINE__)
#define compare_file(h,s
,o) compare_file2(h,s,o
,__FILE__,__LINE__)
static
void
compare_file2
(
HANDLE
handle
,
SOCKET
sock
,
const
char
*
file
,
int
line
)
static
void
compare_file2
(
HANDLE
handle
,
SOCKET
sock
,
int
offset
,
const
char
*
file
,
int
line
)
{
char
buf1
[
256
],
buf2
[
256
];
BOOL
success
;
int
i
=
0
;
SetFilePointer
(
handle
,
0
,
NULL
,
FILE_BEGIN
);
SetFilePointer
(
handle
,
offset
,
NULL
,
FILE_BEGIN
);
while
(
1
)
{
DWORD
n1
=
0
,
n2
=
0
;
...
...
@@ -7457,6 +7457,7 @@ static void compare_file2(HANDLE handle, SOCKET sock, const char *file, int line
static
void
test_TransmitFile
(
void
)
{
DWORD
num_bytes
,
err
,
file_size
,
total_sent
;
GUID
transmitFileGuid
=
WSAID_TRANSMITFILE
;
LPFN_TRANSMITFILE
pTransmitFile
=
NULL
;
HANDLE
file
=
INVALID_HANDLE_VALUE
;
...
...
@@ -7466,11 +7467,13 @@ static void test_TransmitFile(void)
struct
sockaddr_in
bindAddress
;
TRANSMIT_FILE_BUFFERS
buffers
;
SOCKET
client
,
server
,
dest
;
DWORD
num_bytes
,
err
;
WSAOVERLAPPED
ov
;
char
buf
[
256
];
int
iret
,
len
;
BOOL
bret
;
memset
(
&
ov
,
0
,
sizeof
(
ov
)
);
/* Setup sockets for testing TransmitFile */
client
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
server
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
...
...
@@ -7494,6 +7497,7 @@ static void test_TransmitFile(void)
skip
(
"Unable to open a file to transmit.
\n
"
);
goto
cleanup
;
}
file_size
=
GetFileSize
(
file
,
NULL
);
/* Test TransmitFile with an invalid socket */
bret
=
pTransmitFile
(
INVALID_SOCKET
,
file
,
0
,
0
,
NULL
,
NULL
,
0
);
...
...
@@ -7567,7 +7571,7 @@ static void test_TransmitFile(void)
/* 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
);
compare_file
(
file
,
dest
,
0
);
/* Test TransmitFile with both file and buffer data */
buffers
.
Head
=
&
header_msg
[
0
];
...
...
@@ -7580,7 +7584,81 @@ static void test_TransmitFile(void)
iret
=
recv
(
dest
,
buf
,
sizeof
(
header_msg
)
+
1
,
0
);
ok
(
memcmp
(
buf
,
&
header_msg
[
0
],
sizeof
(
header_msg
)
+
1
)
==
0
,
"TransmitFile header buffer did not match!
\n
"
);
compare_file
(
file
,
dest
);
compare_file
(
file
,
dest
,
0
);
iret
=
recv
(
dest
,
buf
,
sizeof
(
footer_msg
)
+
1
,
0
);
ok
(
memcmp
(
buf
,
&
footer_msg
[
0
],
sizeof
(
footer_msg
)
+
1
)
==
0
,
"TransmitFile footer buffer did not match!
\n
"
);
/* Test overlapped TransmitFile */
ov
.
hEvent
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
ov
.
hEvent
==
INVALID_HANDLE_VALUE
)
{
skip
(
"Could not create event object, some tests will be skipped. errno = %d
\n
"
,
GetLastError
());
goto
cleanup
;
}
SetFilePointer
(
file
,
0
,
NULL
,
FILE_BEGIN
);
bret
=
pTransmitFile
(
client
,
file
,
0
,
0
,
&
ov
,
NULL
,
0
);
err
=
WSAGetLastError
();
ok
(
!
bret
,
"TransmitFile succeeded unexpectedly.
\n
"
);
ok
(
err
==
ERROR_IO_PENDING
,
"TransmitFile triggered unexpected errno (%d != %d)
\n
"
,
err
,
ERROR_IO_PENDING
);
iret
=
WaitForSingleObject
(
ov
.
hEvent
,
2000
);
ok
(
iret
==
WAIT_OBJECT_0
,
"Overlapped TransmitFile failed.
\n
"
);
WSAGetOverlappedResult
(
client
,
&
ov
,
&
total_sent
,
FALSE
,
NULL
);
ok
(
total_sent
==
file_size
,
"Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).
\n
"
,
total_sent
,
file_size
);
compare_file
(
file
,
dest
,
0
);
/* Test overlapped TransmitFile w/ start offset */
ov
.
hEvent
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
ov
.
hEvent
==
INVALID_HANDLE_VALUE
)
{
skip
(
"Could not create event object, some tests will be skipped. errno = %d
\n
"
,
GetLastError
());
goto
cleanup
;
}
SetFilePointer
(
file
,
0
,
NULL
,
FILE_BEGIN
);
ov
.
Offset
=
10
;
bret
=
pTransmitFile
(
client
,
file
,
0
,
0
,
&
ov
,
NULL
,
0
);
err
=
WSAGetLastError
();
ok
(
!
bret
,
"TransmitFile succeeded unexpectedly.
\n
"
);
ok
(
err
==
ERROR_IO_PENDING
,
"TransmitFile triggered unexpected errno (%d != %d)
\n
"
,
err
,
ERROR_IO_PENDING
);
iret
=
WaitForSingleObject
(
ov
.
hEvent
,
2000
);
ok
(
iret
==
WAIT_OBJECT_0
,
"Overlapped TransmitFile failed.
\n
"
);
WSAGetOverlappedResult
(
client
,
&
ov
,
&
total_sent
,
FALSE
,
NULL
);
ok
(
total_sent
==
(
file_size
-
ov
.
Offset
),
"Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).
\n
"
,
total_sent
,
file_size
-
ov
.
Offset
);
compare_file
(
file
,
dest
,
ov
.
Offset
);
/* Test overlapped TransmitFile w/ file and buffer data */
ov
.
hEvent
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
ov
.
hEvent
==
INVALID_HANDLE_VALUE
)
{
skip
(
"Could not create event object, some tests will be skipped. errno = %d
\n
"
,
GetLastError
());
goto
cleanup
;
}
buffers
.
Head
=
&
header_msg
[
0
];
buffers
.
HeadLength
=
sizeof
(
header_msg
)
+
1
;
buffers
.
Tail
=
&
footer_msg
[
0
];
buffers
.
TailLength
=
sizeof
(
footer_msg
)
+
1
;
SetFilePointer
(
file
,
0
,
NULL
,
FILE_BEGIN
);
ov
.
Offset
=
0
;
bret
=
pTransmitFile
(
client
,
file
,
0
,
0
,
&
ov
,
&
buffers
,
0
);
err
=
WSAGetLastError
();
ok
(
!
bret
,
"TransmitFile succeeded unexpectedly.
\n
"
);
ok
(
err
==
ERROR_IO_PENDING
,
"TransmitFile triggered unexpected errno (%d != %d)
\n
"
,
err
,
ERROR_IO_PENDING
);
iret
=
WaitForSingleObject
(
ov
.
hEvent
,
2000
);
ok
(
iret
==
WAIT_OBJECT_0
,
"Overlapped TransmitFile failed.
\n
"
);
WSAGetOverlappedResult
(
client
,
&
ov
,
&
total_sent
,
FALSE
,
NULL
);
ok
(
total_sent
==
(
file_size
+
buffers
.
HeadLength
+
buffers
.
TailLength
),
"Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).
\n
"
,
total_sent
,
file_size
+
buffers
.
HeadLength
+
buffers
.
TailLength
);
iret
=
recv
(
dest
,
buf
,
sizeof
(
header_msg
)
+
1
,
0
);
ok
(
memcmp
(
buf
,
&
header_msg
[
0
],
sizeof
(
header_msg
)
+
1
)
==
0
,
"TransmitFile header buffer did not match!
\n
"
);
compare_file
(
file
,
dest
,
0
);
iret
=
recv
(
dest
,
buf
,
sizeof
(
footer_msg
)
+
1
,
0
);
ok
(
memcmp
(
buf
,
&
footer_msg
[
0
],
sizeof
(
footer_msg
)
+
1
)
==
0
,
"TransmitFile footer buffer did not match!
\n
"
);
...
...
@@ -7595,6 +7673,7 @@ static void test_TransmitFile(void)
cleanup:
CloseHandle
(
file
);
CloseHandle
(
ov
.
hEvent
);
closesocket
(
client
);
closesocket
(
server
);
}
...
...
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