server: Make it possible for WaitCommEvent to detect recursive requests.
This commit is contained in:
parent
318931bd46
commit
a890d0f030
|
@ -966,7 +966,6 @@ static void test_waittxempty(void)
|
|||
SetLastError(0xdeadbeef);
|
||||
res = WaitCommEvent(hcom, &evtmask, &ovl_wait2);
|
||||
ok(!res, "WaitCommEvent should fail if there is a pending wait\n");
|
||||
todo_wine
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
CloseHandle(ovl_wait2.hEvent);
|
||||
|
||||
|
|
|
@ -381,7 +381,21 @@ static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st)
|
|||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie, DWORD *pending_write)
|
||||
static void stop_waiting( HANDLE handle )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
SERVER_START_REQ( set_serial_info )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->flags = SERIALINFO_PENDING_WAIT;
|
||||
if ((status = wine_server_call( req )))
|
||||
ERR("failed to clear waiting state: %#x\n", status);
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie, DWORD *pending_write, BOOL start_wait)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
|
@ -389,6 +403,7 @@ static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie, DWORD
|
|||
{
|
||||
req->handle = wine_server_obj_handle( hDevice );
|
||||
req->flags = pending_write ? SERIALINFO_PENDING_WRITE : 0;
|
||||
if (start_wait) req->flags |= SERIALINFO_PENDING_WAIT;
|
||||
if (!(status = wine_server_call( req )))
|
||||
{
|
||||
*mask = reply->eventmask;
|
||||
|
@ -940,7 +955,7 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
|
|||
&new_irq_info, &commio->irq_info,
|
||||
new_mstat, commio->mstat, commio->pending_write);
|
||||
if (*commio->events) break;
|
||||
get_wait_mask(commio->hDevice, &dummy, &cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL);
|
||||
get_wait_mask(commio->hDevice, &dummy, &cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL, FALSE);
|
||||
if (commio->cookie != cookie)
|
||||
{
|
||||
*commio->events = 0;
|
||||
|
@ -959,6 +974,7 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
|
|||
else
|
||||
commio->iosb->u.Status = STATUS_CANCELLED;
|
||||
}
|
||||
stop_waiting(commio->hDevice);
|
||||
if (commio->hEvent) NtSetEvent(commio->hEvent, NULL);
|
||||
RtlFreeHeap(GetProcessHeap(), 0, commio);
|
||||
return 0;
|
||||
|
@ -980,7 +996,12 @@ static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, PIO_STATUS_BLOCK
|
|||
commio->iosb = piosb;
|
||||
commio->hEvent = hEvent;
|
||||
commio->pending_write = 0;
|
||||
get_wait_mask(commio->hDevice, &commio->evtmask, &commio->cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL);
|
||||
status = get_wait_mask(commio->hDevice, &commio->evtmask, &commio->cookie, (commio->evtmask & EV_TXEMPTY) ? &commio->pending_write : NULL, TRUE);
|
||||
if (status)
|
||||
{
|
||||
RtlFreeHeap(GetProcessHeap(), 0, commio);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* We may never return, if some capabilities miss
|
||||
* Return error in that case
|
||||
|
@ -1045,6 +1066,7 @@ error_caps:
|
|||
status = STATUS_INVALID_PARAMETER;
|
||||
#endif
|
||||
out_now:
|
||||
stop_waiting(commio->hDevice);
|
||||
RtlFreeHeap(GetProcessHeap(), 0, commio);
|
||||
return status;
|
||||
}
|
||||
|
@ -1175,7 +1197,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
|
|||
case IOCTL_SERIAL_GET_WAIT_MASK:
|
||||
if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
|
||||
{
|
||||
if (!(status = get_wait_mask(hDevice, lpOutBuffer, NULL, NULL)))
|
||||
if (!(status = get_wait_mask(hDevice, lpOutBuffer, NULL, NULL, FALSE)))
|
||||
sz = sizeof(DWORD);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -3083,6 +3083,7 @@ struct set_serial_info_reply
|
|||
#define SERIALINFO_SET_TIMEOUTS 0x01
|
||||
#define SERIALINFO_SET_MASK 0x02
|
||||
#define SERIALINFO_PENDING_WRITE 0x04
|
||||
#define SERIALINFO_PENDING_WAIT 0x08
|
||||
|
||||
|
||||
|
||||
|
@ -5845,6 +5846,6 @@ union generic_reply
|
|||
struct set_suspend_context_reply set_suspend_context_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 451
|
||||
#define SERVER_PROTOCOL_VERSION 452
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -2239,6 +2239,7 @@ enum message_type
|
|||
#define SERIALINFO_SET_TIMEOUTS 0x01
|
||||
#define SERIALINFO_SET_MASK 0x02
|
||||
#define SERIALINFO_PENDING_WRITE 0x04
|
||||
#define SERIALINFO_PENDING_WAIT 0x08
|
||||
|
||||
|
||||
/* Create an async I/O */
|
||||
|
|
|
@ -77,7 +77,8 @@ struct serial
|
|||
|
||||
unsigned int eventmask;
|
||||
unsigned int generation; /* event mask change counter */
|
||||
unsigned int pending_write;
|
||||
unsigned int pending_write : 1;
|
||||
unsigned int pending_wait : 1;
|
||||
|
||||
struct termios original;
|
||||
|
||||
|
@ -139,6 +140,7 @@ struct object *create_serial( struct fd *fd )
|
|||
serial->eventmask = 0;
|
||||
serial->generation = 0;
|
||||
serial->pending_write = 0;
|
||||
serial->pending_wait = 0;
|
||||
serial->fd = (struct fd *)grab_object( fd );
|
||||
set_fd_user( fd, &serial_fd_ops, &serial->obj );
|
||||
return &serial->obj;
|
||||
|
@ -205,6 +207,17 @@ DECL_HANDLER(get_serial_info)
|
|||
|
||||
if ((serial = get_serial_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
if (req->flags & SERIALINFO_PENDING_WAIT)
|
||||
{
|
||||
if (serial->pending_wait)
|
||||
{
|
||||
release_object( serial );
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
serial->pending_wait = 1;
|
||||
}
|
||||
|
||||
/* timeouts */
|
||||
reply->readinterval = serial->readinterval;
|
||||
reply->readconst = serial->readconst;
|
||||
|
@ -231,6 +244,17 @@ DECL_HANDLER(set_serial_info)
|
|||
|
||||
if ((serial = get_serial_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
if (req->flags & SERIALINFO_PENDING_WAIT)
|
||||
{
|
||||
if (!serial->pending_wait)
|
||||
{
|
||||
release_object( serial );
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
serial->pending_wait = 0;
|
||||
}
|
||||
|
||||
/* timeouts */
|
||||
if (req->flags & SERIALINFO_SET_TIMEOUTS)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue