286 lines
7.1 KiB
C++
286 lines
7.1 KiB
C++
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
|
|
#include "Private.h"
|
|
#include "Globals.h"
|
|
#include "SampleIME.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::SampleIMECLSID, CSampleIME::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;
|
|
}
|
|
|