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);
};
#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;
}