HelloATL.cpp 

////////////////////////////////////////////////////
//
// HelloATL.cpp 
//
// 用ATL实现一个COM进程内服务器
//

#include <windows.h>
#include "hello.h"
#define IID_DEFINED
#include "hello_i.c"

#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include <atlimpl.cpp>

class ATL_NO_VTABLE CHelloATL 
: public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CHelloATL, &CLSID_HelloATL>,
public IHello
{
public:
BEGIN_COM_MAP(CHelloATL)
COM_INTERFACE_ENTRY(IHello)
END_COM_MAP()

DECLARE_REGISTRY_RESOURCEID(1)

STDMETHODIMP Hello(BSTR bstr)
{
MessageBoxW(0, bstr ? bstr : OLESTR(""), L"Hello!", MB_SETFOREGROUND);
return S_OK;
}
};

CComModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_HelloATL, CHelloATL)
END_OBJECT_MAP()

BOOL WINAPI DllMain(HINSTANCE h, DWORD dwReason, void *)
{
if (dwReason == DLL_PROCESS_ATTACH)
_Module.Init(ObjectMap, h);
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE;
}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{ return _Module.GetClassObject(rclsid, riid, ppv); }

STDAPI DllCanUnloadNow(void)
{ return _Module.GetLockCount() ? S_FALSE : S_OK; }

STDAPI DllRegisterServer(void)
{ return _Module.RegisterServer(TRUE); }

STDAPI DllUnregisterServer(void)
{ return _Module.UnregisterServer(); }


HelloATL.rc 

1 TYPELIB "hello.tlb"
1 REGISTRY "HelloATL.rgs"

HelloATL.rgs 

HKCR {
NoRemove CLSID {
ForceRemove {D50841E2-9AAA-11d0-8C20-0080C73925BA} = s 'HelloATL' {
InprocServer32 = s '%MODULE%' {
val ThreadingModel = s 'Both'
}
}
}
}

HelloSDK.cpp 

////////////////////////////////////////////////////
//
// HelloSDK.cpp
//
// 用 SDK 实现的 COM 进程内服务器
//

#include <windows.h>
#include "hello.h"
#define IID_DEFINED
#include "hello_i.c"

LONG g_cLocks = 0;
inline LONG LockModule(void) { return InterlockedIncrement(&g_cLocks); }
inline LONG UnlockModule(void) { return InterlockedDecrement(&g_cLocks); }

class CHelloSDK : public IHello {
LONG m_dwRef;
public:
CHelloSDK(void) : m_dwRef(0) { LockModule(); }
virtual ~CHelloSDK(void) { UnlockModule(); }

STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
if (riid == IID_IUnknown || riid == IID_IHello)
*ppv = (IHello*)this;
else
return (*ppv = 0), E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}

STDMETHODIMP_(ULONG) AddRef(void) 
{ return InterlockedIncrement(&m_dwRef); }

STDMETHODIMP_(ULONG) Release(void) { 
LONG res = InterlockedIncrement(&m_dwRef); 
if (res == 0)
delete this;
return res;
}

STDMETHODIMP Hello(BSTR bstr) {
MessageBoxW(0, bstr ? bstr : OLESTR(""), L"Hello!", MB_SETFOREGROUND);
return S_OK;
}
};

HINSTANCE g_hInstance = 0;

BOOL WINAPI DllMain(HINSTANCE h, DWORD dwReason, void *) {
if (dwReason == DLL_PROCESS_ATTACH)
g_hInstance = h;
return TRUE;
}

class CHelloClassObject : public IClassFactory {
public:
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {
if (riid == IID_IUnknown || riid == IID_IClassFactory)
*ppv = (IClassFactory *)this;
else
return (*ppv = 0), E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}

STDMETHODIMP_(ULONG) AddRef(void) { return LockModule(); }
STDMETHODIMP_(ULONG) Release(void) { return UnlockModule(); }


STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) {
*ppv = 0;
if (pUnkOuter) return CLASS_E_NOAGGREGATION;
CHelloSDK *p = new CHelloSDK;
if (!p) return E_OUTOFMEMORY;
p->AddRef();
HRESULT hr = p->QueryInterface(riid, ppv);
p->Release();
return hr;
}

STDMETHODIMP LockServer(BOOL b) 
{ return (b ? LockModule() : UnlockModule()), S_OK; }
};

CHelloClassObject g_classObject;

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { 
if (rclsid == CLSID_HelloSDK)
return g_classObject.QueryInterface(riid, ppv);
return (*ppv = 0), CLASS_E_CLASSNOTAVAILABLE;
}

STDAPI DllCanUnloadNow(void)
{ return g_cLocks ? S_FALSE : S_OK; }

STDAPI DllRegisterServer(void) { 
char szFileName[MAX_PATH]; OLECHAR wszFileName[MAX_PATH];
GetModuleFileName(g_hInstance, szFileName, MAX_PATH);
mbstowcs(wszFileName, szFileName, MAX_PATH);

ITypeLib *ptl = 0;
HRESULT hr = LoadTypeLib(wszFileName, &ptl);
if (FAILED(hr)) return hr;
hr = RegisterTypeLib(ptl, wszFileName, 0);
ptl->Release();
if (FAILED(hr)) return hr;

LONG err = RegSetValueA(HKEY_CLASSES_ROOT, 
"CLSID\\{D50841E3-9AAA-11d0-8C20-0080C73925BA}",
REG_SZ, "HelloSDK", 9);
if (err != ERROR_SUCCESS) goto error_exit;

HKEY hkey;
err = RegCreateKeyA(HKEY_CLASSES_ROOT, 
"CLSID\\{D50841E3-9AAA-11d0-8C20-0080C73925BA}"
"\\InprocServer32", &hkey);
if (err != ERROR_SUCCESS) goto error_exit;

err = RegSetValueExA(hkey, 0, 0, REG_SZ, (BYTE*)szFileName, 
strlen(szFileName) + 1);
if (err != ERROR_SUCCESS) 
err = RegSetValueExA(hkey,"ThreadingModel",0,REG_SZ, (BYTE*)"Both", 5);
RegCloseKey(hkey);
error_exit:
return (err == ERROR_SUCCESS) ? S_OK :
MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, err);
}

STDAPI DllUnregisterServer(void) { 
LONG err = RegDeleteKeyA(HKEY_CLASSES_ROOT, 
"CLSID\\{D50841E3-9AAA-11d0-8C20-0080C73925BA}"
"\\InprocServer32");
if (err != ERROR_SUCCESS) goto error_exit;

err = RegDeleteKeyA(HKEY_CLASSES_ROOT, 
"CLSID\\{D50841E3-9AAA-11d0-8C20-0080C73925BA}");
error_exit:
return (err == ERROR_SUCCESS) ? S_OK :
MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, err);
}


HelloSDK.rc 

1 TYPELIB "Hello.tlb"