📄 aggregate.cpp
字号:
// support aggregation...
// the unknown of the object we're aggregating
// must be IUnknown for aggregation...
IUnknown *m_pUnkAggregate;
};
//-------------------------------------------------------------------
// Creating the inner object for reuse...
// CoMyEngine::CreateInnerObject
//-------------------------------------------------------------------
void CoThesaurus::CreateInnerObject()
{
// support aggregation...
// The aggregation law of COM require us to create
// the inner object, and requesting only for IUnknown
// and nothing else!!!
MULTI_QI mqi[] = { {&IID_IUnknown, NULL, S_OK} };
// Notice "this" as the second argument...
// reuse by aggregation!!!
// Outer unknown is this object--uses the inner object.
// This argument is the magic that get's our
// object (CLSID_Thesaurus) to reuse the
// inner object (CLSID_OcrEngine)
// Special support here in case the inner object
// code happened to cause a delete of this object.
// Remember at this moment, the reference count
// that we are keeping for this object is 0, since
// we're still in the constructor.
// Here's a potential probelm: The inner object
// QIs for one of our (this object's) interfaces
// (refcount=1) and releases it (refcount=0),
// causing a premature delete of this object.
// To prevent this, we temporarily increment and decrement our
// reference count. However, don't call Release, since
// it deletes our object. You'd have to use this technique:
InterlockedIncrement(&m_lRefCount);
HRESULT hr = CoCreateInstanceEx(CLSID_OcrEngine,
this,
CLSCTX_SERVER,
NULL,
sizeof(mqi)/sizeof(mqi[0]),
mqi);
InterlockedDecrement(&m_lRefCount);
if (SUCCEEDED(hr) && SUCCEEDED(mqi[0].hr)) {
m_pUnkAggregate = reinterpret_cast<IUnknown *>(mqi[0].pItf);
} else {
DisplayStatus(TEXT("Failed to create inner object..."), S_OK);
wprintf(TEXT("You need to use the Aggregatable")
TEXT("Version of CLSID_OcrEngine\n")
TEXT("It lives in code\\basics\\reuse\\inner\n")
TEXT("Version of CLSID_OcrEngine\n"));
assert(false);
}
}
//-------------------------------------------------------------------
// CoThesaurus::CreateObject - static function to create an
// CoThesaurus object
//-------------------------------------------------------------------
HRESULT CoThesaurus::CreateObject(LPUNKNOWN pUnkOuter,
REFIID riid,
void** ppv)
{
*ppv = NULL;
// CoThesaurus doesn't support aggregation
if (pUnkOuter != NULL) { return CLASS_E_NOAGGREGATION; }
CoThesaurus * pThesaurus = new CoThesaurus;
if (pThesaurus == NULL) { return E_OUTOFMEMORY; }
HRESULT hr = pThesaurus->QueryInterface(riid, ppv);
if (FAILED(hr)) { delete pThesaurus; }
return hr;
}
//-------------------------------------------------------------------
// CoThesaurus::QueryInterface
//-------------------------------------------------------------------
STDMETHODIMP
CoThesaurus::QueryInterface(REFIID riid, void** ppv)
{
if (ppv==NULL) { return E_INVALIDARG; }
if (riid==IID_IUnknown) {
*ppv= static_cast<IThesaurus *>(this);
} else if (riid==IID_IThesaurus) {
*ppv= static_cast<IThesaurus *>(this);
} else if (riid==IID_IOcr||riid==IID_ISpell) {
// Support Aggregation...
// interfaces belong to the reused object
// let the inner object handle this request!
return m_pUnkAggregate->QueryInterface(riid, ppv) ;
} else {
*ppv=NULL; return E_NOINTERFACE ;
}
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
return S_OK;
}
//*******************************************************************
//*******************************************************************
//*** Class Factory: manufacturing CoThesaurus objects
//*******************************************************************
//*******************************************************************
class CoThesaurusFactory : public IClassFactory
{
public:
// IUnknown Methods
STDMETHODIMP QueryInterface (REFIID riid, void** ppv);
STDMETHODIMP_(ULONG) AddRef(void)
{ return 1; }
STDMETHODIMP_(ULONG) Release(void)
{ return 1; }
// IClassFactory Methods
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,
REFIID riid,
void **ppv)
{
// call CoThesaurus's static function to create
// a CoThesaurus component object
return CoThesaurus::CreateObject(pUnkOuter, riid, ppv);
}
STDMETHODIMP LockServer(BOOL fLock)
{
if (fLock) {
ComponentAddRef();
} else {
ComponentRelease();
}
return S_OK;
}
};
//-------------------------------------------------------------------
// Singleton factory instance that manufacture CoCorEngine
// component objects
//-------------------------------------------------------------------
CoThesaurusFactory g_ThesaurusClassFactory;
//-------------------------------------------------------------------
// CoThesaurusFactory::QueryInterface
//-------------------------------------------------------------------
STDMETHODIMP
CoThesaurusFactory::QueryInterface(REFIID riid, void** ppv)
{
if (ppv==NULL) { return E_INVALIDARG; }
if (riid==IID_IUnknown) {
*ppv= static_cast<IClassFactory *>(this);
} else if (riid==IID_IClassFactory) {
*ppv= static_cast<IClassFactory *>(this);
} else {
*ppv=NULL; return E_NOINTERFACE ;
}
reinterpret_cast<IUnknown *>(*ppv)->AddRef();
return S_OK;
}
//*******************************************************************
//*******************************************************************
//*** Main Program
//*******************************************************************
//*******************************************************************
void main(int argc, char **argv)
{
DisplayStatus(TEXT("Server: Started"), S_OK);
g_hExitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
assert(g_hExitEvent);
// registration if required
if (argc > 1) {
if (_stricmp(argv[1], "-RegServer")==0){
RegisterComponent();
DisplayStatus(TEXT("Registered..."), S_OK);
return ;
}
if (_stricmp(argv[1], "-UnRegServer")==0){
UnregisterComponent();
DisplayStatus(TEXT("Unregistered..."), S_OK);
return ;
}
}
// Init COM
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
assert(SUCCEEDED(hr));
// Register Thesaurus Class Factory with COM
DWORD dwRegister;
hr = CoRegisterClassObject(CLSID_Thesaurus,
&g_ThesaurusClassFactory,
CLSCTX_SERVER,
REGCLS_MULTIPLEUSE,
&dwRegister);
assert(SUCCEEDED(hr));
// we don't have to do this, but it's a good habit
g_ThesaurusClassFactory.Release();
// sit and wait until CoThesaurus object is used
WaitForSingleObject(g_hExitEvent, INFINITE);
// revoke the factory from public view
CoRevokeClassObject(dwRegister);
// uninitialize
CoUninitialize();
DisplayStatus(TEXT("Server shutting down in 5 seconds..."), S_OK);
Sleep(5000);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -