Icopyhook is a COM interface for creating a copy hook handler that determines whether a folder or printer object can be moved, copied, renamed, or deleted. The shell will invoke the Copycallback method of the Icopyhook interface to validate them before performing these operations. Copycallback returns an int value indicating whether the shell should continue to perform this operation. The return value Idyes indicates continuation, while the return value Idno and idcancel indicate termination.
A Folder object can install multiple copy hook handlers. If this happens, the shell calls each handler in turn. Only when each handler returns Idyes does the shell actually perform the action requested by the user.
The role of the copy hook handler is to validate the four operations before they are executed, but the shell does not notify the copy hook handler of the results of the operation. However, the API functions provided by Windows FindFirstChangeNotification and findnextchangenotification can implement this function. Therefore, only by combining the two methods can the state of a folder be fully monitored.
The Copy hook handler implementation is not difficult, first creating a COM object as an in-process component, and it only needs to expose a Icopyhook interface (and, of course, IUnknown). Then register this COM component with Regsrv32.exe. The final step is to register your copy hook handler with the shell by creating a sub key with any name under the registry hkey_classes_root\directory\shellex\copyhookhandlers, in this sub Key to create an item of type REG_SZ and use the CLSID of your COM object as its default value.
Here is a copy of the hook Implementation Program (note: The following code through the old demon changes and added a detailed operation process, in the BCB6 successfully compiled and passed the test)
1. Create Tcopyhook from the Icopyhook interface and create Tclassfactory from the IClassFactory interface:
TCopyHook.h
The Tcopyhook class implements the Icopyhook interface, Tclassfactory implements the IClassFactory interface
//---------------------------------------------------------------------------
#define No_win32_lean_and_mean
#include <shlobj.h>
//---------------------------------------------------------------------------
Class Tcopyhook:public Icopyhook
{
Public
Tcopyhook (): m_refcnt (0) {}
STDMETHODIMP QueryInterface (Refiid iid,void **ppvobject);
Stdmethodimp_ (ULONG) AddRef ();
Stdmethodimp_ (ULONG) release ();
Stdmethodimp_ (UINT) Copycallback (HWND hwnd, UINT Wfunc, UINT wflags,
LPCTSTR Pszsrcfile, DWORD dwsrcattribs,
LPCTSTR Pszdestfile, DWORD dwdestattribs);
Private
int m_refcnt;
};
//---------------------------------------------------------------------------
Class Tclassfactory:public IClassFactory
{
Public
Tclassfactory (): m_refcnt (0) {}
STDMETHODIMP QueryInterface (Refiid iid, void **ppvobject);
Stdmethodimp_ (ULONG) AddRef ();
Stdmethodimp_ (ULONG) release ();
Stdmethodimp CreateInstance (IUnknown *punkouter, refiid riid, void **ppvobject);
STDMETHODIMP Lockserver (BOOL fLock);
Private
int m_refcnt;
};
TCopyHook.cpp
Implementation files for Tcopyhook objects and Tclassfactory objects
#include <stdio.h>
#include "TCopyHook.h"
//---------------------------------------------------------------------------
extern LONG Nlocks; Object count, for DllCanUnloadNow
ULONG __stdcall Tcopyhook::addref ()
{
if (m_refcnt = 0)
nlocks++;
m_refcnt++;
return m_refcnt;
}
//---------------------------------------------------------------------------
ULONG __stdcall Tcopyhook::release ()
{
int nnewcnt =--m_refcnt;
if (nnewcnt <= 0)
{
nlocks--;
Delete this;
}
return nnewcnt;
}
//---------------------------------------------------------------------------
HRESULT __stdcall Tcopyhook::queryinterface (refiid dwiid, void **ppvobject)
{
if (dwiid = = IID_IUnknown)
*ppvobject = static_cast<iunknown*> (this);
Else
if (dwiid = = Iid_ishellcopyhook)
*ppvobject = static_cast<icopyhook*> (this);
Else
return e_nointerface;
Reinterpret_cast<iunknown*> (*ppvobject)->addref ();
return S_OK;
}
//---------------------------------------------------------------------------
This is the Copycallback method, and all the features of the copy hook are implemented by it. The specific value of the parameter see MSDN
UINT __stdcall Tcopyhook::copycallback (HWND hwnd, UINT Wfunc, UINT wflags,
LPCTSTR Pszsrcfile, DWORD dwsrcattribs,
LPCTSTR Pszdestfile, DWORD dwdestattribs)
{
Char szmessage[max_path+14];
sprintf (Szmessage, "Do you want to continue the operation on%s?) ", Pszsrcfile);
Return MessageBox (NULL, Szmessage, "confirm", Mb_yesno | Mb_iconexclamation);
}
//---------------------------------------------------------------------------
ULONG __stdcall Tclassfactory::addref ()
{
if (m_refcnt==0)
nlocks++;
m_refcnt++;
return m_refcnt;
}
//---------------------------------------------------------------------------
ULONG __stdcall Tclassfactory::release ()
{
int nnewcnt =--m_refcnt;
if (nnewcnt <= 0)
{
nlocks--;
Delete this;
}
return nnewcnt;
}
//---------------------------------------------------------------------------
HRESULT __stdcall Tclassfactory::queryinterface (refiid dwiid, void **ppvobject)
{
if (dwiid = = IID_IUnknown)
*ppvobject = static_cast<iunknown*> (this);
Else
if (dwiid = = iid_iclassfactory)
*ppvobject = static_cast<iclassfactory*> (this);
Else
return e_nointerface;
Reinterpret_cast<iunknown*> (*ppvobject)->addref ();
return S_OK;
}
//---------------------------------------------------------------------------
HRESULT __stdcall tclassfactory::createinstance (iunknown* punkownouter,
REFIID riid, void** ppvobj)
{
if (Punkownouter!= NULL)
return class_e_noaggregation;
Tcopyhook *pobj = new Tcopyhook;
Pobj->addref ();
HRESULT hr = Pobj->queryinterface (riid, ppvobj);
Pobj->release ();
return HR;
}
//---------------------------------------------------------------------------
HRESULT __stdcall Tclassfactory::lockserver (BOOL fLock)
{
if (FLock)
nlocks++;
Else
nlocks--;
return S_OK;
}