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"
|