2025-11-28 00:35:46 +09:00

744 lines
19 KiB
C++

/**************************************************************************
THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright 2002 Microsoft Corporation. All Rights Reserved.
**************************************************************************/
/**************************************************************************
File: ADEvent.cpp
Description:
**************************************************************************/
/**************************************************************************
#include statements
**************************************************************************/
#include <olectl.h>
#include <shlobj.h>
#include <dsclient.h>
#include "ADEvent.h"
#include <initguid.h>
#include <dsadmin.h>
#include <tchar.h>
#include <stdio.h>
/**************************************************************************
private function prototypes
**************************************************************************/
int WideCharToLocal(LPTSTR pLocal, size_t buffSize, LPWSTR pWide, DWORD dwChars);
int LocalToWideChar(LPWSTR pWide, size_t buffSize, LPTSTR pLocal, DWORD dwChars);
BOOL DeleteEntireKey(HKEY hKey, LPTSTR pszSubKey);
/**************************************************************************
global variables and definitions
**************************************************************************/
// {08698521-653C-4386-B206-DFA3C0F904E5}
DEFINE_GUID(CLSID_AdminEventHandler,
0x8698521, 0x653c, 0x4386, 0xb2, 0x6, 0xdf, 0xa3, 0xc0, 0xf9, 0x4, 0xe5);
HINSTANCE g_hInst;
UINT g_DllRefCount;
TCHAR g_szMainTitle[] = TEXT("Sample AD Admin Notification Handler");
/**************************************************************************
DllMain
**************************************************************************/
extern "C" BOOL WINAPI DllMain( HINSTANCE hInstance,
DWORD dwReason,
LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
break;
}
return TRUE;
}
/**************************************************************************
DllCanUnloadNow
**************************************************************************/
STDAPI DllCanUnloadNow(void)
{
return (g_DllRefCount == 0) ? S_OK : S_FALSE;
}
/**************************************************************************
DllGetClassObject
**************************************************************************/
STDAPI DllGetClassObject( REFCLSID rclsid,
REFIID riid,
LPVOID *ppReturn)
{
*ppReturn = NULL;
//if we don't support this classid, return the proper error code
if(!IsEqualCLSID(rclsid, CLSID_AdminEventHandler))
{
return CLASS_E_CLASSNOTAVAILABLE;
}
//create a CClassFactory object and check it for validity
CClassFactory *pClassFactory = new CClassFactory();
if(NULL == pClassFactory)
{
return E_OUTOFMEMORY;
}
//get the QueryInterface return for our return value
HRESULT hr = pClassFactory->QueryInterface(riid, ppReturn);
//call Release to decement the ref count - creating the object set it to one
//and QueryInterface incremented it - since its being used externally (not by
//us), we only want the ref count to be 1
pClassFactory->Release();
//return the result from QueryInterface
return hr;
}
/**************************************************************************
DllRegisterServer
**************************************************************************/
typedef struct _REGSTRUCT
{
HKEY hRootKey;
LPTSTR lpszSubKey;
LPTSTR lpszValueName;
LPTSTR lpszData;
}REGSTRUCT, *LPREGSTRUCT;
STDAPI DllRegisterServer(void)
{
int i;
HKEY hKey;
LRESULT lResult;
DWORD dwDisp;
TCHAR szSubKey[MAX_PATH];
TCHAR szCLSID[MAX_PATH];
TCHAR szModule[MAX_PATH];
LPWSTR pwsz;
//get the CLSID in string form
StringFromIID(CLSID_AdminEventHandler, &pwsz);
if(pwsz)
{
WideCharToLocal(szCLSID, ARRAYSIZE(szCLSID), pwsz, ARRAYSIZE(szCLSID));
//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
if(pMalloc)
{
pMalloc->Free(pwsz);
pMalloc->Release();
}
}
//get this DLL's path and file name
GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule));
//register the CLSID entries
REGSTRUCT ClsidEntries[] = {HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), NULL, g_szMainTitle,
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocServer32"), NULL, TEXT("%s"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Apartment"),
NULL, NULL, NULL, NULL};
for(i = 0; ClsidEntries[i].hRootKey; i++)
{
//Create the sub key string.
_stprintf_s(szSubKey, ARRAYSIZE(szSubKey), ClsidEntries[i].lpszSubKey, szCLSID);
lResult = RegCreateKeyEx( ClsidEntries[i].hRootKey,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp);
if(NOERROR == lResult)
{
TCHAR szData[MAX_PATH] = TEXT("");
//if necessary, create the value string
_stprintf_s(szData, ARRAYSIZE(szData), ClsidEntries[i].lpszData, szModule);
lResult = RegSetValueEx( hKey,
ClsidEntries[i].lpszValueName,
0,
REG_SZ,
(LPBYTE)szData,
lstrlen(szData) + 1);
RegCloseKey(hKey);
}
else
{
return SELFREG_E_CLASS;
}
}
return S_OK;
}
/**************************************************************************
DllUnregisterServer()
**************************************************************************/
STDAPI DllUnregisterServer(VOID)
{
LPWSTR pwsz;
TCHAR szCLSID[MAX_PATH];
TCHAR szSubKey[MAX_PATH];
//get the CLSID in string form
StringFromIID(CLSID_AdminEventHandler, &pwsz);
if(pwsz)
{
WideCharToLocal(szCLSID, ARRAYSIZE(szCLSID), pwsz, ARRAYSIZE(szCLSID));
//free the string
CoTaskMemFree(pwsz);
}
else
{
return E_FAIL;
}
//delete the object's registry entries
_stprintf_s(szSubKey, ARRAYSIZE(szSubKey), TEXT("CLSID\\%s"), szCLSID);
DeleteEntireKey(HKEY_CLASSES_ROOT, szSubKey);
return S_OK;
}
///////////////////////////////////////////////////////////////////////////
//
// IClassFactory implementation
//
/**************************************************************************
CClassFactory::CClassFactory
**************************************************************************/
CClassFactory::CClassFactory()
{
m_ObjRefCount = 1;
g_DllRefCount++;
}
/**************************************************************************
CClassFactory::~CClassFactory
**************************************************************************/
CClassFactory::~CClassFactory()
{
g_DllRefCount--;
}
/**************************************************************************
CClassFactory::QueryInterface
**************************************************************************/
STDMETHODIMP CClassFactory::QueryInterface( REFIID riid,
LPVOID FAR * ppReturn)
{
*ppReturn = NULL;
if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = (LPUNKNOWN)(LPCLASSFACTORY)this;
}
if(IsEqualIID(riid, IID_IClassFactory))
{
*ppReturn = (LPCLASSFACTORY)this;
}
if(*ppReturn)
{
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
CClassFactory::AddRef
**************************************************************************/
STDMETHODIMP_(DWORD) CClassFactory::AddRef()
{
return ++m_ObjRefCount;
}
/**************************************************************************
CClassFactory::Release
**************************************************************************/
STDMETHODIMP_(DWORD) CClassFactory::Release()
{
if(--m_ObjRefCount == 0)
{
delete this;
return 0;
}
return m_ObjRefCount;
}
/**************************************************************************
CClassFactory::CreateInstance
**************************************************************************/
STDMETHODIMP CClassFactory::CreateInstance( LPUNKNOWN pUnknown,
REFIID riid,
LPVOID FAR * ppObject)
{
*ppObject = NULL;
if(pUnknown != NULL)
{
return CLASS_E_NOAGGREGATION;
}
//add implementation specific code here
CAdminNotifyHandler *pAdminNotifyHandler = new CAdminNotifyHandler;
if(NULL == pAdminNotifyHandler)
{
return E_OUTOFMEMORY;
}
//get the QueryInterface return for our return value
HRESULT hr = pAdminNotifyHandler->QueryInterface(riid, ppObject);
//call Release to decement the ref count
pAdminNotifyHandler->Release();
//return the result from QueryInterface
return hr;
}
/**************************************************************************
CClassFactory::LockServer
**************************************************************************/
STDMETHODIMP CClassFactory::LockServer(BOOL)
{
return E_NOTIMPL;
}
///////////////////////////////////////////////////////////////////////////
//
// CAdminNotifyHandler implementation
//
/**************************************************************************
CAdminNotifyHandler::CAdminNotifyHandler()
**************************************************************************/
CAdminNotifyHandler::CAdminNotifyHandler()
{
m_ObjRefCount = 1;
g_DllRefCount++;
m_pdoFrom = NULL;
m_pdoTo = NULL;
}
/**************************************************************************
CAdminNotifyHandler::~CAdminNotifyHandler()
**************************************************************************/
CAdminNotifyHandler::~CAdminNotifyHandler()
{
g_DllRefCount--;
End();
}
///////////////////////////////////////////////////////////////////////////
//
// IUnknown Implementation
//
/**************************************************************************
CAdminNotifyHandler::QueryInterface
**************************************************************************/
STDMETHODIMP CAdminNotifyHandler::QueryInterface( REFIID riid,
LPVOID FAR * ppReturn)
{
*ppReturn = NULL;
//IUnknown
if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = (LPVOID)this;
}
//IDsAdminNotifyHandler
if(IsEqualIID(riid, IID_IDsAdminNotifyHandler))
{
*ppReturn = (IDsAdminNotifyHandler*)this;
}
if(*ppReturn)
{
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
CAdminNotifyHandler::AddRef
**************************************************************************/
STDMETHODIMP_(DWORD) CAdminNotifyHandler::AddRef()
{
return ++m_ObjRefCount;
}
/**************************************************************************
CAdminNotifyHandler::Release
**************************************************************************/
STDMETHODIMP_(DWORD) CAdminNotifyHandler::Release()
{
if(--m_ObjRefCount == 0)
{
delete this;
return 0;
}
return m_ObjRefCount;
}
///////////////////////////////////////////////////////////////////////////
//
// IDsAdminNotifyHandler Implementation
//
/**************************************************************************
CAdminNotifyHandler::Initialize()
**************************************************************************/
STDMETHODIMP CAdminNotifyHandler::Initialize(IDataObject* pExtraInfo,
ULONG* puEventFlags)
{
OutputDebugString(TEXT("CAdminNotifyHandler::Initialize\n"));
if(NULL == puEventFlags)
{
return E_INVALIDARG;
}
//Tell the host which events the handler wants to receive.
*puEventFlags = DSA_NOTIFY_ALL;
return S_OK;
}
/**************************************************************************
CAdminNotifyHandler::Begin()
**************************************************************************/
STDMETHODIMP CAdminNotifyHandler::Begin(ULONG uEvent,
IDataObject* pArg1,
IDataObject* pArg2,
ULONG* puFlags,
BSTR* pBstr)
{
OutputDebugString(TEXT("CAdminNotifyHandler::Begin\n"));
if(NULL == pArg1)
{
return E_INVALIDARG;
}
if(NULL == puFlags)
{
return E_INVALIDARG;
}
if(NULL == pBstr)
{
return E_INVALIDARG;
}
//release any data objects this handler may already have
End();
//save the data objects
pArg1->QueryInterface(IID_IDataObject, (LPVOID*)&m_pdoFrom);
if(NULL != pArg2)
{
pArg2->QueryInterface(IID_IDataObject, (LPVOID*)&m_pdoTo);
}
STGMEDIUM stm;
FORMATETC fe;
HRESULT hr;
fe.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pArg1->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
LPDSOBJECTNAMES pdson = (LPDSOBJECTNAMES)GlobalLock(stm.hGlobal);
if(pdson)
{
LPWSTR pwszName = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetName);
LPWSTR pwszClass = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetClass);
OutputDebugString(TEXT("\t"));
OutputDebugStringW(pwszClass);
OutputDebugString(TEXT(" - "));
OutputDebugStringW(pwszName);
OutputDebugString(TEXT("\n"));
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
if(pArg2)
{
fe.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pArg2->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
LPDSOBJECTNAMES pdson = (LPDSOBJECTNAMES)GlobalLock(stm.hGlobal);
if(pdson)
{
LPWSTR pwszName = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetName);
LPWSTR pwszClass = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetClass);
OutputDebugString(TEXT("\t"));
OutputDebugStringW(pwszClass);
OutputDebugString(TEXT(" - "));
OutputDebugStringW(pwszName);
OutputDebugString(TEXT("\n"));
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
}
*puFlags = DSA_NOTIFY_FLAG_ADDITIONAL_DATA |
DSA_NOTIFY_FLAG_FORCE_ADDITIONAL_DATA;
WCHAR wszTitle[MAX_PATH];
LocalToWideChar(wszTitle, ARRAYSIZE(wszTitle), g_szMainTitle, MAX_PATH);
*pBstr = SysAllocString(wszTitle);
return *pBstr ? S_OK : E_OUTOFMEMORY;
}
/**************************************************************************
CAdminNotifyHandler::Notify()
**************************************************************************/
STDMETHODIMP CAdminNotifyHandler::Notify(ULONG nItem, ULONG uFlags)
{
OutputDebugString(TEXT("CAdminNotifyHandler::Notify\n"));
return S_OK;
}
/**************************************************************************
CAdminNotifyHandler::End()
**************************************************************************/
STDMETHODIMP CAdminNotifyHandler::End(void)
{
OutputDebugString(TEXT("CAdminNotifyHandler::End\n"));
if(m_pdoFrom)
{
m_pdoFrom->Release();
m_pdoFrom = NULL;
}
if(m_pdoTo)
{
m_pdoTo->Release();
m_pdoTo = NULL;
}
return S_OK;
}
/**************************************************************************
WideCharToLocal()
**************************************************************************/
int WideCharToLocal(LPTSTR pLocal, size_t buffSize, LPWSTR pWide, DWORD dwChars)
{
*pLocal = 0;
#ifdef UNICODE
wcsncpy_s(pLocal, buffSize, pWide, dwChars);
#else
WideCharToMultiByte( CP_ACP,
0,
pWide,
-1,
pLocal,
dwChars,
NULL,
NULL);
#endif
return lstrlen(pLocal);
}
/**************************************************************************
LocalToWideChar()
**************************************************************************/
int LocalToWideChar(LPWSTR pWide, size_t buffSize, LPTSTR pLocal, DWORD dwChars)
{
*pWide = 0;
#ifdef UNICODE
wcsncpy_s(pWide, buffSize, pLocal, dwChars);
#else
MultiByteToWideChar( CP_ACP,
0,
pLocal,
-1,
pWide,
dwChars);
#endif
return lstrlenW(pWide);
}
/**************************************************************************
DeleteEntireKey()
**************************************************************************/
BOOL DeleteEntireKey(HKEY hKey, LPTSTR pszSubKey)
{
LRESULT lResult;
HKEY hEnumKey;
lResult = RegOpenKeyEx( hKey,
pszSubKey,
0,
KEY_ENUMERATE_SUB_KEYS,
&hEnumKey);
if(NOERROR == lResult)
{
TCHAR szKey[MAX_PATH];
DWORD dwSize = MAX_PATH;
while(ERROR_SUCCESS == RegEnumKeyEx(hEnumKey, 0, szKey, &dwSize, NULL, NULL, NULL, NULL))
{
DeleteEntireKey(hEnumKey, szKey);
dwSize = MAX_PATH;
}
RegCloseKey(hEnumKey);
}
else
{
return FALSE;
}
RegDeleteKey(hKey, pszSubKey);
return TRUE;
}