// 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; }