ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

最小のUMDFドライバ

DllMain

UMDFのデバイスドライバはDLLとして実装することになっている。そのため、一般のDLLと同様にDllMain関数を実装する必要がある。
UMDFとしては特に何か実装しなければならないものはないので今回はとりあえず空の関数を置いておく。(もちろん、何か書いてもよい。)

BOOL WINAPI DllMain( HINSTANCE hModule, DWORD dwReason, PVOID )
{
	return TRUE;
}

DllGetClassObject

次に、DLL を読み込んだフレームワークは、このデバイスドライバのCOMオブジェクトを生成するためのClassFactoryを取得しようとする。
そのClassFactoryオブジェクトを生成するのが、DllGetClassObject関数である。

// {EAE3786C-9C06-404d-953E-3788AF1BA9BD}
static const GUID CLSID_MyDriverCoClass = { 0xeae3786c, 0x9c06, 0x404d, { 0x95, 0x3e, 0x37, 0x88, 0xaf, 0x1b, 0xa9, 0xbd } };

HRESULT STDAPICALLTYPE DllGetClassObject( __in REFCLSID ClassId, __in REFIID InterfaceId, __deref_out LPVOID *Interface )
{
	// サポートする CLSID と一致するか
	if( !IsEqualCLSID( ClassId, CLSID_MyDriverCoClass ) ) {
		return CLASS_E_CLASSNOTAVAILABLE;
	}

	CClassFactory* Factory = new CClassFactory();
	if( Factory == NULL ) return E_OUTOFMEMORY;

	// 要求されたインターフェースを引き出す
	HRESULT hr = Factory->QueryInterface( InterfaceId, Interface );

	// Interface が所有しているので、一時変数は解放
	Factory->Release();

	return hr;
}

ここで突然出てきたCLSID_MyDriverCoClassは、これから書くデバイスドライバを識別するための固有のIDである。システム全体でユニークであればいいが、念のためきちんとguidgen.exeなどのツールで生成するべきである。
また、ここで一度Factory変数にnewした後にQueryInterfaceでインターフェースを引き出しているが、この段階でInterfaceも同じインスタンスを所有していることになる。そのため、関数から戻る前にRelease関数でFactory変数の所有権を破棄しないとメモリリークが発生する。
わかりやすさのためにRelease関数を呼んでいるが、実際にはスマートポインタなどを用いて実装するべきであろう。