terminal/src/server/DeviceComm.h

41 lines
1.3 KiB
C
Raw Permalink Normal View History

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- DeviceComm.h
Abstract:
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
- This module assists in communicating via IOCTL messages to and from an endpoint
Author:
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
- Dustin Howett (DuHowett) 10-Apr-2020
Revision History:
--*/
#pragma once
#include "../host/conapi.h"
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
class IDeviceComm
{
public:
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
virtual ~IDeviceComm() = default;
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
[[nodiscard]] virtual HRESULT SetServerInformation(_In_ CD_IO_SERVER_INFORMATION* const pServerInfo) const = 0;
[[nodiscard]] virtual HRESULT ReadIo(_In_opt_ PCONSOLE_API_MSG const pReplyMsg,
_Out_ CONSOLE_API_MSG* const pMessage) const = 0;
[[nodiscard]] virtual HRESULT CompleteIo(_In_ CD_IO_COMPLETE* const pCompletion) const = 0;
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
[[nodiscard]] virtual HRESULT ReadInput(_In_ CD_IO_OPERATION* const pIoOperation) const = 0;
[[nodiscard]] virtual HRESULT WriteOutput(_In_ CD_IO_OPERATION* const pIoOperation) const = 0;
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
[[nodiscard]] virtual HRESULT AllowUIAccess() const = 0;
Convert DeviceComm into an interface and add handle exchange (#8367) This commit replaces DeviceComm with the interface IDeviceComm and the concrete implementation type ConDrvDeviceComm. This work is done in preparation for different device backends. In addition to separating out ConDrv-specific behavior, I've introduced a "handle exchange" interface. HANDLE EXCHANGE --------------- There are points where we give ConDrv opaque handle identifiers to our input buffer, output buffer and process data. The exact content of the opaque identifier is meaningless to ConDrv: the driver's only interaction with these identifiers is to hold onto them and send back whichever are pertinent for each API call. Because of that, we used the raw register-width pointer value of the input buffer, output buffer or process data _as_ the opaque handle value. This works very well for ConDrv <-> conhost using the ConDrvDeviceComm. It works less well for something like the "logging" DeviceComm that will log packets to a file: those packets *cannot* contain pointer values (!) To address this, and to afford flexibility to DeviceComm implementers, I've introduced a two-member complement of handle management functions: * `ULONG_PTR PutHandle(void*)` registers an object with the DeviceComm and returns an opaque identifier. * `void* GetHandle(ULONG_PTR)` takes an opaque identifier and returns the original object. ConDrvDeviceComm implements PutHandle and GetHandle by casting the object pointer to the "opaque handle value", which maintains wire format compatibility[1] with revisions of conhost prior to this change. Simpler DeviceComm implementations that require handle tracking but cannot bear raw pointers can implement these functions by returning an autoincrementing ID (or similar) and registering the raw object pointer in a mapping. I've audited all existing handle exchanges with the driver and updated them to use Put/GetHandle. (I intended to add DestroyHandle, but we are not equipped for handle removal at the moment. ConsoleHandleData/ConsoleProcessHandle are destroyed during wait routine completion, on client disconnect, etc. This does mean that an id<->pointer mapping will grow without bound, but at a cost of ~8 bytes per entry and a short-lived console session I am not too concerned about the cost.) [1] Wire format compatibility is not required, and later we may want to switch ConDrvDeviceComm to `EncodePointer` and `DecodePointer` just to insulate us against a spurious ConDrv packet allowing for an arbitrary 4/8-byte read and subsequent liftoff into space.
2020-12-16 00:07:43 +01:00
[[nodiscard]] virtual ULONG_PTR PutHandle(const void*) = 0;
[[nodiscard]] virtual void* GetHandle(ULONG_PTR) const = 0;
[[nodiscard]] virtual HRESULT GetServerHandle(_Out_ HANDLE* pHandle) const = 0;
};