D言語サンプルコード集

ネイティブコードを生成する言語界期待の若手D言語を広めましょう。
D言語に関することなら、質問、雑談等なんでもOKです。
返信
アバター
tk-xleader
記事: 153
登録日時: 8年前
連絡を取る:

D言語サンプルコード集

#1

投稿記事 by tk-xleader » 6年前

 D言語のサンプルコードを投稿するためのトピを立ててみました。一つ目は、D言語によるWin32 COMサーバーサンプルプログラムです。

コード:

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言語を広めよう” へ戻る