開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 aaa
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト

レジストリへの登録
regsvr32 C:\aaa.dll

レジストリの登録を解除
regsvr32 /u C:\aaa.dll

参考
Infotip ハンドラ

aaa.def
; リンカー/入力/モジュール定義ファイル
 
LIBRARY	"aaa"
 
EXPORTS
	DllCanUnloadNow PRIVATE
	DllGetClassObject PRIVATE
	DllRegisterServer PRIVATE
	DllUnregisterServer PRIVATE
 

aaa.h
class CQueryInfo : public IQueryInfo, public IPersistFile
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
 
	// IQueryInfo
	STDMETHODIMP GetInfoTip(DWORD dwFlags, LPWSTR *ppwszTip);
	STDMETHODIMP GetInfoFlags(DWORD *pdwFlags);
 
	// IPersistFile
	STDMETHODIMP GetClassID(CLSID *pClassID);
	STDMETHODIMP IsDirty();
	STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode);
	STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember);
	STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName);
	STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName);
 
	CQueryInfo();
	~CQueryInfo();
private:
	LONG	m_cRef;
	WCHAR	m_szInfotip[256];
};
 
class CClassFactory : public IClassFactory
{
public:
	STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();
 
	// IClassFactory
	STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject);
	STDMETHODIMP LockServer(BOOL fLock);
};
 

aaa.c
#pragma comment(lib, "shlwapi.lib")
 
#include <ShlObj.h>
#include <Shlwapi.h>
#include <Windows.h>
#include "aaa.h"
 
// 関数プロトタイプ宣言
void LockModule(BOOL bLock);
BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData);
 
// グローバル変数
const CLSID	CLSID_QueryInfoSample = {0x6986c66a, 0x401f, 0x4535,
			{0x89, 0x18, 0x48, 0x07, 0x29, 0x39, 0xd2, 0xa4}};
const TCHAR	g_szClsid[] = TEXT("{6986C66A-401F-4535-8918-48072939D2A4}");
const TCHAR	g_szExt[] = TEXT(".aaa");
 
LONG		g_lLocks = 0;
HINSTANCE	g_hinstDll = NULL;
 
//==============================================================================
// CQueryInfo
 
CQueryInfo::CQueryInfo()
{
	m_cRef = 1;
	LockModule(TRUE);
}
 
CQueryInfo::~CQueryInfo()
{
	LockModule(FALSE);
}
 
STDMETHODIMP CQueryInfo::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;
	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IQueryInfo)) {
		*ppvObject = static_cast<IQueryInfo *>(this);
	} else if (IsEqualIID(riid, IID_IPersist) || IsEqualIID(riid, IID_IPersistFile)) {
		*ppvObject = static_cast<IPersistFile *>(this);
	} else {
		return E_NOINTERFACE;
	}
	AddRef();
	return S_OK;
}
 
STDMETHODIMP_(ULONG) CQueryInfo::AddRef()
{
	return InterlockedIncrement(&m_cRef);
}
 
STDMETHODIMP_(ULONG) CQueryInfo::Release()
{
	if (InterlockedDecrement(&m_cRef) == 0) {
		delete this;
		return 0;
	}
	return m_cRef;
}
 
//------------------------------------------------------------------------------
// IQueryInfo
STDMETHODIMP CQueryInfo::GetInfoTip(DWORD dwFlags, LPWSTR *ppwszTip)
{
	if (!ppwszTip) {
		return E_POINTER;
	}
	*ppwszTip = (LPWSTR)CoTaskMemAlloc((lstrlenW(m_szInfotip) + 1) * sizeof (WCHAR));
	lstrcpyW(*ppwszTip, m_szInfotip);
	return S_OK;
}
 
STDMETHODIMP CQueryInfo::GetInfoFlags(DWORD *pdwFlags)
{
	return E_NOTIMPL;
}
 
//------------------------------------------------------------------------------
// IPersistFile
STDMETHODIMP CQueryInfo::GetClassID(CLSID *pClassID)
{
	*pClassID = CLSID_QueryInfoSample;
	return S_OK;
}
 
STDMETHODIMP CQueryInfo::IsDirty()
{
	return E_NOTIMPL;
}
 
STDMETHODIMP CQueryInfo::Load(LPCOLESTR pszFileName, DWORD dwMode)
{
	lstrcpyW(m_szInfotip, L"My Infotip");
	return S_OK;
}
 
STDMETHODIMP CQueryInfo::Save(LPCOLESTR pszFileName, BOOL fRemember)
{
	return E_NOTIMPL;
}
 
STDMETHODIMP CQueryInfo::SaveCompleted(LPCOLESTR pszFileName)
{
	return E_NOTIMPL;
}
 
STDMETHODIMP CQueryInfo::GetCurFile(LPOLESTR *ppszFileName)
{
	return E_NOTIMPL;
}
 
//==============================================================================
// CClassFactory
 
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;
	if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) {
		*ppvObject = static_cast<IClassFactory *>(this);
	} else {
		return E_NOINTERFACE;
	}
	AddRef();
	return S_OK;
}
 
STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
	LockModule(TRUE);
	return 2;
}
 
STDMETHODIMP_(ULONG) CClassFactory::Release()
{
	LockModule(FALSE);
	return 1;
}
 
//------------------------------------------------------------------------------
// IClassFactory
STDMETHODIMP CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
{
	CQueryInfo	*p;
	HRESULT		hr;
 
	*ppvObject = NULL;
	if (pUnkOuter != NULL) {
		return CLASS_E_NOAGGREGATION;
	}
	p = new CQueryInfo();
	if (p == NULL) {
		return E_OUTOFMEMORY;
	}
	hr = p->QueryInterface(riid, ppvObject);
	p->Release();
	return hr;
}
 
STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
	LockModule(fLock);
	return S_OK;
}
 
//==============================================================================
// DLL Export
 
STDAPI DllCanUnloadNow(void)
{
	return (g_lLocks == 0) ? S_OK : S_FALSE;
}
 
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
	static CClassFactory serverFactory;
	HRESULT	hr;
 
	*ppv = NULL;
	if (IsEqualCLSID(rclsid, CLSID_QueryInfoSample)) {
		hr = serverFactory.QueryInterface(riid, ppv);
	} else {
		hr = CLASS_E_CLASSNOTAVAILABLE;
	}
	return hr;
}
 
STDAPI DllRegisterServer(void)
{
	TCHAR	szModulePath[MAX_PATH];
	TCHAR	szKey[256];
 
	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("ShellExtension Sample"))) {
		return E_FAIL;
	}
	GetModuleFileName(g_hinstDll, szModulePath, _countof(szModulePath));
	wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, szModulePath)) {
		return E_FAIL;
	}
	wsprintf(szKey, TEXT("CLSID\\%s\\InprocServer32"), g_szClsid);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, TEXT("ThreadingModel"), TEXT("Apartment"))) {
		return E_FAIL;
	}
	wsprintf(szKey, TEXT("%s\\shellex\\{00021500-0000-0000-C000-000000000046}"), g_szExt);
	if (!CreateRegistryKey(HKEY_CLASSES_ROOT, szKey, NULL, (LPTSTR)g_szClsid)) {
		return E_FAIL;
	}
	return S_OK;
}
 
STDAPI DllUnregisterServer(void)
{
	TCHAR	szKey[256];
 
	wsprintf(szKey, TEXT("CLSID\\%s"), g_szClsid);
	SHDeleteKey(HKEY_CLASSES_ROOT, szKey);
	SHDeleteKey(HKEY_CLASSES_ROOT, g_szExt);
	return S_OK;
}
 
BOOL APIENTRY DllMain(
	HINSTANCE	hinstDLL,
	DWORD		fdwReason,
	LPVOID		lpvReserved)
{
	switch (fdwReason) {
	case DLL_PROCESS_ATTACH:
		g_hinstDll = hinstDLL;
		DisableThreadLibraryCalls(hinstDLL);
		break;
	}
	return TRUE;
}
 
//==============================================================================
// Function
 
void LockModule(BOOL bLock)
{
	if (bLock) {
		InterlockedIncrement(&g_lLocks);
	} else {
		InterlockedDecrement(&g_lLocks);
	}
}
 
BOOL CreateRegistryKey(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszData)
{
	HKEY	hKey;
	LONG	lResult;
	DWORD	dwSize;
 
	lResult = RegCreateKeyEx(hKeyRoot, lpszKey, 0, NULL, REG_OPTION_NON_VOLATILE,
		KEY_WRITE, NULL, &hKey, NULL);
	if (lResult != ERROR_SUCCESS) {
		return FALSE;
	}
	if (lpszData != NULL) {
		dwSize = (lstrlen(lpszData) + 1) * sizeof (TCHAR);
	} else {
		dwSize = 0;
	}
	RegSetValueEx(hKey, lpszValue, 0, REG_SZ, (LPBYTE)lpszData, dwSize);
	RegCloseKey(hKey);
	return TRUE;
}
 
最終更新:2012年09月01日 16:44