import core.exception;
import core.sys.windows.windows;
import core.sys.windows.dll;
import std.c.windows.com;
immutable HRESULT CLASS_E_CLASSNOTAVAILABLE = 0x80040111;
extern(Windows)
interface IComServer : IUnknown{
extern(Windows):
HRESULT OutMessage(const(wchar)* pszMessage);
}
// {A50BCF60-241D-49ff-BD8A-E88237A331B4}
immutable GUID IID_IComServer =
{ 0xa50bcf60, 0x241d, 0x49ff, [ 0xbd, 0x8a, 0xe8, 0x82, 0x37, 0xa3, 0x31, 0xb4 ] };
class CComServer : IComServer{
ULONG refcount = 1u;
public extern(Windows):
HRESULT QueryInterface(const(IID)* piid,void** ppvObject){
if(ppvObject is null) return E_POINTER;
*ppvObject = null;
if((*piid) == IID_IComServer || (*piid) == IID_IUnknown){
*ppvObject = cast(void*)cast(IComServer)this;
this.AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG AddRef(){
return ++refcount;
}
ULONG Release(){
if(--refcount == 0u){
//todo: オブジェクトの解体コード
return 0u;
}
return refcount;
}
HRESULT OutMessage(const(wchar)* pszMessage){
MessageBoxW(null,pszMessage,"ComServer!"w.ptr,MB_OK);
return S_OK;
}
}
// {599E9B72-0200-483f-B809-5307708B94A5}
immutable GUID CLSID_CComServer =
{ 0x599e9b72, 0x200, 0x483f, [ 0xb8, 0x9, 0x53, 0x7, 0x70, 0x8b, 0x94, 0xa5 ] };
class CComServerFactory : IClassFactory{
LONG lockcount = 0;
public extern(Windows):
HRESULT QueryInterface(const(IID)* piid,void** ppvObject){
if(ppvObject is null) return E_POINTER;
*ppvObject = null;
if((*piid) == IID_IClassFactory || (*piid) == IID_IUnknown){
*ppvObject = cast(void*)cast(IClassFactory)this;
this.AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG AddRef(){
this.LockServer(TRUE);
return 2;
}
ULONG Release(){
this.LockServer(FALSE);
return 1;
}
HRESULT CreateInstance(IUnknown UnkOuter,IID* piid,void** ppvObject){
if(ppvObject is null) return E_POINTER;
*ppvObject = null;
if(UnkOuter !is null) return CLASS_E_NOAGGREGATION;
CComServer instance;
try{
instance = new CComServer;
}catch(OutOfMemoryError error){
return E_OUTOFMEMORY;
}catch(Throwable){
return E_FAIL;
}
auto result = instance.QueryInterface(piid,ppvObject);
instance.Release();
return result;
}
HRESULT LockServer(BOOL fLock){
if(fLock)InterlockedIncrement(&lockcount);
else InterlockedDecrement(&lockcount);
return S_OK;
}
extern(D):
static HRESULT DllGetClassObject(in CLSID* pclsid,in IID* piid,void** ppvObject){
if(ppvObject is null) return E_POINTER;
*ppvObject = null;
if((*pclsid) != CLSID_CComServer)return CLASS_E_CLASSNOTAVAILABLE;
return .factory.QueryInterface(piid,ppvObject);
}
static HRESULT DllCanUnloadNow(){
return (.factory.lockcount == 0)? S_OK: S_FALSE;
}
}
__gshared CComServerFactory factory;
export extern(Windows){
HRESULT DllGetClassObject(in CLSID* pclsid,in IID* piid,void** ppvObject){
return CComServerFactory.DllGetClassObject(pclsid,piid,ppvObject);
}
HRESULT DllCanUnloadNow(){
return CComServerFactory.DllCanUnloadNow();
}
HRESULT DllRegisterServer(){
HKEY key;
auto result = RegCreateKeyExW(HKEY_CLASSES_ROOT,"CLSID\\{599E9B72-0200-483f-B809-5307708B94A5}"w.ptr,0,null,REG_OPTION_NON_VOLATILE,KEY_WRITE,null,&key,null);
if(result != ERROR_SUCCESS) return S_FALSE;
scope(exit)RegCloseKey(key);
HKEY clsinfo;
result = RegCreateKeyExW(key,"InProcServer32"w.ptr,0,null,REG_OPTION_NON_VOLATILE,KEY_WRITE,null,&clsinfo,null);
if(result != ERROR_SUCCESS) return S_FALSE;
scope(exit)RegCloseKey(clsinfo);
wchar[] path = new wchar[MAX_PATH + 10];
auto pathlength = GetModuleFileNameW(g_hInstance,path.ptr,path.length);
path.length = pathlength+1;
RegSetValueExW(clsinfo,null,0,REG_SZ,cast(BYTE*)(path.ptr),path.length * wchar.sizeof);
RegSetValueExW(clsinfo,"ThreadingModel"w.ptr,0,REG_SZ,cast(BYTE*)("Apartment"w.ptr),20);
return S_OK;
}
HRESULT DllUnregisterServer(){
auto hlib = LoadLibraryA("Advapi32.dll".ptr);
if(!hlib) return S_OK;
scope(exit)FreeLibrary(hlib);
extern(Windows) LONG function(HKEY,LPCWSTR) RegDeleteTreeW;
RegDeleteTreeW = cast(typeof(RegDeleteTreeW))GetProcAddress(hlib,"RegDeleteTreeW".ptr);
if(!RegDeleteTreeW)return S_OK;
RegDeleteTreeW(HKEY_CLASSES_ROOT,"CLSID\\{599E9B72-0200-483f-B809-5307708B94A5}"w.ptr);
return S_OK;
}
}
__gshared HINSTANCE g_hInstance;
extern(Windows)
BOOL DllMain(HINSTANCE instance,ULONG reason,VOID* reserved)
{
switch(reason){
case DLL_PROCESS_ATTACH:
g_hInstance = instance;
dll_process_attach( instance, true );
factory = new CComServerFactory;
break;
case DLL_PROCESS_DETACH:
dll_process_detach( instance, true );
break;
case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;
case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
default:
return FALSE;
}
return TRUE;
}
D言語サンプルコード集
- tk-xleader
- 記事: 158
- 登録日時: 13年前
- 連絡を取る:
D言語サンプルコード集
D言語のサンプルコードを投稿するためのトピを立ててみました。一つ目は、D言語によるWin32 COMサーバーサンプルプログラムです。