- better support for non-blocking COMM and socket read/writes:
+ added necessary semantics to fd flags + no longer uses fd type (but fd flags) read/write semantic behavior - fixed socket code to use the proper manifest constants - fixes for kernel32.GetOverlappedResult without hEvent set - in ntdll.Nt{Read|Write}File + always reset the event + added support for longlong offsets + better object disposal in error handling code paths
This commit is contained in:
parent
00acb5f719
commit
1ffddb4d0c
|
@ -497,56 +497,64 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
|
||||||
BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
|
BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
|
||||||
LPDWORD lpTransferred, BOOL bWait)
|
LPDWORD lpTransferred, BOOL bWait)
|
||||||
{
|
{
|
||||||
DWORD r;
|
DWORD r = WAIT_OBJECT_0;
|
||||||
|
|
||||||
TRACE("(%p %p %p %x)\n", hFile, lpOverlapped, lpTransferred, bWait);
|
TRACE( "(%p %p %p %x)\n", hFile, lpOverlapped, lpTransferred, bWait );
|
||||||
|
|
||||||
if (lpOverlapped==NULL)
|
if ( lpOverlapped == NULL )
|
||||||
{
|
{
|
||||||
ERR("lpOverlapped was null\n");
|
ERR("lpOverlapped was null\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!lpOverlapped->hEvent)
|
|
||||||
{
|
|
||||||
ERR("lpOverlapped->hEvent was null\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bWait )
|
if ( bWait )
|
||||||
{
|
{
|
||||||
do {
|
if ( lpOverlapped->hEvent )
|
||||||
TRACE("waiting on %p\n",lpOverlapped);
|
{
|
||||||
r = WaitForSingleObjectEx(lpOverlapped->hEvent, INFINITE, TRUE);
|
do
|
||||||
TRACE("wait on %p returned %ld\n",lpOverlapped,r);
|
{
|
||||||
} while (r==STATUS_USER_APC);
|
TRACE( "waiting on %p\n", lpOverlapped );
|
||||||
|
r = WaitForSingleObjectEx( lpOverlapped->hEvent, INFINITE, TRUE );
|
||||||
|
TRACE( "wait on %p returned %ld\n", lpOverlapped, r );
|
||||||
|
} while ( r == WAIT_IO_COMPLETION );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* busy loop */
|
||||||
|
while ( (volatile DWORD)lpOverlapped->Internal == STATUS_PENDING )
|
||||||
|
Sleep( 10 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( lpOverlapped->Internal == STATUS_PENDING )
|
else if ( lpOverlapped->Internal == STATUS_PENDING )
|
||||||
{
|
{
|
||||||
/* Wait in order to give APCs a chance to run. */
|
/* Wait in order to give APCs a chance to run. */
|
||||||
/* This is cheating, so we must set the event again in case of success -
|
/* This is cheating, so we must set the event again in case of success -
|
||||||
it may be a non-manual reset event. */
|
it may be a non-manual reset event. */
|
||||||
do {
|
do
|
||||||
TRACE("waiting on %p\n",lpOverlapped);
|
{
|
||||||
r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE);
|
TRACE( "waiting on %p\n", lpOverlapped );
|
||||||
TRACE("wait on %p returned %ld\n",lpOverlapped,r);
|
r = WaitForSingleObjectEx( lpOverlapped->hEvent, 0, TRUE );
|
||||||
} while (r==STATUS_USER_APC);
|
TRACE( "wait on %p returned %ld\n", lpOverlapped, r );
|
||||||
if ( r == WAIT_OBJECT_0 )
|
} while ( r == WAIT_IO_COMPLETION );
|
||||||
NtSetEvent ( lpOverlapped->hEvent, NULL );
|
if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
|
||||||
|
NtSetEvent( lpOverlapped->hEvent, NULL );
|
||||||
}
|
}
|
||||||
|
if ( r == WAIT_FAILED )
|
||||||
if(lpTransferred)
|
{
|
||||||
*lpTransferred = lpOverlapped->InternalHigh;
|
ERR("wait operation failed\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (lpTransferred) *lpTransferred = lpOverlapped->InternalHigh;
|
||||||
|
|
||||||
switch ( lpOverlapped->Internal )
|
switch ( lpOverlapped->Internal )
|
||||||
{
|
{
|
||||||
case STATUS_SUCCESS:
|
case STATUS_SUCCESS:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case STATUS_PENDING:
|
case STATUS_PENDING:
|
||||||
SetLastError ( ERROR_IO_INCOMPLETE );
|
SetLastError( ERROR_IO_INCOMPLETE );
|
||||||
if ( bWait ) ERR ("PENDING status after waiting!\n");
|
if ( bWait ) ERR("PENDING status after waiting!\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
default:
|
default:
|
||||||
SetLastError ( RtlNtStatusToDosError ( lpOverlapped->Internal ) );
|
SetLastError( RtlNtStatusToDosError( lpOverlapped->Internal ) );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,7 +648,6 @@ HFILE WINAPI _lopen( LPCSTR path, INT mode )
|
||||||
return (HFILE)create_file_OF( path, mode & ~OF_CREATE );
|
return (HFILE)create_file_OF( path, mode & ~OF_CREATE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* _lread (KERNEL32.@)
|
* _lread (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -247,13 +247,13 @@ typedef struct async_fileio
|
||||||
void* apc_user;
|
void* apc_user;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
unsigned long offset;
|
off_t offset;
|
||||||
enum fd_type fd_type;
|
BOOL avail_mode;
|
||||||
} async_fileio;
|
} async_fileio;
|
||||||
|
|
||||||
static DWORD fileio_get_async_count(const struct async_private *ovp)
|
static DWORD fileio_get_async_count(const struct async_private *ovp)
|
||||||
{
|
{
|
||||||
async_fileio *fileio = (async_fileio*) ovp;
|
const async_fileio *fileio = (const async_fileio*) ovp;
|
||||||
|
|
||||||
if (fileio->count < fileio->async.iosb->Information)
|
if (fileio->count < fileio->async.iosb->Information)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -334,7 +334,7 @@ static void FILE_AsyncReadService(async_private *ovp)
|
||||||
|
|
||||||
/* check to see if the data is ready (non-blocking) */
|
/* check to see if the data is ready (non-blocking) */
|
||||||
|
|
||||||
if ( fileio->fd_type == FD_TYPE_SOCKET )
|
if ( fileio->avail_mode )
|
||||||
result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
|
result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -363,14 +363,15 @@ static void FILE_AsyncReadService(async_private *ovp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("status before: %s\n", (io_status->u.Status == STATUS_SUCCESS) ? "success" : "pending");
|
||||||
io_status->Information += result;
|
io_status->Information += result;
|
||||||
if (io_status->Information >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
|
if (io_status->Information >= fileio->count || fileio->avail_mode )
|
||||||
io_status->u.Status = STATUS_SUCCESS;
|
io_status->u.Status = STATUS_SUCCESS;
|
||||||
else
|
else
|
||||||
io_status->u.Status = STATUS_PENDING;
|
io_status->u.Status = STATUS_PENDING;
|
||||||
|
|
||||||
TRACE("read %d more bytes %ld/%d so far\n",
|
TRACE("read %d more bytes %ld/%d so far (%s)\n",
|
||||||
result, io_status->Information, fileio->count);
|
result, io_status->Information, fileio->count, (io_status->u.Status == STATUS_SUCCESS) ? "success" : "pending");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -402,13 +403,12 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
PLARGE_INTEGER offset, PULONG key)
|
PLARGE_INTEGER offset, PULONG key)
|
||||||
{
|
{
|
||||||
int unix_handle, flags;
|
int unix_handle, flags;
|
||||||
enum fd_type type;
|
|
||||||
|
|
||||||
TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
|
TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
|
||||||
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
||||||
|
|
||||||
io_status->Information = 0;
|
io_status->Information = 0;
|
||||||
io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, &type, &flags );
|
io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_READ, &unix_handle, NULL, &flags );
|
||||||
if (io_status->u.Status) return io_status->u.Status;
|
if (io_status->u.Status) return io_status->u.Status;
|
||||||
|
|
||||||
if (flags & FD_FLAG_RECV_SHUTDOWN)
|
if (flags & FD_FLAG_RECV_SHUTDOWN)
|
||||||
|
@ -442,6 +442,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
|
if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
|
||||||
{
|
{
|
||||||
wine_server_release_fd( hFile, unix_handle );
|
wine_server_release_fd( hFile, unix_handle );
|
||||||
|
if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
|
||||||
return STATUS_NO_MEMORY;
|
return STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
|
ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
|
||||||
|
@ -456,18 +457,24 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
ovp->offset = 0;
|
ovp->offset = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ovp->offset = offset->u.LowPart;
|
ovp->offset = offset->QuadPart;
|
||||||
if (offset->u.HighPart) FIXME("NIY-high part\n");
|
if (offset->u.HighPart && ovp->offset == offset->u.LowPart)
|
||||||
|
FIXME("High part of offset is lost\n");
|
||||||
}
|
}
|
||||||
ovp->apc = apc;
|
ovp->apc = apc;
|
||||||
ovp->apc_user = apc_user;
|
ovp->apc_user = apc_user;
|
||||||
ovp->buffer = buffer;
|
ovp->buffer = buffer;
|
||||||
ovp->fd_type = type;
|
ovp->avail_mode = (flags & FD_FLAG_AVAILABLE);
|
||||||
|
NtResetEvent(hEvent, NULL);
|
||||||
|
|
||||||
io_status->Information = 0;
|
|
||||||
ret = register_new_async(&ovp->async);
|
ret = register_new_async(&ovp->async);
|
||||||
if (ret != STATUS_SUCCESS)
|
if (ret != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
wine_server_release_fd( hFile, unix_handle );
|
||||||
|
if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
|
||||||
|
RtlFreeHeap(GetProcessHeap(), 0, ovp);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
if (flags & FD_FLAG_TIMEOUT)
|
if (flags & FD_FLAG_TIMEOUT)
|
||||||
{
|
{
|
||||||
NtWaitForSingleObject(hEvent, TRUE, NULL);
|
NtWaitForSingleObject(hEvent, TRUE, NULL);
|
||||||
|
@ -480,6 +487,15 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
|
||||||
/* let some APC be run, this will read some already pending data */
|
/* let some APC be run, this will read some already pending data */
|
||||||
timeout.u.LowPart = timeout.u.HighPart = 0;
|
timeout.u.LowPart = timeout.u.HighPart = 0;
|
||||||
NtDelayExecution( TRUE, &timeout );
|
NtDelayExecution( TRUE, &timeout );
|
||||||
|
/* if we only have to read the available data, and none is available,
|
||||||
|
* simply cancel the request. If data was available, it has been read
|
||||||
|
* while in by previous call (NtDelayExecution)
|
||||||
|
*/
|
||||||
|
if ((flags & FD_FLAG_AVAILABLE) && io_status->u.Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
io_status->u.Status = STATUS_SUCCESS;
|
||||||
|
register_old_async(&ovp->async);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return io_status->u.Status;
|
return io_status->u.Status;
|
||||||
}
|
}
|
||||||
|
@ -526,7 +542,7 @@ static void FILE_AsyncWriteService(struct async_private *ovp)
|
||||||
|
|
||||||
/* write some data (non-blocking) */
|
/* write some data (non-blocking) */
|
||||||
|
|
||||||
if ( fileio->fd_type == FD_TYPE_SOCKET )
|
if ( fileio->avail_mode )
|
||||||
result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
|
result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -583,16 +599,12 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
||||||
PLARGE_INTEGER offset, PULONG key)
|
PLARGE_INTEGER offset, PULONG key)
|
||||||
{
|
{
|
||||||
int unix_handle, flags;
|
int unix_handle, flags;
|
||||||
enum fd_type type;
|
|
||||||
|
|
||||||
TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
|
TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p)!\n",
|
||||||
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
||||||
|
|
||||||
TRACE("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
|
|
||||||
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
|
|
||||||
|
|
||||||
io_status->Information = 0;
|
io_status->Information = 0;
|
||||||
io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, &type, &flags );
|
io_status->u.Status = wine_server_handle_to_fd( hFile, GENERIC_WRITE, &unix_handle, NULL, &flags );
|
||||||
if (io_status->u.Status) return io_status->u.Status;
|
if (io_status->u.Status) return io_status->u.Status;
|
||||||
|
|
||||||
if (flags & FD_FLAG_SEND_SHUTDOWN)
|
if (flags & FD_FLAG_SEND_SHUTDOWN)
|
||||||
|
@ -620,15 +632,17 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
|
||||||
ovp->async.iosb = io_status;
|
ovp->async.iosb = io_status;
|
||||||
ovp->count = length;
|
ovp->count = length;
|
||||||
if (offset) {
|
if (offset) {
|
||||||
ovp->offset = offset->u.LowPart;
|
ovp->offset = offset->QuadPart;
|
||||||
if (offset->u.HighPart) FIXME("NIY-high part\n");
|
if (offset->u.HighPart && ovp->offset == offset->u.LowPart)
|
||||||
|
FIXME("High part of offset is lost\n");
|
||||||
} else {
|
} else {
|
||||||
ovp->offset = 0;
|
ovp->offset = 0;
|
||||||
}
|
}
|
||||||
ovp->apc = apc;
|
ovp->apc = apc;
|
||||||
ovp->apc_user = apc_user;
|
ovp->apc_user = apc_user;
|
||||||
ovp->buffer = (void*)buffer;
|
ovp->buffer = (void*)buffer;
|
||||||
ovp->fd_type = type;
|
ovp->avail_mode = (flags & FD_FLAG_AVAILABLE);
|
||||||
|
NtResetEvent(hEvent, NULL);
|
||||||
|
|
||||||
io_status->Information = 0;
|
io_status->Information = 0;
|
||||||
ret = register_new_async(&ovp->async);
|
ret = register_new_async(&ovp->async);
|
||||||
|
|
|
@ -111,8 +111,10 @@ inline static NTSTATUS __register_async( async_private *ovp, const DWORD status
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define register_old_async(ovp) \
|
inline static NTSTATUS register_old_async( async_private *ovp )
|
||||||
__register_async(ovp, ovp->iosb->u.Status);
|
{
|
||||||
|
return __register_async(ovp, ovp->iosb->u.Status);
|
||||||
|
}
|
||||||
|
|
||||||
inline static NTSTATUS register_new_async( async_private *ovp )
|
inline static NTSTATUS register_new_async( async_private *ovp )
|
||||||
{
|
{
|
||||||
|
|
|
@ -805,6 +805,8 @@ enum fd_type
|
||||||
#define FD_FLAG_TIMEOUT 0x02
|
#define FD_FLAG_TIMEOUT 0x02
|
||||||
#define FD_FLAG_RECV_SHUTDOWN 0x04
|
#define FD_FLAG_RECV_SHUTDOWN 0x04
|
||||||
#define FD_FLAG_SEND_SHUTDOWN 0x08
|
#define FD_FLAG_SEND_SHUTDOWN 0x08
|
||||||
|
#define FD_FLAG_AVAILABLE 0x10 /* in overlap read/write operation,
|
||||||
|
* only handle available data (don't wait) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3647,6 +3649,6 @@ union generic_reply
|
||||||
struct set_global_windows_reply set_global_windows_reply;
|
struct set_global_windows_reply set_global_windows_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 147
|
#define SERVER_PROTOCOL_VERSION 148
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -612,10 +612,12 @@ enum fd_type
|
||||||
FD_TYPE_DEFAULT,
|
FD_TYPE_DEFAULT,
|
||||||
FD_TYPE_SOCKET
|
FD_TYPE_SOCKET
|
||||||
};
|
};
|
||||||
#define FD_FLAG_OVERLAPPED 0x01
|
#define FD_FLAG_OVERLAPPED 0x01 /* fd opened in overlapped mode */
|
||||||
#define FD_FLAG_TIMEOUT 0x02
|
#define FD_FLAG_TIMEOUT 0x02 /* read/write is synchronous */
|
||||||
#define FD_FLAG_RECV_SHUTDOWN 0x04
|
#define FD_FLAG_RECV_SHUTDOWN 0x04
|
||||||
#define FD_FLAG_SEND_SHUTDOWN 0x08
|
#define FD_FLAG_SEND_SHUTDOWN 0x08
|
||||||
|
#define FD_FLAG_AVAILABLE 0x10 /* in overlap read/write operation,
|
||||||
|
* only handle available data (don't wait) */
|
||||||
|
|
||||||
|
|
||||||
/* Flush a file buffers */
|
/* Flush a file buffers */
|
||||||
|
|
|
@ -209,9 +209,12 @@ static int serial_get_info( struct fd *fd, int *flags )
|
||||||
*flags = 0;
|
*flags = 0;
|
||||||
if (!(serial->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
|
if (!(serial->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
|
||||||
*flags |= FD_FLAG_OVERLAPPED;
|
*flags |= FD_FLAG_OVERLAPPED;
|
||||||
else if(!((serial->readinterval == MAXDWORD) &&
|
else if (!(serial->readinterval == MAXDWORD &&
|
||||||
(serial->readmult == 0) && (serial->readconst == 0)) )
|
serial->readmult == 0 && serial->readconst == 0))
|
||||||
*flags |= FD_FLAG_TIMEOUT;
|
*flags |= FD_FLAG_TIMEOUT;
|
||||||
|
if (serial->readinterval == MAXDWORD &&
|
||||||
|
serial->readmult == 0 && serial->readconst == 0)
|
||||||
|
*flags |= FD_FLAG_AVAILABLE;
|
||||||
|
|
||||||
return FD_TYPE_DEFAULT;
|
return FD_TYPE_DEFAULT;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +295,7 @@ static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, in
|
||||||
else if ( async ) destroy_async ( async );
|
else if ( async ) destroy_async ( async );
|
||||||
else set_error ( STATUS_INVALID_PARAMETER );
|
else set_error ( STATUS_INVALID_PARAMETER );
|
||||||
|
|
||||||
set_fd_events ( fd, serial_get_poll_events( fd ));
|
set_fd_events ( fd, serial_get_poll_events( fd ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_flush( struct fd *fd, struct event **event )
|
static int serial_flush( struct fd *fd, struct event **event )
|
||||||
|
|
|
@ -234,7 +234,7 @@ static void sock_wake_up( struct sock *sock, int pollev )
|
||||||
int i;
|
int i;
|
||||||
int async_active = 0;
|
int async_active = 0;
|
||||||
|
|
||||||
if ( sock->flags & FD_FLAG_OVERLAPPED )
|
if ( sock->flags & WSA_FLAG_OVERLAPPED )
|
||||||
{
|
{
|
||||||
if( pollev & (POLLIN|POLLPRI) && IS_READY( sock->read_q ) )
|
if( pollev & (POLLIN|POLLPRI) && IS_READY( sock->read_q ) )
|
||||||
{
|
{
|
||||||
|
@ -425,7 +425,7 @@ static void sock_poll_event( struct fd *fd, int event )
|
||||||
sock_reselect( sock );
|
sock_reselect( sock );
|
||||||
|
|
||||||
/* wake up anyone waiting for whatever just happened */
|
/* wake up anyone waiting for whatever just happened */
|
||||||
if ( sock->pmask & sock->mask || sock->flags & FD_FLAG_OVERLAPPED ) sock_wake_up( sock, event );
|
if ( sock->pmask & sock->mask || sock->flags & WSA_FLAG_OVERLAPPED ) sock_wake_up( sock, event );
|
||||||
|
|
||||||
/* if anyone is stupid enough to wait on the socket object itself,
|
/* if anyone is stupid enough to wait on the socket object itself,
|
||||||
* maybe we should wake them up too, just in case? */
|
* maybe we should wake them up too, just in case? */
|
||||||
|
@ -480,7 +480,7 @@ static int sock_get_info( struct fd *fd, int *flags )
|
||||||
struct sock *sock = get_fd_user( fd );
|
struct sock *sock = get_fd_user( fd );
|
||||||
assert ( sock->obj.ops == &sock_ops );
|
assert ( sock->obj.ops == &sock_ops );
|
||||||
|
|
||||||
*flags = 0;
|
*flags = FD_FLAG_AVAILABLE;
|
||||||
if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
|
if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
|
||||||
if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED )
|
if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue