spiegel-keyman/windows/src/engine/kmtip/server.cpp
Marc Durdin 738e1946a6 [Windows] Debug logging and proof of concept tests for keyboarding support within metro-style apps
[Windows] More tidyup and robustness for metro app support - debug cleanup and serialization of input (not quite finished)

[windows] Refactor serialized input code when used with key event thread model

[windows] Add consistent precompiled headers for other projects

[windows] Merge console window test into metro support

[Windows] Tidy up work and identify additional TODOs for metro-style app support

[Windows] Ensure error case falls through to default hook processing for console windows

[Windows] Refactor shared memory into memory mapped file so we can cross 32-64 bit boundary

[Windows] Tweaks to C++ security calls and parameters

[Windows] Start refactor of SerialKeyEvent* classes

[Windows] Rename to SerialKeyEventServer (refactoring)

[Windows] Complete refactoring of SerialKeyEventClient class

[Windows] Further encapsulation and cleanup with 'interfaces' to reduce header pollution

[Windows] Complete serialization fix with move of modifier state management from client thread to server thread to guarantee consistency

[Windows] Replace atom-based keyboard switching with memory mapped file indexed to avoid security constraints

[Windows] Fixup Left Alt+Shift interaction with serializer

[Windows] Use Windows 8.1 SDK for test
2018-10-18 20:00:49 +11:00

299 lines
7.7 KiB
C++

/*
Name: server
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 6 Nov 2007
Modified Date: 7 Nov 2013
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 06 Nov 2007 - mcdurdin - I1140 - Add KeymanAddinConfigure function to reconfigure the user's TSF linked keyboards
22 Mar 2010 - mcdurdin - Compiler fixup - x64 support
18 Mar 2011 - mcdurdin - I2807 - Enable/disable addins
24 Oct 2012 - mcdurdin - I3481 - V9.0 - Eliminate unsafe calls in C++
07 Nov 2012 - mcdurdin - I3549 - V9.0 - x64 version of kmtip addin
07 Nov 2012 - mcdurdin - I3550 - V9.0 - TSF Addin should be always enabled in 9.0
07 Nov 2013 - mcdurdin - I3944 - x64 kmtip has duplicated exports
*/
//
// server.cpp
//
// COM server exports.
//
#include "pch.h"
#include "kmtip.h"
#include "registry.h"
void FreeGlobalObjects(void);
class CClassFactory;
static CClassFactory *g_ObjectInfo[1] = { NULL };
//+---------------------------------------------------------------------------
//
// DllAddRef
//
//----------------------------------------------------------------------------
void DllAddRef(void)
{
InterlockedIncrement(&g_cRefDll);
}
//+---------------------------------------------------------------------------
//
// DllRelease
//
//----------------------------------------------------------------------------
void DllRelease(void)
{
if (InterlockedDecrement(&g_cRefDll) < 0) // g_cRefDll == -1 with zero refs
{
EnterCriticalSection(&g_cs);
// need to check ref again after grabbing mutex
if (g_ObjectInfo[0] != NULL)
{
FreeGlobalObjects();
}
assert(g_cRefDll == -1);
LeaveCriticalSection(&g_cs);
}
}
//+---------------------------------------------------------------------------
//
// CClassFactory declaration with IClassFactory Interface
//
//----------------------------------------------------------------------------
class CClassFactory : public IClassFactory
{
public:
// IUnknown methods
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IClassFactory methods
STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj);
STDMETHODIMP LockServer(BOOL fLock);
// Constructor
CClassFactory(REFCLSID rclsid, HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj))
: _rclsid(rclsid)
{
_pfnCreateInstance = pfnCreateInstance;
}
public:
REFCLSID _rclsid;
HRESULT (*_pfnCreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObj);
};
//+---------------------------------------------------------------------------
//
// CClassFactory::QueryInterface
//
//----------------------------------------------------------------------------
STDAPI CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
{
*ppvObj = this;
DllAddRef();
return NOERROR;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
//+---------------------------------------------------------------------------
//
// CClassFactory::AddRef
//
//----------------------------------------------------------------------------
STDAPI_(ULONG) CClassFactory::AddRef()
{
DllAddRef();
return g_cRefDll+1; // -1 w/ no refs
}
//+---------------------------------------------------------------------------
//
// CClassFactory::Release
//
//----------------------------------------------------------------------------
STDAPI_(ULONG) CClassFactory::Release()
{
DllRelease();
return g_cRefDll+1; // -1 w/ no refs
}
//+---------------------------------------------------------------------------
//
// CClassFactory::CreateInstance
//
//----------------------------------------------------------------------------
STDAPI CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
{
return _pfnCreateInstance(pUnkOuter, riid, ppvObj);
}
//+---------------------------------------------------------------------------
//
// CClassFactory::LockServer
//
//----------------------------------------------------------------------------
STDAPI CClassFactory::LockServer(BOOL fLock)
{
if (fLock)
{
DllAddRef();
}
else
{
DllRelease();
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// BuildGlobalObjects
//
//----------------------------------------------------------------------------
void BuildGlobalObjects(void)
{
// Build CClassFactory Objects
g_ObjectInfo[0] = new CClassFactory(c_clsidKMTipTextService, CKMTipTextService::CreateInstance);
// You can add more object info here.
// Don't forget to increase number of item for g_ObjectInfo[],
}
//+---------------------------------------------------------------------------
//
// FreeGlobalObjects
//
//----------------------------------------------------------------------------
void FreeGlobalObjects(void)
{
// Free CClassFactory Objects
for (int i = 0; i < ARRAYSIZE(g_ObjectInfo); i++)
{
if (NULL != g_ObjectInfo[i])
{
delete g_ObjectInfo[i];
g_ObjectInfo[i] = NULL;
}
}
}
//+---------------------------------------------------------------------------
//
// DllGetClassObject
//
//----------------------------------------------------------------------------
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppvObj)
{
if (g_ObjectInfo[0] == NULL)
{
EnterCriticalSection(&g_cs);
// need to check ref again after grabbing mutex
if (g_ObjectInfo[0] == NULL)
{
BuildGlobalObjects();
}
LeaveCriticalSection(&g_cs);
}
if (IsEqualIID(riid, IID_IClassFactory) ||
IsEqualIID(riid, IID_IUnknown))
{
for (int i = 0; i < ARRAYSIZE(g_ObjectInfo); i++)
{
if (NULL != g_ObjectInfo[i] &&
IsEqualGUID(rclsid, g_ObjectInfo[i]->_rclsid))
{
*ppvObj = (void *)g_ObjectInfo[i];
DllAddRef(); // class factory holds DLL ref count
return NOERROR;
}
}
}
*ppvObj = NULL;
return CLASS_E_CLASSNOTAVAILABLE;
}
//+---------------------------------------------------------------------------
//
// DllCanUnloadNow
//
//----------------------------------------------------------------------------
STDAPI DllCanUnloadNow(void)
{
if (g_cRefDll >= 0) // -1 with no refs
return S_FALSE;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// DllUnregisterServer
//
//----------------------------------------------------------------------------
STDAPI DllUnregisterServer(void)
{
CKMTipTextService::RegisterCategories(FALSE);
CKMTipTextService::UnregisterProfiles();
CKMTipTextService::UnregisterServer();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// DllRegisterServer
//
//----------------------------------------------------------------------------
STDAPI DllRegisterServer(void)
{
// register this service's profile with the tsf
if (!CKMTipTextService::RegisterServer() ||
!CKMTipTextService::RegisterProfiles() ||
!CKMTipTextService::RegisterCategories(TRUE))
{
DllUnregisterServer(); // cleanup any loose ends
return E_FAIL;
}
return S_OK;
}