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
0a689219
Commit
0a689219
authored
May 27, 2021
by
Zebediah Figura
Committed by
Alexandre Julliard
May 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Introduce IOCTL_AFD_WINE_TRANSMIT.
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
d8968b95
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
224 additions
and
0 deletions
+224
-0
socket.c
dlls/ntdll/unix/socket.c
+212
-0
afd.h
include/wine/afd.h
+12
-0
No files found.
dlls/ntdll/unix/socket.c
View file @
0a689219
...
...
@@ -71,6 +71,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
winsock
);
#define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
static
async_data_t
server_async
(
HANDLE
handle
,
struct
async_fileio
*
user
,
HANDLE
event
,
PIO_APC_ROUTINE
apc
,
void
*
apc_context
,
IO_STATUS_BLOCK
*
io
)
{
...
...
@@ -126,6 +128,23 @@ struct async_send_ioctl
struct
iovec
iov
[
1
];
};
struct
async_transmit_ioctl
{
struct
async_fileio
io
;
HANDLE
file
;
char
*
buffer
;
unsigned
int
buffer_size
;
/* allocated size of buffer */
unsigned
int
read_len
;
/* amount of valid data currently in the buffer */
unsigned
int
head_cursor
;
/* amount of header data already sent */
unsigned
int
file_cursor
;
/* amount of file data already sent */
unsigned
int
buffer_cursor
;
/* amount of data currently in the buffer already sent */
unsigned
int
tail_cursor
;
/* amount of tail data already sent */
unsigned
int
file_len
;
/* total file length to send */
DWORD
flags
;
TRANSMIT_FILE_BUFFERS
buffers
;
LARGE_INTEGER
offset
;
};
static
NTSTATUS
sock_errno_to_status
(
int
err
)
{
switch
(
err
)
...
...
@@ -921,6 +940,182 @@ static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
return
status
;
}
static
ssize_t
do_send
(
int
fd
,
const
void
*
buffer
,
size_t
len
,
int
flags
)
{
ssize_t
ret
;
while
((
ret
=
send
(
fd
,
buffer
,
len
,
flags
))
<
0
&&
errno
==
EINTR
);
if
(
ret
<
0
&&
errno
!=
EWOULDBLOCK
)
WARN
(
"send: %s
\n
"
,
strerror
(
errno
)
);
return
ret
;
}
static
NTSTATUS
try_transmit
(
int
sock_fd
,
int
file_fd
,
struct
async_transmit_ioctl
*
async
)
{
ssize_t
ret
;
while
(
async
->
head_cursor
<
async
->
buffers
.
HeadLength
)
{
TRACE
(
"sending %u bytes of header data
\n
"
,
async
->
buffers
.
HeadLength
-
async
->
head_cursor
);
ret
=
do_send
(
sock_fd
,
(
char
*
)
async
->
buffers
.
Head
+
async
->
head_cursor
,
async
->
buffers
.
HeadLength
-
async
->
head_cursor
,
0
);
if
(
ret
<
0
)
return
sock_errno_to_status
(
errno
);
TRACE
(
"send returned %zd
\n
"
,
ret
);
async
->
head_cursor
+=
ret
;
}
while
(
async
->
buffer_cursor
<
async
->
read_len
)
{
TRACE
(
"sending %u bytes of file data
\n
"
,
async
->
read_len
-
async
->
buffer_cursor
);
ret
=
do_send
(
sock_fd
,
async
->
buffer
+
async
->
buffer_cursor
,
async
->
read_len
-
async
->
buffer_cursor
,
0
);
if
(
ret
<
0
)
return
sock_errno_to_status
(
errno
);
TRACE
(
"send returned %zd
\n
"
,
ret
);
async
->
buffer_cursor
+=
ret
;
async
->
file_cursor
+=
ret
;
}
if
(
async
->
file
&&
async
->
buffer_cursor
==
async
->
read_len
)
{
unsigned
int
read_size
=
async
->
buffer_size
;
if
(
async
->
file_len
)
read_size
=
min
(
read_size
,
async
->
file_len
-
async
->
file_cursor
);
TRACE
(
"reading %u bytes of file data
\n
"
,
read_size
);
do
{
if
(
async
->
offset
.
QuadPart
==
FILE_USE_FILE_POINTER_POSITION
)
ret
=
read
(
file_fd
,
async
->
buffer
,
read_size
);
else
ret
=
pread
(
file_fd
,
async
->
buffer
,
read_size
,
async
->
offset
.
QuadPart
);
}
while
(
ret
<
0
&&
errno
==
EINTR
);
if
(
ret
<
0
)
return
errno_to_status
(
errno
);
TRACE
(
"read returned %zd
\n
"
,
ret
);
async
->
read_len
=
ret
;
async
->
buffer_cursor
=
0
;
if
(
async
->
offset
.
QuadPart
!=
FILE_USE_FILE_POINTER_POSITION
)
async
->
offset
.
QuadPart
+=
ret
;
if
(
ret
<
read_size
||
(
async
->
file_len
&&
async
->
file_cursor
==
async
->
file_len
))
async
->
file
=
NULL
;
return
STATUS_PENDING
;
/* still more data to send */
}
while
(
async
->
tail_cursor
<
async
->
buffers
.
TailLength
)
{
TRACE
(
"sending %u bytes of tail data
\n
"
,
async
->
buffers
.
TailLength
-
async
->
tail_cursor
);
ret
=
do_send
(
sock_fd
,
(
char
*
)
async
->
buffers
.
Tail
+
async
->
tail_cursor
,
async
->
buffers
.
TailLength
-
async
->
tail_cursor
,
0
);
if
(
ret
<
0
)
return
sock_errno_to_status
(
errno
);
TRACE
(
"send returned %zd
\n
"
,
ret
);
async
->
tail_cursor
+=
ret
;
}
return
STATUS_SUCCESS
;
}
static
NTSTATUS
async_transmit_proc
(
void
*
user
,
IO_STATUS_BLOCK
*
io
,
NTSTATUS
status
)
{
int
sock_fd
,
file_fd
=
-
1
,
sock_needs_close
=
FALSE
,
file_needs_close
=
FALSE
;
struct
async_transmit_ioctl
*
async
=
user
;
TRACE
(
"%#x
\n
"
,
status
);
if
(
status
==
STATUS_ALERTED
)
{
if
((
status
=
server_get_unix_fd
(
async
->
io
.
handle
,
0
,
&
sock_fd
,
&
sock_needs_close
,
NULL
,
NULL
)))
return
status
;
if
(
async
->
file
&&
(
status
=
server_get_unix_fd
(
async
->
file
,
0
,
&
file_fd
,
&
file_needs_close
,
NULL
,
NULL
)))
{
if
(
sock_needs_close
)
close
(
sock_fd
);
return
status
;
}
status
=
try_transmit
(
sock_fd
,
file_fd
,
async
);
TRACE
(
"got status %#x
\n
"
,
status
);
if
(
status
==
STATUS_DEVICE_NOT_READY
)
status
=
STATUS_PENDING
;
if
(
sock_needs_close
)
close
(
sock_fd
);
if
(
file_needs_close
)
close
(
file_fd
);
}
if
(
status
!=
STATUS_PENDING
)
{
io
->
Status
=
status
;
io
->
Information
=
async
->
head_cursor
+
async
->
file_cursor
+
async
->
tail_cursor
;
release_fileio
(
&
async
->
io
);
}
return
status
;
}
static
NTSTATUS
sock_transmit
(
HANDLE
handle
,
HANDLE
event
,
PIO_APC_ROUTINE
apc
,
void
*
apc_user
,
IO_STATUS_BLOCK
*
io
,
int
fd
,
const
struct
afd_transmit_params
*
params
)
{
int
file_fd
,
file_needs_close
=
FALSE
;
struct
async_transmit_ioctl
*
async
;
enum
server_fd_type
file_type
;
union
unix_sockaddr
addr
;
socklen_t
addr_len
;
HANDLE
wait_handle
;
NTSTATUS
status
;
ULONG
options
;
addr_len
=
sizeof
(
addr
);
if
(
getpeername
(
fd
,
&
addr
.
addr
,
&
addr_len
)
!=
0
)
return
STATUS_INVALID_CONNECTION
;
if
(
params
->
file
)
{
if
((
status
=
server_get_unix_fd
(
params
->
file
,
0
,
&
file_fd
,
&
file_needs_close
,
&
file_type
,
NULL
)))
return
status
;
if
(
file_needs_close
)
close
(
file_fd
);
if
(
file_type
!=
FD_TYPE_FILE
)
{
FIXME
(
"unsupported file type %#x
\n
"
,
file_type
);
return
STATUS_NOT_IMPLEMENTED
;
}
}
if
(
!
(
async
=
(
struct
async_transmit_ioctl
*
)
alloc_fileio
(
sizeof
(
*
async
),
async_transmit_proc
,
handle
)))
return
STATUS_NO_MEMORY
;
async
->
file
=
params
->
file
;
async
->
buffer_size
=
params
->
buffer_size
?
params
->
buffer_size
:
65536
;
if
(
!
(
async
->
buffer
=
malloc
(
async
->
buffer_size
)))
{
release_fileio
(
&
async
->
io
);
return
STATUS_NO_MEMORY
;
}
async
->
read_len
=
0
;
async
->
head_cursor
=
0
;
async
->
file_cursor
=
0
;
async
->
buffer_cursor
=
0
;
async
->
tail_cursor
=
0
;
async
->
file_len
=
params
->
file_len
;
async
->
flags
=
params
->
flags
;
async
->
buffers
=
params
->
buffers
;
async
->
offset
=
params
->
offset
;
SERVER_START_REQ
(
send_socket
)
{
req
->
status
=
STATUS_PENDING
;
req
->
total
=
0
;
req
->
async
=
server_async
(
handle
,
&
async
->
io
,
event
,
apc
,
apc_user
,
io
);
status
=
wine_server_call
(
req
);
wait_handle
=
wine_server_ptr_handle
(
reply
->
wait
);
options
=
reply
->
options
;
}
SERVER_END_REQ
;
if
(
status
!=
STATUS_PENDING
)
release_fileio
(
&
async
->
io
);
if
(
wait_handle
)
status
=
wait_async
(
wait_handle
,
options
&
FILE_SYNCHRONOUS_IO_ALERT
);
return
status
;
}
NTSTATUS
sock_ioctl
(
HANDLE
handle
,
HANDLE
event
,
PIO_APC_ROUTINE
apc
,
void
*
apc_user
,
IO_STATUS_BLOCK
*
io
,
ULONG
code
,
void
*
in_buffer
,
ULONG
in_size
,
void
*
out_buffer
,
ULONG
out_size
)
{
...
...
@@ -1037,6 +1232,23 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
break
;
}
case
IOCTL_AFD_WINE_TRANSMIT
:
{
const
struct
afd_transmit_params
*
params
=
in_buffer
;
if
((
status
=
server_get_unix_fd
(
handle
,
0
,
&
fd
,
&
needs_close
,
NULL
,
NULL
)))
return
status
;
if
(
in_size
<
sizeof
(
*
params
))
{
return
STATUS_BUFFER_TOO_SMALL
;
break
;
}
status
=
sock_transmit
(
handle
,
event
,
apc
,
apc_user
,
io
,
fd
,
params
);
break
;
}
case
IOCTL_AFD_POLL
:
status
=
sock_poll
(
handle
,
event
,
apc
,
apc_user
,
io
,
in_buffer
,
in_size
,
out_buffer
,
out_size
);
break
;
...
...
include/wine/afd.h
View file @
0a689219
...
...
@@ -23,6 +23,7 @@
#include <winternl.h>
#include <winioctl.h>
#include <mswsock.h>
#include "wine/server_protocol.h"
#ifdef USE_WS_PREFIX
...
...
@@ -93,6 +94,7 @@ struct afd_poll_params
#define IOCTL_AFD_WINE_SHUTDOWN CTL_CODE(FILE_DEVICE_NETWORK, 204, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_RECVMSG CTL_CODE(FILE_DEVICE_NETWORK, 205, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_SENDMSG CTL_CODE(FILE_DEVICE_NETWORK, 206, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_TRANSMIT CTL_CODE(FILE_DEVICE_NETWORK, 207, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, FILE_ANY_ACCESS)
...
...
@@ -137,4 +139,14 @@ struct afd_sendmsg_params
const
WSABUF
*
buffers
;
};
struct
afd_transmit_params
{
HANDLE
file
;
DWORD
file_len
;
DWORD
buffer_size
;
LARGE_INTEGER
offset
;
TRANSMIT_FILE_BUFFERS
buffers
;
DWORD
flags
;
};
#endif
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