不依賴 ATL/MFC,以純 C++ 實作標準進程內(In-Process)COM 伺服器,深入理解 IClassFactory、IUnknown、DllGetClassObject 等核心機制。適用於 Shell Extension 等輕量級 COM 元件開發。
#include <comdef.h>
// CLSID
__declspec(selectany) GUID CLSID_Mine = {0xdc186800, 0x657f, 0x11d4, {0xb0,0xb5,0x0,0x50,0xba,0xbf,0xc9,0x4}};
// 介面 IID 與方法
__interface __declspec(uuid("F614FB00-6702-11d4-B0B7-0050BABFC904"))
ImyInterface : public IUnknown {
STDMETHOD(Square)(long* pVal) PURE;
STDMETHOD(Cube)(long* pVal) PURE;
};
class CmyInterface : public CComBase<>, public InterfaceImpl<ImyInterface> {
public:
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv);
STDMETHOD(Square)(long* pVal);
STDMETHOD(Cube)(long* pVal);
};
STDMETHODIMP CmyInterface::QueryInterface(REFIID riid, LPVOID* ppv) {
*ppv = NULL;
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, __uuidof(ImyInterface))) {
*ppv = (ImyInterface*)this; _AddRef(); return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP CmyInterface::Square(long* pVal) { *pVal = (*pVal) * (*pVal); return S_OK; }
STDMETHODIMP CmyInterface::Cube(long* pVal) { *pVal = (*pVal) * (*pVal) * (*pVal); return S_OK; }
template <class T> class CMultiCreator { // 多例工廠
public: T* CreateObject() { return new T; }
};
class CClassFactory : public CComBase<>, public InterfaceImpl<IClassFactory>, public CMultiCreator<CmyInterface> {
public:
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv);
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObj);
STDMETHODIMP LockServer(BOOL) { return S_OK; }
};
STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObj) {
*ppvObj = NULL;
if (pUnkOuter) return CLASS_E_NOAGGREGATION;
m_pObj = CreateObject(); // CmyInterface 實例
if (!m_pObj) return E_OUTOFMEMORY;
HRESULT hr = m_pObj->QueryInterface(riid, ppvObj);
if (FAILED(hr)) delete m_pObj;
return hr;
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppvOut) {
*ppvOut = NULL;
if (IsEqualIID(rclsid, CLSID_Mine)) {
CClassFactory* pcf = new CClassFactory;
return pcf->QueryInterface(riid, ppvOut);
}
return CLASS_E_CLASSNOTAVAILABLE;
}
ImyInterface* pMine = NULL;
CoCreateInstance(CLSID_Mine, NULL, CLSCTX_INPROC_SERVER,
__uuidof(ImyInterface), (void**)&pMine);
long val = 5; pMine->Square(&val); // val = 25
pMine->Cube(&val); // val = 125
pMine->Release();
CComBase 提供參考計數(_AddRef/_Release)。InterfaceImpl<T> 實作介面查詢轉發。HKCR\CLSID\{CLSID}\InprocServer32 指向 DLL 路徑。