/*++ * File name: * tclientaxobj.h * Contents: * This module contains the header for the CTClientApi class. * * Copyright (C) 2002 Microsoft Corp. --*/ #include "resource.h" #include #include "gdata.h" // // VOID // SaveError ( // IN PCSTR Error, // IN DWORD TlsIndex, // OUT HRESULT *Result // ); // #define SaveError(Error, TlsIndex, Result) \ { \ \ /* \ * Set the result code. The presence of an error string indicates \ * failure. \ */ \ \ *(Result) = (Error) == NULL ? S_OK : E_FAIL; \ \ /* \ * Update the current thread's error string. If a TLS index could not \ * be allocated for the current instance, error strings cannot be used. \ */ \ \ if ((TlsIndex) != TLS_OUT_OF_INDEXES) \ { \ \ /* \ / If a TLS index was allocated, setting the value should not fail. \ */ \ \ if (!RTL_VERIFY(TlsSetValue((TlsIndex), (PVOID)(Error)))) \ { \ *(Result) = HRESULT_FROM_WIN32(GetLastError()); \ } \ } \ } \ // // CTClientApi class. // class CTClientApi : public CComObjectRoot, public CComCoClass, public CComControl, public IDispatchImpl, public IPersistStreamInitImpl, public IPersistStorageImpl, public IOleControlImpl, public IOleObjectImpl, public IOleInPlaceActiveObjectImpl, public IOleInPlaceObjectWindowlessImpl, public IViewObjectExImpl //, // public IObjectSafetyImpl { public: CTClientApi( ) : m_pCI(NULL) { // // Allocate the index for per-thread errors. If the allocation // fails, error strings will not be available. // m_dwErrorIndex = TlsAlloc(); // // Initialize the allocation lists. // #if 0 InitializeListHead(&m_HeapAllocations); InitializeListHead(&m_SysStringAllocations); InitializeListHead(&m_TClientAllocations); #endif // // Initialize the global printing routine. It would be preferable to // set it only if it is currently empty, but Windows 95 compatibility // is required, and therefore InterlockedCompareExchange would have // to be dynamically loaded with LoadLibrary. // InterlockedExchangePointer((PVOID *)&g_pfnPrintMessage, CTClientApi::PrintMessage); } ~CTClientApi( ) { #if 0 PLIST_ENTRY pNextEntry; PALLOCATION pAllocation; #endif // // If a connection exists, disconnect it. // if (m_pCI != NULL) { RTL_VERIFY(SCDisconnect(m_pCI) == NULL); m_pCI = NULL; } // // TODO: The lists aren't used at present, but if they are going to // be used, an access count and rundown flag should be used to // protect the following code. // #if 0 // // Free any heap allocations. // while (!IsListEmpty(&m_HeapAllocations)) { // // Remove the entry from the list, free the allocated memory, // then free the allocation structure. // pNextEntry = RemoveHeadList(&m_HeapAllocations); ASSERT(pNextEntry != NULL); pAllocation = CONTAINING_RECORD(pNextEntry, ALLOCATION, AllocationListEntry); ASSERT(pAllocation != NULL && pAllocation->Address != NULL); RTL_VERIFY(HeapFree(GetProcessHeap(), 0, pAllocation->Address)); RTL_VERIFY(HeapFree(GetProcessHeap(), 0, pAllocation)); } // // Free any COM strings that will not be freed by the caller. // while (!IsListEmpty(&m_SysStringAllocations)) { // // Remove the entry from the list, free the allocated memory, // then free the allocation structure. // pNextEntry = RemoveHeadList(&m_SysStringAllocations); ASSERT(pNextEntry != NULL); pAllocation = CONTAINING_RECORD(pNextEntry, ALLOCATION, AllocationListEntry); ASSERT(pAllocation != NULL && pAllocation->Address != NULL); SysFreeString((BSTR)pAllocation->Address); RTL_VERIFY(HeapFree(GetProcessHeap(), 0, pAllocation)); } // // Free any TClient-allocated memory. // while (!IsListEmpty(&m_TClientAllocations)) { // // Remove the entry from the list, free the allocated memory, // then free the allocation structure. // pNextEntry = RemoveHeadList(&m_TClientAllocations); ASSERT(pNextEntry != NULL); pAllocation = CONTAINING_RECORD(pNextEntry, ALLOCATION, AllocationListEntry); ASSERT(pAllocation != NULL && pAllocation->Address != NULL); SCFreeMem(pAllocation->Address); RTL_VERIFY(HeapFree(GetProcessHeap(), 0, pAllocation)); } #endif // // If an error index was allocated, free it. // if (m_dwErrorIndex != TLS_OUT_OF_INDEXES) { RTL_VERIFY(TlsFree(m_dwErrorIndex)); } } // // Define message map which may be enabled later, if GUI support is added // (e.g. for logging). // #if 0 BEGIN_MSG_MAP(CTClientApi) MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_TIMER, OnTimer) MESSAGE_HANDLER(WM_SIZE, OnSize) MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) END_MSG_MAP() #endif // 0 // // Define COM map. // BEGIN_COM_MAP(CTClientApi) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITClientApi) // COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject, IViewObjectEx) COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject2, IViewObjectEx) COM_INTERFACE_ENTRY_IMPL(IViewObjectEx) COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleWindow, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleInPlaceObject, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY_IMPL(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY_IMPL(IOleInPlaceActiveObject) COM_INTERFACE_ENTRY_IMPL(IOleControl) COM_INTERFACE_ENTRY_IMPL(IOleObject) COM_INTERFACE_ENTRY_IMPL(IPersistStorage) COM_INTERFACE_ENTRY_IMPL(IPersistStreamInit) END_COM_MAP() // // Define connection-point map. // BEGIN_CONNECTION_POINT_MAP(CTClientApi) END_CONNECTION_POINT_MAP() // // Define property map. // BEGIN_PROP_MAP(CTClientApi) END_PROPERTY_MAP() // // COM declarations. // //DECLARE_NOT_AGGREGATABLE(CTClientApi) DECLARE_GET_CONTROLLING_UNKNOWN() //DECLARE_CONTROL_INFO(CLSID_CTClient) DECLARE_REGISTRY_RESOURCEID(IDR_TClient) protected: // // Define connection information and error index. // PCONNECTINFO m_pCI; DWORD m_dwErrorIndex; // // The following lists are used to track allocations from the process and // CRT heaps. The SysXxxString routines use the CRT heap, which is also // used for the TClient allocations. General allocations use the process // heap. // // Note: These lists are not currently used. // #if 0 LIST_ENTRY m_HeapAllocations; LIST_ENTRY m_SysStringAllocations; LIST_ENTRY m_TClientAllocations; #endif // // ITClientApi interface. // public: // // Declare message handlers which may be enabled later. // #if 0 HRESULT OnDraw ( ATL_DRAWINFO& di ); LRESULT OnCreate ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); LRESULT OnDestroy ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); LRESULT OnLButtonDown ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); LRESULT OnLButtonUp ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); LRESULT OnMouseMove ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); LRESULT OnSize ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { UNREFERENCED_PARAMETER(uMsg); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(bHandled); return 0; } LRESULT OnEraseBackground ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { UNREFERENCED_PARAMETER(uMsg); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(bHandled); return 0; } LRESULT OnTimer ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ) { UNREFERENCED_PARAMETER(uMsg); UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(bHandled); return 0; } #endif // 0 STDMETHODIMP get_Error ( OUT BSTR *Message ) { PSTR szError; BSTR bstrError; HRESULT hrResult; USES_CONVERSION; ATLTRACE(_T("ITClientApi::get_Error\n")); // // Get the current thread's error string. If a TLS index could not be // allocated, an error string cannot be returned. // if (m_dwErrorIndex != TLS_OUT_OF_INDEXES) { szError = (PSTR)TlsGetValue(m_dwErrorIndex); } else { szError = NULL; } // // If the error string is NULL or empty, use NULL. // if (szError == NULL || *szError == '\0') { bstrError = NULL; } // // Convert the current error string to a BSTR. This will allocate // from the CRT heap, and the storage must be freed by the caller, // using SysFreeString. // else { bstrError = A2BSTR(szError); if (bstrError == NULL) { return E_OUTOFMEMORY; } } // // Copy the address of the error string to the message pointer. // hrResult = E_FAIL; _try { _try { *Message = bstrError; hrResult = S_OK; } // // If the message pointer is invalid, set an appropriate return // value. // _except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { hrResult = E_POINTER; } } // // If the message pointer could not be set, the BSTR will not be // returned, so free it. // _finally { if (FAILED(hrResult)) { ASSERT(bstrError != NULL); SysFreeString(bstrError); } } return hrResult; } STDMETHODIMP SaveClipboard ( IN BSTR FormatName, IN BSTR FileName ); STDMETHODIMP IsDead ( OUT BOOL *Dead ); STDMETHODIMP SendTextAsMessages ( IN BSTR Text ); STDMETHODIMP Connect2 ( IN BSTR ServerName, IN BSTR UserName, IN BSTR Password, IN BSTR Domain, IN BSTR Shell, IN ULONG XResolution, IN ULONG YResolution, IN ULONG ConnectionFlags, IN ULONG ColorDepth, IN ULONG AudioOptions ); STDMETHODIMP GetFeedbackString ( OUT BSTR *FeedbackString ); STDMETHODIMP GetFeedback ( OUT SAFEARRAY **Feedback ); STDMETHODIMP ClientTerminate ( VOID ); STDMETHODIMP Check ( IN BSTR Command, IN BSTR Parameter ); STDMETHODIMP Clipboard ( IN ULONG Command, IN BSTR FileName ); STDMETHODIMP Connect ( IN BSTR ServerName, IN BSTR UserName, IN BSTR Password, IN BSTR Domain, IN ULONG XResolution, IN ULONG YResolution ); STDMETHODIMP Disconnect ( VOID ); STDMETHODIMP Logoff ( VOID ); STDMETHODIMP SendData ( IN UINT Message, IN UINT_PTR WParameter, IN LONG_PTR LParameter ); STDMETHODIMP Start ( IN BSTR AppName ); STDMETHODIMP SwitchToProcess ( IN BSTR WindowTitle ); STDMETHODIMP SendMouseClick ( IN ULONG XPosition, IN ULONG YPosition ); STDMETHODIMP GetSessionId ( OUT ULONG *SessionId ); STDMETHODIMP CloseClipboard ( VOID ); STDMETHODIMP OpenClipboard ( IN HWND Window ); STDMETHODIMP SetClientTopmost ( IN BOOL Enable ); STDMETHODIMP Attach ( IN HWND Window, IN LONG_PTR Cookie ); STDMETHODIMP Detach ( VOID ); STDMETHODIMP GetIni ( OUT ITClientIni **Ini ); STDMETHODIMP GetClientWindowHandle ( OUT HWND *Window ); // // Utility routines. // static VOID CTClientApi::PrintMessage ( MESSAGETYPE MessageType, LPCSTR Format, ... ); };