* chore: settle line endings in .gitattributes Nothing declared line endings, so each file kept whatever the contributor's core.autocrlf produced when it was added: 382 text files ended up LF and 50 CRLF. The CRLF ones are the hazard. Editing one on macOS or Linux writes LF lines into it, and clang-format rejects a file that mixes both -- which is how `quality / Workflow validation` went red on KeyStateCategory.h, where three lines out of a CRLF file had arrived as LF. #309 converted those three lines back and left the other 49 files loaded. The repository now declares LF and the working trees are renormalized to match, so the failure mode is gone rather than deferred to whichever of those files is edited next. The four binary types are declared rather than left to git's heuristic, which decides from the first 8000 bytes alone. user_dict.dat is caught by that sample today only because the 40-byte seed is almost entirely NUL. Verified: the 56 renormalized files are byte-identical to their old contents once CR is stripped, no text file in the index still carries CRLF, and scripts/format.sh --check passes. * chore: skip the line-ending renormalization in blame The commit before this one rewrote every line of 56 files without changing a character of them, which is what this file exists to hide.
277 lines
6.8 KiB
C++
277 lines
6.8 KiB
C++
#include "Private.h"
|
|
#include "Globals.h"
|
|
#include "MetasequoiaIME.h"
|
|
|
|
// from Register.cpp
|
|
BOOL RegisterProfiles();
|
|
void UnregisterProfiles();
|
|
BOOL RegisterCategories();
|
|
void UnregisterCategories();
|
|
BOOL RegisterServer();
|
|
void UnregisterServer();
|
|
|
|
void FreeGlobalObjects(void);
|
|
|
|
class CClassFactory;
|
|
static CClassFactory *classFactoryObjects[1] = {nullptr};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllAddRef
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void DllAddRef(void)
|
|
{
|
|
InterlockedIncrement(&Global::dllRefCount);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllRelease
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void DllRelease(void)
|
|
{
|
|
if (InterlockedDecrement(&Global::dllRefCount) < 0)
|
|
{
|
|
EnterCriticalSection(&Global::CS);
|
|
|
|
if (nullptr != classFactoryObjects[0])
|
|
{
|
|
FreeGlobalObjects();
|
|
}
|
|
assert(Global::dllRefCount == -1);
|
|
|
|
LeaveCriticalSection(&Global::CS);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CClassFactory declaration with IClassFactory Interface
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CClassFactory : public IClassFactory
|
|
{
|
|
public:
|
|
// IUnknown methods
|
|
STDMETHODIMP QueryInterface(REFIID riid, _Outptr_ void **ppvObj);
|
|
STDMETHODIMP_(ULONG) AddRef(void);
|
|
STDMETHODIMP_(ULONG) Release(void);
|
|
|
|
// IClassFactory methods
|
|
STDMETHODIMP CreateInstance(_In_opt_ IUnknown *pUnkOuter, _In_ REFIID riid, _COM_Outptr_ 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, _COM_Outptr_ void **ppvObj);
|
|
|
|
private:
|
|
CClassFactory &operator=(const CClassFactory &rhn)
|
|
{
|
|
rhn;
|
|
};
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CClassFactory::QueryInterface
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CClassFactory::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
|
|
{
|
|
*ppvObj = this;
|
|
DllAddRef();
|
|
return NOERROR;
|
|
}
|
|
*ppvObj = nullptr;
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CClassFactory::AddRef
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) CClassFactory::AddRef()
|
|
{
|
|
DllAddRef();
|
|
return (Global::dllRefCount + 1);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CClassFactory::Release
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) CClassFactory::Release()
|
|
{
|
|
DllRelease();
|
|
return (Global::dllRefCount + 1);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CClassFactory::CreateInstance
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CClassFactory::CreateInstance(_In_opt_ IUnknown *pUnkOuter, _In_ REFIID riid, _COM_Outptr_ 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)
|
|
{
|
|
classFactoryObjects[0] =
|
|
new (std::nothrow) CClassFactory(Global::MetasequoiaIMECLSID, CMetasequoiaIME::CreateInstance);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// FreeGlobalObjects
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void FreeGlobalObjects(void)
|
|
{
|
|
for (int i = 0; i < ARRAYSIZE(classFactoryObjects); i++)
|
|
{
|
|
if (nullptr != classFactoryObjects[i])
|
|
{
|
|
delete classFactoryObjects[i];
|
|
classFactoryObjects[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
DeleteObject(Global::defaultlFontHandle);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllGetClassObject
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
_Check_return_ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ void **ppv)
|
|
{
|
|
if (classFactoryObjects[0] == nullptr)
|
|
{
|
|
EnterCriticalSection(&Global::CS);
|
|
|
|
// need to check ref again after grabbing mutex
|
|
if (classFactoryObjects[0] == nullptr)
|
|
{
|
|
BuildGlobalObjects();
|
|
}
|
|
|
|
LeaveCriticalSection(&Global::CS);
|
|
}
|
|
|
|
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
|
|
{
|
|
for (int i = 0; i < ARRAYSIZE(classFactoryObjects); i++)
|
|
{
|
|
if (nullptr != classFactoryObjects[i] && IsEqualGUID(rclsid, classFactoryObjects[i]->_rclsid))
|
|
{
|
|
*ppv = (void *)classFactoryObjects[i];
|
|
DllAddRef(); // class factory holds DLL ref count
|
|
return NOERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppv = nullptr;
|
|
|
|
return CLASS_E_CLASSNOTAVAILABLE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllCanUnloadNow
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI DllCanUnloadNow(void)
|
|
{
|
|
if (Global::dllRefCount >= 0)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllUnregisterServer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
UnregisterProfiles();
|
|
UnregisterCategories();
|
|
UnregisterServer();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// DllRegisterServer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI DllRegisterServer(void)
|
|
{
|
|
if ((!RegisterServer()) || (!RegisterProfiles()) || (!RegisterCategories()))
|
|
{
|
|
DllUnregisterServer();
|
|
return E_FAIL;
|
|
}
|
|
return S_OK;
|
|
}
|