diff --git a/winpr/libwinpr/comm/comm.h b/winpr/libwinpr/comm/comm.h index b382cdfa7..ac149133e 100644 --- a/winpr/libwinpr/comm/comm.h +++ b/winpr/libwinpr/comm/comm.h @@ -74,8 +74,8 @@ typedef struct winpr_comm WINPR_COMM; void _comm_setRemoteSerialDriver(HANDLE hComm, REMOTE_SERIAL_DRIVER_ID); /* TMP: TODO: move all specific defines and types here? at least SERIAL_EV_* */ -#define SERIAL_EV_FREERDP_STOP 0x4000 /* bit unused by SERIAL_EV_* */ -#define SERIAL_EV_FREERDP_CLOSING 0x8000 /* bit unused by SERIAL_EV_* */ +#define SERIAL_EV_FREERDP_WAITING 0x4000 /* bit unused by SERIAL_EV_* */ +#define SERIAL_EV_FREERDP_STOP 0x8000 /* bit unused by SERIAL_EV_* */ #endif /* _WIN32 */ diff --git a/winpr/libwinpr/comm/comm_serial_sys.c b/winpr/libwinpr/comm/comm_serial_sys.c index 678aa74ee..4df984036 100644 --- a/winpr/libwinpr/comm/comm_serial_sys.c +++ b/winpr/libwinpr/comm/comm_serial_sys.c @@ -1013,14 +1013,27 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask) { ULONG possibleMask; + + /* Stops pending IOCTL_SERIAL_WAIT_ON_MASK + * http://msdn.microsoft.com/en-us/library/ff546805%28v=vs.85%29.aspx + */ + + if (pComm->PendingEvents & SERIAL_EV_FREERDP_WAITING) + { + /* FIXME: any doubt on reading PendingEvents out of a critical section? */ + + EnterCriticalSection(&pComm->EventsLock); + pComm->PendingEvents |= SERIAL_EV_FREERDP_STOP; + LeaveCriticalSection(&pComm->EventsLock); + + /* waiting the end of the pending _wait_on_mask() */ + while (pComm->PendingEvents & SERIAL_EV_FREERDP_WAITING) + Sleep(10); /* 10ms */ + } + /* NB: ensure to leave the critical section before to return */ EnterCriticalSection(&pComm->EventsLock); - if (pComm->PendingEvents & SERIAL_EV_FREERDP_CLOSING) - { - return TRUE; /* returns without complaining */ - } - if (*pWaitMask == 0) { /* clearing pending events */ @@ -1037,11 +1050,6 @@ static BOOL _set_wait_mask(WINPR_COMM *pComm, const ULONG *pWaitMask) pComm->PendingEvents = 0; } - /* Stops pending IOCTL_SERIAL_WAIT_ON_MASK - * http://msdn.microsoft.com/en-us/library/ff546805%28v=vs.85%29.aspx - */ - pComm->PendingEvents |= SERIAL_EV_FREERDP_STOP; - possibleMask = *pWaitMask & _SERIAL_SYS_SUPPORTED_EV_MASK; if (possibleMask != *pWaitMask) @@ -1170,11 +1178,6 @@ static BOOL _get_commstatus(WINPR_COMM *pComm, SERIAL_STATUS *pCommstatus) /* NB: ensure to leave the critical section before to return */ EnterCriticalSection(&pComm->EventsLock); - if (pComm->PendingEvents & SERIAL_EV_FREERDP_CLOSING) - { - return TRUE; /* returns without complaining */ - } - ZeroMemory(pCommstatus, sizeof(SERIAL_STATUS)); ZeroMemory(¤tCounters, sizeof(struct serial_icounter_struct)); @@ -1338,25 +1341,25 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask) { assert(*pOutputMask == 0); - /* UGLY: removes the STOP bit set by an initial _set_wait_mask() */ - pComm->PendingEvents &= ~SERIAL_EV_FREERDP_STOP; + EnterCriticalSection(&pComm->EventsLock); + pComm->PendingEvents |= SERIAL_EV_FREERDP_WAITING; + LeaveCriticalSection(&pComm->EventsLock); + while (TRUE) { /* NB: EventsLock also used by _refresh_PendingEvents() */ if (!_refresh_PendingEvents(pComm)) { + EnterCriticalSection(&pComm->EventsLock); + pComm->PendingEvents &= ~SERIAL_EV_FREERDP_WAITING; + LeaveCriticalSection(&pComm->EventsLock); return FALSE; } /* NB: ensure to leave the critical section before to return */ EnterCriticalSection(&pComm->EventsLock); - if (pComm->PendingEvents & SERIAL_EV_FREERDP_CLOSING) - { - return TRUE; /* returns without complaining */ - } - if (pComm->PendingEvents & SERIAL_EV_FREERDP_STOP) { pComm->PendingEvents &= ~SERIAL_EV_FREERDP_STOP; @@ -1368,6 +1371,7 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask) */ assert(*pOutputMask == 0); + pComm->PendingEvents &= ~SERIAL_EV_FREERDP_WAITING; LeaveCriticalSection(&pComm->EventsLock); return TRUE; } @@ -1391,6 +1395,10 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask) if (*pOutputMask != 0) { /* at least an event occurred */ + + EnterCriticalSection(&pComm->EventsLock); + pComm->PendingEvents &= ~SERIAL_EV_FREERDP_WAITING; + LeaveCriticalSection(&pComm->EventsLock); return TRUE; } @@ -1407,6 +1415,9 @@ static BOOL _wait_on_mask(WINPR_COMM *pComm, ULONG *pOutputMask) } DEBUG_WARN("_wait_on_mask, unexpected return, WaitEventMask=0X%lX", pComm->WaitEventMask); + EnterCriticalSection(&pComm->EventsLock); + pComm->PendingEvents &= ~SERIAL_EV_FREERDP_WAITING; + LeaveCriticalSection(&pComm->EventsLock); assert(FALSE); return FALSE; } diff --git a/winpr/libwinpr/handle/handle.c b/winpr/libwinpr/handle/handle.c index 4d777d265..e7ada73ba 100644 --- a/winpr/libwinpr/handle/handle.c +++ b/winpr/libwinpr/handle/handle.c @@ -208,7 +208,7 @@ BOOL CloseHandle(HANDLE hObject) * SERIAL_EV_FREERDP_STOP anyway. Remove this code if * you think otherwise. */ EnterCriticalSection(&comm->EventsLock); - comm->PendingEvents |= SERIAL_EV_FREERDP_CLOSING; + comm->PendingEvents |= SERIAL_EV_FREERDP_STOP; LeaveCriticalSection(&comm->EventsLock); DeleteCriticalSection(&comm->EventsLock);