summaryrefslogtreecommitdiff
path: root/OSpiceX.h
blob: 406435b49e35855d6d4d960aea242907a103d6ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
/*
 * Copyright 2013 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the GNU General Public License, version 2 or any
 * later version. See the file COPYING in the top-level directory of
 * this distribution or http://www.gnu.org/licenses/gpl-2.0.txt.
 */
// OSpiceX.h : Declaration of the COSpiceX

#pragma once

#include "resource.h"       // main symbols

// atl uses the deprecate function wsprintfA, disable the C4995 warning
#pragma warning(disable : 4995)
#include <atlctl.h>
#include <map>
#include "stdint.h"

#include "SpiceX.h"
#include "SpiceXCommon.h" 
#include "_IOSpiceXEvents_CP.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

// All SpiceX Windows Messages constants are offsets from SPICEX_WM_BASE
#define	SPICEX_WM_BASE							WM_USER + 0x1000	// 0x0400 + 0x1000 = 0x1400 = 5120
#define SPICEX_ON_DISCONNECTED_MSG				(SPICEX_WM_BASE+0)	// 5120
#define SPICEX_ON_MENU_ITEM_SELECTED_MSG		(SPICEX_WM_BASE+1)	// 5120

// http://msdn.microsoft.com/en-us/library/aa911976.aspx
#define RDP_ERROR_CODE_LOCAL_DISCONNECTION 1
#define RDP_ERROR_CODE_DNS_LOOKUP_FAILED 260
#define RDP_ERROR_CODE_OUT_OF_MEMORY 262
#define RDP_ERROR_CODE_WINSOCK_CONNECT_FAILED 516
#define RDP_ERROR_CODE_HOST_NOT_FOUND 520
#define RDP_ERROR_CODE_INTERNAL_ERROR 1032
#define RDP_ERROR_RECV_WINSOCK_FAILED 1028
#define RDP_ERROR_SEND_WINSOCK_FAILED 772
#define RDP_ERROR_CODE_TIMEOUT 1796

#define SPICE_ERROR_BASE 100

#define PIPE_BUF_SIZE 16384

struct ControllerValue;

// COSpiceX
class ATL_NO_VTABLE COSpiceX :
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatchImpl<IOSpiceX, &IID_IOSpiceX, &LIBID_SpiceXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public IPersistStreamInitImpl<COSpiceX>,
	public IPersistPropertyBagImpl<COSpiceX>,
	public IOleControlImpl<COSpiceX>,
	public IOleObjectImpl<COSpiceX>,
	public IOleInPlaceActiveObjectImpl<COSpiceX>,
	public IViewObjectExImpl<COSpiceX>,
	public IOleInPlaceObjectWindowlessImpl<COSpiceX>,
	public ISupportErrorInfo,
	public IConnectionPointContainerImpl<COSpiceX>,
	public CProxy_IOSpiceXEvents<COSpiceX>,
	public IPersistStorageImpl<COSpiceX>,
	public ISpecifyPropertyPagesImpl<COSpiceX>,
	public IQuickActivateImpl<COSpiceX>,
#ifndef _WIN32_WCE
	public IDataObjectImpl<COSpiceX>,
#endif
	public IProvideClassInfo2Impl<&CLSID_OSpiceX, &__uuidof(_IOSpiceXEvents), &LIBID_SpiceXLib>,
#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
	public IObjectSafetyImpl<COSpiceX, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
#endif
	public CComCoClass<COSpiceX, &CLSID_OSpiceX>,
	public CComControl<COSpiceX>,
	// added by itai 10/07/07 (IObjectSafetyImpl implementation (suppress unsafe AX msg)
	public IObjectSafetyImpl<COSpiceX, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
{
public:


	COSpiceX()
	{
        // added by itai 01/07/07 (indicate the control should be windowed, used for calling html events
        // from a non base thread using Windows Messages)
        m_bWindowOnly = true;
        m_hClientPipe = NULL;
        m_hEventThread = NULL;
        m_hClientProcess = NULL;
        m_hUsbCtrlProcess = NULL;
        m_hUsbCtrlLog = INVALID_HANDLE_VALUE;
        m_pi.hProcess = NULL;
		m_ulNumberOfMonitors = 1;
        m_UsbListenPort = 32032;
        m_AdminConsole = TRUE;
        m_SendCtrlAltDelete = TRUE;
        m_NoTaskMgrExecution = FALSE;
        m_UsbAutoShare = FALSE;

        ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
        m_OverlappedRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
        m_OverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        InitializeCriticalSection(&m_WriteLock);
        m_WriteStart = m_WriteEnd = m_WriteBuffer;
        m_WritePending = false;

		// set object properties to their default values
		StringCchCopyN(m_HostIP, MAX_PATH, L"255.255.255.255", MAX_PATH);
        StringCchCopyN(m_GuestHostName, MAX_PATH, L"", MAX_PATH);
		StringCchCopyN(m_AudioGuestIP, MAX_PATH, L"255.255.255.255", MAX_PATH);
		StringCchCopyN(m_szCipherSuite, MAX_PATH, L"", MAX_PATH);
		StringCchCopyN(m_szSSLChannels, MAX_PATH, L"", MAX_PATH);
		m_bIsSSL = false;
		m_Port = 0;
		m_SecurePort = 0;
		m_AudioPort = 0;
		StringCchCopyN(m_Title, RED_CLIENT_MAX_TITLE_SIZE, RED_CLIENT_DEFAULT_TITLE,
                       RED_CLIENT_MAX_TITLE_SIZE);
		StringCchCopyN(m_szPassword, RED_MAX_PASSWORD_LENGTH, L"", RED_MAX_PASSWORD_LENGTH);
        StringCchCopyN(m_strMenuResource, RED_CLIENT_MAX_MENU_SIZE, L"", RED_CLIENT_MAX_MENU_SIZE);
	}

DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_INSIDEOUT |
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST
)

DECLARE_REGISTRY_RESOURCEID(IDR_OSPICEX)


BEGIN_COM_MAP(COSpiceX)
	COM_INTERFACE_ENTRY(IOSpiceX)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IViewObjectEx)
	COM_INTERFACE_ENTRY(IViewObject2)
	COM_INTERFACE_ENTRY(IViewObject)
	COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceObject)
	COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
	COM_INTERFACE_ENTRY(IOleControl)
	COM_INTERFACE_ENTRY(IOleObject)
	COM_INTERFACE_ENTRY(IPersistStreamInit)
	COM_INTERFACE_ENTRY(IPersistPropertyBag)
	COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
	COM_INTERFACE_ENTRY(ISupportErrorInfo)
	COM_INTERFACE_ENTRY(IConnectionPointContainer)
	COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
	COM_INTERFACE_ENTRY(IQuickActivate)
	COM_INTERFACE_ENTRY(IPersistStorage)
#ifndef _WIN32_WCE
	COM_INTERFACE_ENTRY(IDataObject)
#endif
	COM_INTERFACE_ENTRY(IProvideClassInfo)
	COM_INTERFACE_ENTRY(IProvideClassInfo2)
#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
	COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
#endif
	// added by itai 10/07/07 (IObjectSafetyImpl implementation (suppress unsafe AX msg)
	COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()

BEGIN_PROP_MAP(COSpiceX)
	PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
	PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
	// Example entries
	// PROP_ENTRY("Property Description", dispid, clsid)
	// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

BEGIN_CONNECTION_POINT_MAP(COSpiceX)
	CONNECTION_POINT_ENTRY(__uuidof(_IOSpiceXEvents))
END_CONNECTION_POINT_MAP()

BEGIN_MSG_MAP(COSpiceX)
	CHAIN_MSG_MAP(CComControl<COSpiceX>)
	DEFAULT_REFLECTION_HANDLER()
	// added by itai 01/07/07 (using windows messages to fire events)
	MESSAGE_HANDLER(SPICEX_ON_DISCONNECTED_MSG, OnDisconnectedMsg)
    MESSAGE_HANDLER(SPICEX_ON_MENU_ITEM_SELECTED_MSG, OnMenuItemSelected)
END_MSG_MAP()
// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
	{
		static const IID* arr[] =
		{
			&IID_IOSpiceX,
		};

		for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
		{
			if (InlineIsEqualGUID(*arr[i], riid))
				return S_OK;
		}
		return S_FALSE;
	}

// IViewObjectEx
	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// IPersistPropertBag
	STDMETHOD(Load)(IPropertyBag *pPropBag, IErrorLog* pErrorLog);

	// IOSpiceX
public:
		HRESULT OnDraw(ATL_DRAWINFO& di)
		{
		RECT& rc = *(RECT*)di.prcBounds;
		// Set Clip region to the rectangle specified by di.prcBounds
		HRGN hRgnOld = NULL;
		if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
			hRgnOld = NULL;
		bool bSelectOldRgn = false;

		HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);

		if (hRgnNew != NULL)
		{
			bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);
		}

		Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
		SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
		LPCTSTR pszText = _T("ATL 8.0 : OSpiceX");
#ifndef _WIN32_WCE
		TextOut(di.hdcDraw,
			(rc.left + rc.right) / 2,
			(rc.top + rc.bottom) / 2,
			pszText,
			lstrlen(pszText));
#else
		ExtTextOut(di.hdcDraw,
			(rc.left + rc.right) / 2,
			(rc.top + rc.bottom) / 2,
			ETO_OPAQUE,
			NULL,
			pszText,
			ATL::lstrlen(pszText),
			NULL);
#endif

		if (bSelectOldRgn)
			SelectClipRgn(di.hdcDraw, hRgnOld);

		return S_OK;
	}

    LRESULT OnMenuItemSelected(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
		Fire_OnMenuItemSelected((ULONG)wParam);
		return ERROR_SUCCESS;
    }

	LRESULT OnDisconnectedMsg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		Fire_OnDisconnected((LONG)wParam);
		return ERROR_SUCCESS;
	}

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}
	STDMETHOD(Connect)(void);
	STDMETHOD(Disconnect)(void);
	STDMETHOD(SendCAD)(void);
	STDMETHOD(Show)(void);
	STDMETHOD(Hide)(void);
	STDMETHOD(SetSecondaryAddress)(void);
	STDMETHOD(get_HostIP)(BSTR* pVal);
	STDMETHOD(put_HostIP)(BSTR newVal);
	STDMETHOD(get_Port)(USHORT* pVal);
	STDMETHOD(put_Port)(USHORT newVal);
	STDMETHOD(get_SecurePort)(USHORT* pVal);
	STDMETHOD(put_SecurePort)(USHORT newVal);
	STDMETHOD(get_ScaleEnable)(ULONG* pVal);
	STDMETHOD(put_ScaleEnable)(ULONG newVal);
	STDMETHOD(get_ScaleNum)(ULONG* pVal);
	STDMETHOD(put_ScaleNum)(ULONG newVal);
	STDMETHOD(get_ScaleDen)(ULONG* pVal);
	STDMETHOD(put_ScaleDen)(ULONG newVal);
	STDMETHOD(get_FullScreen)(ULONG* pVal);
	STDMETHOD(put_FullScreen)(ULONG newVal);
	STDMETHOD(get_MsUser)(BSTR* pVal);
	STDMETHOD(put_MsUser)(BSTR newVal);
	STDMETHOD(get_MSDomain)(BSTR* pVal);
	STDMETHOD(put_MSDomain)(BSTR newVal);
	STDMETHOD(get_MSPassword)(BSTR* pVal);
	STDMETHOD(put_MSPassword)(BSTR newVal);
	STDMETHOD(get_StretchMode)(ULONG* pVal);
	STDMETHOD(put_StretchMode)(ULONG newVal);
	STDMETHOD(get_ScreenHeight)(ULONG* pVal);
	STDMETHOD(put_ScreenHeight)(ULONG newVal);
	STDMETHOD(get_ConnectingText)(BSTR* pVal);
	STDMETHOD(put_ConnectingText)(BSTR newVal);
	STDMETHOD(get_DisconnectingText)(BSTR* pVal);
	STDMETHOD(put_DisconnectingText)(BSTR newVal);
	STDMETHOD(get_SwapMouseButtons)(ULONG* pVal);
	STDMETHOD(put_SwapMouseButtons)(ULONG newVal);
	STDMETHOD(get_AudioRedirection)(ULONG* pVal);
	STDMETHOD(put_AudioRedirection)(ULONG newVal);
	STDMETHOD(get_SecondaryHostIP)(BSTR* pVal);
	STDMETHOD(put_SecondaryHostIP)(BSTR newVal);
	STDMETHOD(get_SecondaryPort)(USHORT* pVal);
	STDMETHOD(put_SecondaryPort)(USHORT newVal);
	STDMETHOD(get_PollingInterval)(ULONG* pVal);
	STDMETHOD(put_PollingInterval)(ULONG newVal);
	STDMETHOD(get_Title)(BSTR* pVal);
	STDMETHOD(put_Title)(BSTR newVal);
	// Audio interface
	STDMETHOD(ConnectAudio)(void);
	STDMETHOD(DisconnectAudio)(void);
	STDMETHOD(get_AudioGuestIP)(BSTR* pVal);
	STDMETHOD(put_AudioGuestIP)(BSTR newVal);
	STDMETHOD(get_AudioGuestPort)(SHORT* pVal);
	STDMETHOD(put_AudioGuestPort)(SHORT newVal);
	STDMETHOD(get_Password)(BSTR* pVal);
	STDMETHOD(put_Password)(BSTR newVal);
	STDMETHOD(get_CipherSuite)(BSTR* pVal);
	STDMETHOD(put_CipherSuite)(BSTR newVal);
	STDMETHOD(get_SSLChannels)(BSTR* pVal);
	STDMETHOD(put_SSLChannels)(BSTR newVal);
    STDMETHOD(get_multimediaPorts)(BSTR* pVal);
    STDMETHOD(put_multimediaPorts)(BSTR newVal);
    STDMETHOD(get_DynamicMenu)(BSTR* pVal);
    STDMETHOD(put_DynamicMenu)(BSTR newVal);
    STDMETHOD(get_NumberOfMonitors)(ULONG* pVal);
    STDMETHOD(put_NumberOfMonitors)(ULONG newVal);
    STDMETHOD(CreateMenu)(BSTR MenuResourceString);
    STDMETHOD(DeleteMenu)(void);
    STDMETHOD(get_UsbListenPort)(USHORT* pVal);
    STDMETHOD(put_UsbListenPort)(USHORT newVal);
    STDMETHOD(get_AdminConsole)(BOOL* pVal);
    STDMETHOD(put_AdminConsole)(BOOL newVal);
    STDMETHOD(get_SendCtrlAltDelete)(BOOL* pVal);
    STDMETHOD(put_SendCtrlAltDelete)(BOOL newVal);
    STDMETHOD(get_NoTaskMgrExecution)(BOOL* pVal);
    STDMETHOD(put_NoTaskMgrExecution)(BOOL newVal);
    STDMETHOD(get_GuestHostName)(BSTR* pVal);
    STDMETHOD(put_GuestHostName)(BSTR newVal);
    STDMETHOD(get_HotKey)(BSTR* pVal);
    STDMETHOD(put_HotKey)(BSTR newVal);
    STDMETHOD(SetUsbFilter)(BSTR newVal);
    STDMETHOD(get_Version)(BSTR* pVal);
    STDMETHOD(get_UsbAutoShare)(BOOL* pVal);
    STDMETHOD(put_UsbAutoShare)(BOOL newVal);
    STDMETHOD(SetLanguageStrings)(BSTR bzSection, BSTR bzLangStr);
	STDMETHOD(get_TrustStore)(BSTR* pVal);
	STDMETHOD(put_TrustStore)(BSTR newVal);
	STDMETHOD(get_HostSubject)(BSTR* pVal);
	STDMETHOD(put_HostSubject)(BSTR newVal);
	STDMETHOD(get_ColorDepth)(USHORT* pVal);
	STDMETHOD(put_ColorDepth)(USHORT newVal);
	STDMETHOD(get_DisableEffects)(BSTR* pVal);
	STDMETHOD(put_DisableEffects)(BSTR newVal);
	STDMETHOD(get_SmartCard)(BOOL* pVal);
	STDMETHOD(put_SmartCard)(BOOL newVal);
	STDMETHOD(get_Proxy)(BSTR* pVal);
	STDMETHOD(put_Proxy)(BSTR newVal);

private:
    UINT m_CurrentExecuterState;
    HANDLE m_hClientPipe;
    HANDLE m_hEventThread;
    HANDLE m_hClientProcess;
    HANDLE m_hUsbCtrlProcess;
    HANDLE m_hUsbCtrlLog;
    PROCESS_INFORMATION m_pi;

    OVERLAPPED m_OverlappedRead;
    OVERLAPPED m_OverlappedWrite;
    CRITICAL_SECTION m_WriteLock;
    int8_t m_WriteBuffer[PIPE_BUF_SIZE];
    int8_t* m_WriteStart;
    int8_t* m_WriteEnd;
    bool m_WritePending;

	bool m_bIsSSL;
	wchar_t	m_szPassword[RED_MAX_PASSWORD_LENGTH];
	wchar_t m_szCipherSuite[MAX_PATH];
	wchar_t m_szSSLChannels[MAX_PATH];
	wchar_t m_HostIP[MAX_PATH];
    wchar_t m_GuestHostName[MAX_PATH];
	wchar_t m_AudioGuestIP[MAX_PATH];
    wchar_t m_AudioGuestPorts[MAX_PATH];
    wchar_t m_Title[RED_CLIENT_MAX_TITLE_SIZE];
    wchar_t m_strMenuResource[RED_CLIENT_MAX_MENU_SIZE];
    std::wstring m_UsbFilter;
    std::map<std::wstring, std::wstring> m_Language;
    std::wstring m_HotKey;
    std::wstring m_TrustStore;
    std::wstring m_HostSubject;
	USHORT	m_Port;
	USHORT	m_SecurePort;
	USHORT	m_AudioPort;
	ULONG	m_ulNumberOfMonitors;
	ULONG	m_ScaleEnable;
	ULONG	m_ScaleNum;
	ULONG	m_ScaleDen;
	ULONG	m_FullScreen;
	BSTR	m_MsUser;
	BSTR	m_MSDomain;
	BSTR	m_MSPassword;
	ULONG	m_StretchMode;
	ULONG	m_ScreenHeight;
	BSTR	m_ConnectingText;
	BSTR	m_DisconnectingText;
	ULONG	m_SwapMouseButtons;
	ULONG	m_AudioRedirection;
	BSTR	m_SecondaryHostIP;
	USHORT	m_SecondaryPort;
	ULONG	m_PollingInterval;
    USHORT  m_UsbListenPort;
    BOOL    m_AdminConsole;
    BOOL    m_SendCtrlAltDelete;
    BOOL    m_NoTaskMgrExecution;
    BOOL    m_UsbAutoShare;
    USHORT  m_ColorDepth;
    std::wstring m_DisableEffects;
    BOOL    m_SmartCard;
    std::wstring m_Proxy;

private:
    static DWORD WINAPI event_thread(PVOID param);
    bool handle_in_msg(ControllerValue& msg);
    bool handle_out_msg();
    HRESULT write_to_pipe(const void* data, uint32_t size);
    HRESULT send_init();
    HRESULT send_msg(uint32_t id);
    HRESULT send_value(uint32_t id, uint32_t value);
    HRESULT send_bool(uint32_t id, uint32_t value);
    HRESULT send_wstr(uint32_t id, const wchar_t* str, bool use_mb_str = false);
    void cleanup();

    static DWORD WINAPI UsbCtrlWatchDog(PVOID param);
    HRESULT ExecuteUsbCtrl();
    HRESULT CreateCAFile(OUT LPWSTR szCAFileName, DWORD nSize);
};

OBJECT_ENTRY_AUTO(__uuidof(OSpiceX), COSpiceX)