mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
winpr-handle: CloseHandle(), added ability to register some callback functions
winpr-comm: implemented CommCloseHandle()
This commit is contained in:
committed by
Emmanuel Ledoux
parent
d38a323526
commit
f454a5c0c8
@@ -385,6 +385,9 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
|
||||
|
||||
error_handle:
|
||||
|
||||
/* FIXME: find out whether it's required or not to get
|
||||
* BytesReturned == OutputBufferLength when
|
||||
* CommDeviceIoControl returns FALSE */
|
||||
assert(OutputBufferLength == BytesReturned);
|
||||
|
||||
Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */
|
||||
|
||||
@@ -314,13 +314,13 @@ WINPR_API BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecu
|
||||
|
||||
/* Extra Functions */
|
||||
|
||||
typedef BOOL (*pcIsHandled)(LPCSTR lpFileName);
|
||||
typedef BOOL (*pcIsFileHandled)(LPCSTR lpFileName);
|
||||
typedef HANDLE (*pcCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
|
||||
typedef struct _HANDLE_CREATOR
|
||||
{
|
||||
pcIsHandled IsHandled;
|
||||
pcIsFileHandled IsHandled;
|
||||
pcCreateFileA CreateFileA;
|
||||
} HANDLE_CREATOR, *PHANDLE_CREATOR, *LPHANDLE_CREATOR;
|
||||
|
||||
|
||||
@@ -755,6 +755,7 @@ typedef struct _COMM_DEVICE
|
||||
static COMM_DEVICE **_CommDevices = NULL;
|
||||
|
||||
static HANDLE_CREATOR *_CommHandleCreator = NULL;
|
||||
static HANDLE_CLOSE_CB *_CommHandleCloseCb = NULL;
|
||||
|
||||
static pthread_once_t _CommInitialized = PTHREAD_ONCE_INIT;
|
||||
static void _CommInit()
|
||||
@@ -763,6 +764,7 @@ static void _CommInit()
|
||||
|
||||
assert(_CommDevices == NULL);
|
||||
assert(_CommHandleCreator == NULL);
|
||||
assert(_CommHandleCloseCb == NULL);
|
||||
|
||||
_CommDevices = (COMM_DEVICE**)calloc(COMM_DEVICE_MAX+1, sizeof(COMM_DEVICE*));
|
||||
|
||||
@@ -775,8 +777,18 @@ static void _CommInit()
|
||||
RegisterHandleCreator(_CommHandleCreator);
|
||||
}
|
||||
|
||||
_CommHandleCloseCb = (HANDLE_CLOSE_CB*)malloc(sizeof(HANDLE_CLOSE_CB));
|
||||
if (_CommHandleCloseCb)
|
||||
{
|
||||
_CommHandleCloseCb->IsHandled = CommIsHandled;
|
||||
_CommHandleCloseCb->CloseHandle = CommCloseHandle;
|
||||
|
||||
RegisterHandleCloseCb(_CommHandleCloseCb);
|
||||
}
|
||||
|
||||
assert(_CommDevices != NULL);
|
||||
assert(_CommHandleCreator != NULL);
|
||||
assert(_CommHandleCloseCb != NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,4 +1244,69 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
|
||||
}
|
||||
|
||||
|
||||
BOOL CommIsHandled(HANDLE handle)
|
||||
{
|
||||
WINPR_COMM *pComm;
|
||||
|
||||
pComm = (WINPR_COMM*)handle;
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL CommCloseHandle(HANDLE handle)
|
||||
{
|
||||
WINPR_COMM *pComm;
|
||||
|
||||
pComm = (WINPR_COMM*)handle;
|
||||
|
||||
if (!pComm || pComm->Type != HANDLE_TYPE_COMM)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pComm->PendingEvents & SERIAL_EV_FREERDP_WAITING)
|
||||
{
|
||||
ULONG WaitMask = 0;
|
||||
DWORD BytesReturned = 0;
|
||||
|
||||
/* ensures to gracefully stop the WAIT_ON_MASK's loop */
|
||||
if (!CommDeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK, &WaitMask, sizeof(ULONG), NULL, 0, &BytesReturned, NULL))
|
||||
{
|
||||
DEBUG_WARN("failure to WAIT_ON_MASK's loop!");
|
||||
}
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&pComm->ReadLock);
|
||||
DeleteCriticalSection(&pComm->WriteLock);
|
||||
DeleteCriticalSection(&pComm->EventsLock);
|
||||
|
||||
if (pComm->fd > 0)
|
||||
close(pComm->fd);
|
||||
|
||||
if (pComm->fd_write > 0)
|
||||
close(pComm->fd_write);
|
||||
|
||||
if (pComm->fd_write_event > 0)
|
||||
close(pComm->fd_write_event);
|
||||
|
||||
if (pComm->fd_read > 0)
|
||||
close(pComm->fd_read);
|
||||
|
||||
if (pComm->fd_read_event > 0)
|
||||
close(pComm->fd_read_event);
|
||||
|
||||
free(pComm);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
@@ -74,6 +74,9 @@ typedef struct winpr_comm WINPR_COMM;
|
||||
#define FREERDP_PURGE_TXABORT 0x00000001 /* abort pending transmission */
|
||||
#define FREERDP_PURGE_RXABORT 0x00000002 /* abort pending reception */
|
||||
|
||||
BOOL CommIsHandled(HANDLE handle);
|
||||
BOOL CommCloseHandle(HANDLE handle);
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* WINPR_COMM_PRIVATE_H */
|
||||
|
||||
@@ -462,7 +462,7 @@ static BOOL _CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID l
|
||||
|
||||
if (!pServerSerialDriver->wait_on_mask(pComm, pOutputMask))
|
||||
{
|
||||
*lpBytesReturned = sizeof(ULONG); /* TMP: TODO: all lpBytesReturned values to be reviewed on error */
|
||||
*lpBytesReturned = sizeof(ULONG);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -670,6 +670,12 @@ BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
result = _CommDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
|
||||
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
|
||||
if (lpBytesReturned && *lpBytesReturned != nOutBufferSize)
|
||||
{
|
||||
/* This might be a hint for a bug, especially when result==TRUE */
|
||||
DEBUG_WARN("lpBytesReturned=%d and nOutBufferSize=%d are different!", *lpBytesReturned, nOutBufferSize);
|
||||
}
|
||||
|
||||
if (pComm->permissive)
|
||||
{
|
||||
if (!result)
|
||||
@@ -722,7 +728,7 @@ int _comm_ioctl_tcsetattr(int fd, int optional_actions, const struct termios *te
|
||||
if (memcmp(¤tState, termios_p, sizeof(struct termios)) != 0)
|
||||
{
|
||||
DEBUG_WARN("Failure: all termios parameters are still not set on a second attempt");
|
||||
return -1; /* TMP: double-check whether some parameters can differ anyway */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../synch/synch.h"
|
||||
#include "../thread/thread.h"
|
||||
#include "../pipe/pipe.h"
|
||||
@@ -37,14 +40,83 @@
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
/* _HandleCreators is a NULL-terminated array with a maximun of HANDLE_CREATOR_MAX HANDLE_CREATOR */
|
||||
#define HANDLE_CLOSE_CB_MAX 128
|
||||
static HANDLE_CLOSE_CB **_HandleCloseCbs = NULL;
|
||||
|
||||
static pthread_once_t _HandleCloseCbsInitialized = PTHREAD_ONCE_INIT;
|
||||
static void _HandleCloseCbsInit()
|
||||
{
|
||||
/* NB: error management to be done outside of this function */
|
||||
|
||||
assert(_HandleCloseCbs == NULL);
|
||||
|
||||
_HandleCloseCbs = (HANDLE_CLOSE_CB**)calloc(HANDLE_CLOSE_CB_MAX+1, sizeof(HANDLE_CLOSE_CB*));
|
||||
|
||||
assert(_HandleCloseCbs != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE on success, FALSE otherwise.
|
||||
*/
|
||||
BOOL RegisterHandleCloseCb(HANDLE_CLOSE_CB *pHandleCloseCb)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pthread_once(&_HandleCloseCbsInitialized, _HandleCloseCbsInit) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_HandleCloseCbs == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
for (i=0; i<HANDLE_CLOSE_CB_MAX; i++)
|
||||
{
|
||||
if (_HandleCloseCbs[i] == NULL)
|
||||
{
|
||||
_HandleCloseCbs[i] = pHandleCloseCb;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL CloseHandle(HANDLE hObject)
|
||||
{
|
||||
int i;
|
||||
ULONG Type;
|
||||
PVOID Object;
|
||||
|
||||
if (!winpr_Handle_GetInfo(hObject, &Type, &Object))
|
||||
return FALSE;
|
||||
|
||||
if (pthread_once(&_HandleCloseCbsInitialized, _HandleCloseCbsInit) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_HandleCloseCbs == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i=0; _HandleCloseCbs[i] != NULL; i++)
|
||||
{
|
||||
HANDLE_CLOSE_CB *close_cb = (HANDLE_CLOSE_CB*)_HandleCloseCbs[i];
|
||||
if (close_cb && close_cb->IsHandled(hObject))
|
||||
{
|
||||
return close_cb->CloseHandle(hObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Type == HANDLE_TYPE_THREAD)
|
||||
{
|
||||
WINPR_THREAD* thread;
|
||||
@@ -197,43 +269,6 @@ BOOL CloseHandle(HANDLE hObject)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (Type == HANDLE_TYPE_COMM)
|
||||
{
|
||||
WINPR_COMM* comm;
|
||||
|
||||
comm = (WINPR_COMM*) Object;
|
||||
|
||||
/* NOTE: This is up to the caller of CloseHandle() to
|
||||
* ensure there is no pending request. Sending
|
||||
* SERIAL_EV_FREERDP_STOP anyway. Remove this code if
|
||||
* you think otherwise. */
|
||||
EnterCriticalSection(&comm->EventsLock);
|
||||
comm->PendingEvents |= SERIAL_EV_FREERDP_STOP;
|
||||
LeaveCriticalSection(&comm->EventsLock);
|
||||
|
||||
DeleteCriticalSection(&comm->ReadLock);
|
||||
DeleteCriticalSection(&comm->WriteLock);
|
||||
DeleteCriticalSection(&comm->EventsLock);
|
||||
|
||||
if (comm->fd > 0)
|
||||
close(comm->fd);
|
||||
|
||||
if (comm->fd_write > 0)
|
||||
close(comm->fd_write);
|
||||
|
||||
if (comm->fd_write_event > 0)
|
||||
close(comm->fd_write_event);
|
||||
|
||||
if (comm->fd_read > 0)
|
||||
close(comm->fd_read);
|
||||
|
||||
if (comm->fd_read_event > 0)
|
||||
close(comm->fd_read_event);
|
||||
|
||||
free(comm);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -64,4 +64,16 @@ static inline BOOL winpr_Handle_GetInfo(HANDLE handle, ULONG* pType, PVOID* pObj
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
typedef BOOL (*pcIsHandled)(HANDLE handle);
|
||||
typedef BOOL (*pcCloseHandle)(HANDLE handle);
|
||||
|
||||
typedef struct _HANDLE_CLOSE_CB
|
||||
{
|
||||
pcIsHandled IsHandled;
|
||||
pcCloseHandle CloseHandle;
|
||||
} HANDLE_CLOSE_CB;
|
||||
|
||||
BOOL RegisterHandleCloseCb(HANDLE_CLOSE_CB *pHandleClose);
|
||||
|
||||
#endif /* WINPR_HANDLE_PRIVATE_H */
|
||||
|
||||
Reference in New Issue
Block a user