Перехватываю API функции копирования/перемещения использую Detours. При тестах на своем приложении хуки срабатывают. А при инжекте DLL (DLL успешно подгружается и выгружается) в эксплорер, систем, или вообще во все процессы, не срабатывает. Видимо эксплорер использует какие-то другие функции. Подскажите куда копать.
Единственное, удалось перехватить копирование, поставив хуки на методы интерфейса IFileOperation, но он срабатывает до диалога замены файла (где написано файл существует. заменить?), а мне нужно чтобы срабатывало после него.
Код Dll:
library thread_splice_lib;
uses
Windows,
System.SysUtils,
ActiveX,
ShlObj,
ShellApi,
CPUID in '..\..\..\delphi-detours-library-master\Source\CPUID.pas',
DDetours in '..\..\..\delphi-detours-library-master\Source\DDetours.pas',
InstDecode in '..\..\..\delphi-detours-library-master\Source\InstDecode.pas';
{$R *.res}
type
_tagpropertykey = packed record
fmtid: TGUID;
pid: DWORD;
end;
PROPERTYKEY = _tagpropertykey;
//----------------------------------------------
// IShellItem interface declaration
//----------------------------------------------
IShellItem = interface(IUnknown)
['{43826d1e-e718-42ee-bc55-a1e261c37bfe}']
function BindToHandler(const pbc: IBindCtx; const bhid: TGUID;
const riid: TIID; out ppv): HResult; stdcall;
function GetParent(var ppsi: IShellItem): HResult; stdcall;
function GetDisplayName(sigdnName: DWORD; var ppszName: LPWSTR): HResult; stdcall;
function GetAttributes(sfgaoMask: DWORD; var psfgaoAttribs: DWORD): HResult; stdcall;
function Compare(const psi: IShellItem; hint: DWORD;
var piOrder: Integer): HResult; stdcall;
end;
//----------------------------------------------
// ISHellEnumItems interface declaration
//----------------------------------------------
IEnumShellItems = interface(IUnknown)
['{70629033-e363-4a28-a567-0db78006e6d7}']
function Next(celt: ULONG; out rgelt; pceltFetched: PLongint): HResult; stdcall;
function Skip(celt: ULONG): HResult; stdcall;
function Reset: HResult; stdcall;
function Clone(out ppenum: IEnumShellItems): HResult; stdcall;
end;
//----------------------------------------------
// IShellItemArray interface declaration
//----------------------------------------------
IShellItemArray = interface(IUnknown)
['{b63ea76d-1f85-456f-a19c-48159efa858b}']
function BindToHandler(const pbc: IBindCtx; const rbhid: TGUID;
const riid: TIID; out ppvOut): HResult; stdcall;
function GetPropertyStore(flags: DWORD; const riid: TIID; out ppv): HResult; stdcall;
function GetPropertyDescriptionList(const keyType: PropertyKey;
const riid: TIID; out ppv): HResult; stdcall;
function GetAttributes(dwAttribFlags: DWORD; sfgaoMask: DWORD;
var psfgaoAttribs: DWORD): HResult; stdcall;
function GetCount(var pdwNumItems: DWORD): HResult; stdcall;
function GetItemAt(dwIndex: DWORD; var ppsi: IShellItem): HResult; stdcall;
function EnumItems(var ppenumShellItems: IEnumShellItems): HResult; stdcall;
end;
//----------------------------------------------
// SHCreateShellItemArrayFromDataObject declaration
//----------------------------------------------
TSHCreateShellItemArrayFromDataObject = function(pdo: IDataObject;
const riid: TGUID; ppv: Pointer): HRESULT; StdCall;
//----------------------------------------------
// Operations done by IFileOperation
//----------------------------------------------
TFileOperation = (opCopy, opMove, opDelete, opRename);
var
//---------------------------------------------------------------------------
// Hook's nextProcs
//---------------------------------------------------------------------------
CoCreateInstance_np: function(const clsid: TCLSID; unkOuter: Pointer;
dwClsContext: Longint; const iid: TIID; pv: Pointer): HResult; stdcall;
CopyItems_np: function( p: POinter; punkItems: IUnknown;
psiDestinationFolder: IShellItem ): HRESULT; stdcall;
CopyItem_np: function( p: POinter; psiitem: IShellItem;
psiDestinationFolder: IShellItem; pszCopyName: LPCWSTR;
pfopsItem: Pointer ): HRESULT; stdcall;
DeleteItem_np: function( p: POinter; psiItem: IShellItem; pfopsItem:
Pointer ): HRESULT; stdcall;
DeleteItems_np: function( p: POinter; punkItems: IUnknown ): HRESULT; stdcall;
MoveItems_np: function( p: POinter; punkItems: IUnknown;
psiDestinationFolder: IShellItem ): HRESULT; stdcall;
MoveItem_np: function( p: POinter; psiitem: IShellItem;
psiDestinationFolder: IShellItem; pszCopyName: LPCWSTR;
pfopsItem: Pointer ): HRESULT; stdcall;
RenameItem_np: function( p: Pointer; psiItem: IShellItem; pszNewName:
LPCWSTR; pfopsItem: Pointer ): HRESULT; stdcall;
RenameItems_np: function( p: Pointer; punkItems: IUnknown; pszNewName:
LPCWSTR ): HRESULT; stdcall;
const
IID_ShellItemArray : TGUID = '{b63ea76d-1f85-456f-a19c-48159efa858b}';
IID_DataObject: TGUID = '{0000010E-0000-0000-C000-000000000046}';
SIGDN_FILESYSPATH = $80058000;
SIGDN_NORMALDISPLAY = $00000000;
//----------------------------------------------
// Little function for string to PWideChar convertion
//----------------------------------------------
function PWideToString( wide: PWideChar ): string;
var
pAtual: Pointer;
begin
pAtual := wide;
Result := '';
// A PWideChar ends when a #0#0 is found. 2 bytes, then we can
// typecast for a Word comparasion
while PWord( pAtual )^ <> 0 do
begin
// We use only the first byte. Jump 2.
Result := Result + Chr( PByte( pAtual )^ );
pAtual := Pointer( Integer( pAtual ) + 2 );
end;
end;
//----------------------------------------------
// Convert and returns as true, to be used on one line IF
//----------------------------------------------
function ConvertWtoS( wide: PWideChar; var output: string ): Boolean;
begin
Result := True;
output := PWideToString( wide );
end;
//----------------------------------------------
// All one item operation will step here.
//----------------------------------------------
function canPerform_ShellItem( item, dest: IShellItem; secParam: LPCWSTR;
op: TFileOperation ): Boolean;
var
itemPath, destPath: PWideChar;
sItemPath, sDestPath: string;
begin
Result := True;
if Item.GetDisplayName( SIGDN_FILESYSPATH, itemPath ) = S_OK then
begin
// Extract the origin file path
sItemPath := PWideToString( itemPath );
// For deletion, there's no need for destiny
if op <> opDelete then
begin
// There's destiny
if ( dest <> nil ) and (dest.GetDisplayName(
SIGDN_FILESYSPATH, destPath ) = S_OK) then
// Transforms the string including a path delimiter
sDestPath := IncludeTrailingPathDelimiter( PWideToString( destPath ) )
else sDestPath := IncludeTrailingPathDelimiter( ExtractFilePath( sItemPath ) );
// If there's no destiny, we'll use the origin
if secParam = nil then
sDestPath := sDestPath + ExtractFileName( sItemPath )
else sDestPath := sDestPath + PWideToString( secParam );
end;
case op of
opCopy:
// Shows a messageBox
Result := MessageBoxA( 0, PAnsiChar( 'Copying from: ' + sItemPath + #13#10 + 'to: ' + sDestPath ),'Allow?', MB_YESNO ) = ID_YES;
opMove :
// Shows a messageBox
Result := MessageBoxA( 0, PAnsiChar( 'Moving from: ' + sItemPath + #13#10 + 'to: ' + sDestPath ),'Allow?', MB_YESNO ) = ID_YES;
opDelete:
// Shows a messageBox
Result := MessageBoxA( 0, PAnsiChar( 'Deleteing file: ' + sItemPath ),'Allow?', MB_YESNO ) = ID_YES;
opRename:
// Shows a messageBox
Result := MessageBoxA( 0, PAnsiChar( 'Renaming from: ' + sItemPath + #13#10 + 'to: ' + sDestPath ),'Allow?', MB_YESNO ) = ID_YES;
end;
end;
end;
//-------------------------------------
// Many items performing method
//-------------------------------------
function canPerform_ShellItemArray( itemArr: IShellItemArray; dest: IShellItem;
op: TFileOperation ): Boolean;
var
nTotal: Cardinal;
nAux: Integer;
shellItem: IShellItem;
begin
Result := True;
// Is a valid array?
if itemArr.GetCount( nTotal ) = S_OK then
begin
for nAux := 0 to nTotal -1 do
begin
// Extract the current item
if itemArr.GetItemAt( nAux, shellItem ) = S_OK then
begin
// check if the operation can be performed
Result := Result and canPerform_ShellItem( shellItem, dest, nil, op );
// In abortion case, break
if not Result then
Break;
end;
end;
end;
end;
//-------------------------------------
// Many items performing method, trough IDataObject
//-------------------------------------
function canPerform_DataObject( dataObject: IDataObject; dest: IShellItem;
op: TFileOperation ): Boolean;
var
SHConverteFromData: TSHCreateShellItemArrayFromDataObject;
shellItemArr: IShellItemArray;
begin
Result := True;
// Windows Vista has implemented a function to convert an
// IDataObject to ISHellItemArray. We'll use it.
@SHConverteFromData := GetProcAddress( GetModuleHandle('shell32.dll'),
'SHCreateShellItemArrayFromDataObject' );
// Functoun found, use it.
if (@SHConverteFromData <> nil) and ( SHConverteFromData(
dataObject, IID_ShellItemArray, @shellItemArr ) = S_OK ) then
begin
// Perform the item now.
Result := canPerform_ShellItemArray( shellItemArr, dest, op );
end;
end;
//------------------------------------
// Many items performing method, trough punkData
//------------------------------------
function canPerform_PunkItem( punkItems: IUnknown; dest: IShellItem;
op: TFileOperation ): Boolean;
var
shellItemArr: IShellItemArray;
dataObject: IDataObject;
begin
Result := True;
if punkItems.QueryInterface( IID_ShellItemArray, shellItemArr ) = S_OK then
// If we have a ShellItemArr, check directly
result := canPerform_ShellItemArray( shellItemArr, dest, op )
// In case of IDataObject, convert to IShellItemArray
else if punkItems.QueryInterface( IID_DataObject, dataObject ) = S_OK then
result := canPerform_DataObject( dataObject, dest, op );
end;
function IsWindows64: Boolean;
type
TIsWow64Process = function(AHandle:THandle; var AIsWow64: BOOL): BOOL; stdcall;
var
vKernel32Handle: DWORD;
vIsWow64Process: TIsWow64Process;
vIsWow64 : BOOL;
begin
// 1) assume that we are not running under Windows 64 bit
Result := False;
// 2) Load kernel32.dll library
vKernel32Handle := LoadLibrary('kernel32.dll');
if (vKernel32Handle = 0) then Exit; // Loading kernel32.dll was failed, just return
try
// 3) Load windows api IsWow64Process
@vIsWow64Process := GetProcAddress(vKernel32Handle, 'IsWow64Process');
if not Assigned(vIsWow64Process) then Exit; // Loading IsWow64Process was failed, just return
// 4) Execute IsWow64Process against our own process
vIsWow64 := False;
if (vIsWow64Process(GetCurrentProcess, vIsWow64)) then
Result := vIsWow64; // use the returned value
finally
FreeLibrary(vKernel32Handle); // unload the library
end;
end;
//------------------------------------------
// Given an interface pointer, find out the position by it's index
//------------------------------------------
function GetInterfaceMethod(const intf; methodIndex: dword) : pointer;
begin
if IsWindows64 then
result := pointer(pointer(DWORD_PTR(pointer(intf)^) + methodIndex * {sizeOf(cardinal)} 8)^)
else
result := pointer(pointer(DWORD(pointer(intf)^) + methodIndex * {sizeOf(cardinal)} 4)^);
end;
//-----------------------------
// DeleteItems callBack
//-----------------------------
function DeleteItems_cb( p: POinter; punkItems: IUnknown ): HRESULT; stdcall;
begin
if canPerform_PunkItem( punkItems, nil, opDelete ) then
Result := deleteItems_np( p, punkItems )
else Result := E_ABORT;
end;
//-----------------------------
// DeleteItem callBack
//-----------------------------
function DeleteItem_cb( p: POinter; psiItem: IShellItem;
pfopsItem: Pointer ): HRESULT; stdcall;
begin
if canPerform_ShellItem( psiItem, nil, nil, opDelete ) then
Result := deleteItem_np( p, psiItem, pfopsItem )
else Result := E_ABORT;
end;
//-----------------------------
// CopyItem callBack
//-----------------------------
function CopyItem_cb( p: POinter; psiItem: IShellItem; psiDestinationFolder:
IShellItem; pszCopyName: LPCWSTR; pfopsItem: Pointer ): HRESULT; stdcall;
begin
if canPerform_ShellItem( psiItem, psiDestinationFolder, pszCopyName, opCopy ) then
Result := CopyItem_np( p, psiItem, psiDestinationFolder, pszCopyName,
pfopsItem )
else Result := E_ABORT;
end;
//-----------------------------
// CopyItems callBack
//-----------------------------
function CopyItems_cb( p: POinter; punkItems: IUnknown; psiDestinationFolder:
IShellItem ): HRESULT; stdcall;
begin
if canPerform_PunkItem( punkItems, psiDestinationFolder, opCopy ) then
Result := CopyItems_np( p, punkItems, psiDestinationFolder )
else Result := E_ABORT;
end;
//-----------------------------
// MoveItem callBack
//-----------------------------
function MoveItem_cb( p: POinter; psiItem: IShellItem; psiDestinationFolder:
IShellItem; pszCopyName: LPCWSTR; pfopsItem: Pointer ): HRESULT; stdcall;
begin
if canPerform_ShellItem( psiItem, psiDestinationFolder, pszCopyName, opMove ) then
Result := MoveItem_np( p, psiItem, psiDestinationFolder, pszCopyName,
pfopsItem )
else Result := E_ABORT;
end;
//-----------------------------
// MoveItems callBack
//-----------------------------
function MoveItems_cb( p: POinter; punkItems: IUnknown; psiDestinationFolder:
IShellItem ): HRESULT; stdcall;
begin
if canPerform_PunkItem( punkItems, psiDestinationFolder, opMove ) then
Result := MoveItems_np( p, punkItems, psiDestinationFolder )
else Result := E_ABORT;
end;
//-----------------------------
// RenameItem callBack
//-----------------------------
function RenameItem_cb( p: Pointer; psiItem: IShellItem; pszNewName:
LPCWSTR; pfopsItem: Pointer ): HRESULT; stdcall;
begin
if canPerform_ShellItem( psiItem, nil, pszNewName, opRename ) then
Result := RenameItem_np( p, psiItem, pszNewName, pfopsItem )
else Result := E_ABORT;
end;
//-----------------------------
// RenameItems callBack
//-----------------------------
function RenameItems_cb( p: Pointer; punkItems: IUnknown; pszNewName:
LPCWSTR ): HRESULT; stdcall;
begin
if canPerform_PunkItem( punkItems, nil, opRename ) then
Result := RenameItems_np( p, punkItems, pszNewName )
else Result := E_ABORT;
end;
//-----------------------------
// coCreateInstance callBack
//-----------------------------
function CoCreateInstance_cb(const clsid: TCLSID; unkOuter: Pointer;
dwClsContext: Longint; const iid: TIID; pv: Pointer): HResult; stdcall;
const
IFileOperation_GUID = '3AD05575-8857-4850-9277-11B85BDB8E09';
procedure HookFunctionIndex( index: Integer; CallBack: Pointer; var NextProc: Pointer );
begin
// Hook if it is not yet hooked
if NextProc = nil then
//HookCode( GetInterfaceMethod( pv^, index ), CallBack, NextProc );
NextProc := InterceptCreate(GetInterfaceMethod( pv^, index ), CallBack);
end;
begin
// Call the original API to get it's instance pointer
Result := CoCreateInstance_np( clsid, unkOuter, dwClsContext, iid, pv );
// Check IFileOperation GUID
if pos( IFIleOperation_GUID, GUIDToString(clsid) ) <> 0 then
begin
//------------------------------------
// Hook each function of our interface
//------------------------------------
HookFunctionIndex( 12, @RenameItem_Cb , @RenameItem_np );
HookFunctionIndex( 13, @RenameItems_Cb, @RenameItems_np );
HookFunctionIndex( 14, @MoveItem_Cb , @MoveItem_np );
HookFunctionIndex( 15, @MoveItems_cb , @MoveItems_np );
HookFunctionIndex( 16, @CopyItem_cb , @CopyItem_np );
HookFunctionIndex( 17, @CopyItems_cb , @CopyItems_np );
HookFunctionIndex( 18, @DeleteItem_cb , @DeleteItem_np );
HookFunctionIndex( 19, @DeleteItems_cb, @DeleteItems_np );
end;
end;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var
CopyFileA_np: function(lpExistingFileName, lpNewFileName: LPCSTR; bFailIfExists: BOOL): BOOL; stdcall;
CopyFileW_np: function(lpExistingFileName, lpNewFileName: LPCWSTR; bFailIfExists: BOOL): BOOL; stdcall;
CopyFileExA_np: function(lpExistingFileName, lpNewFileName: LPWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD): BOOL; stdcall;
CopyFileExW_np: function(lpExistingFileName, lpNewFileName: LPCWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD): BOOL; stdcall;
ReplaceFileA_np: function(lpReplacedFileName, lpReplacementFileName, lpBackupFileName: LPCSTR; dwReplaceFlags: DWORD; lpExclude, lpReserved: Pointer): BOOL; stdcall;
ReplaceFileW_np: function(lpReplacedFileName, lpReplacementFileName, lpBackupFileName: LPCWSTR; dwReplaceFlags: DWORD; lpExclude, lpReserved: Pointer): BOOL; stdcall;
CopyFileTransactedA_np: function(lpExistingFileName, lpNewFileName: LPSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD; hTransaction: THandle): BOOL; stdcall;
CopyFileTransactedW_np: function(lpExistingFileName, lpNewFileName: LPWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD; hTransaction: THandle): BOOL; stdcall;
MoveFileA_np: function(lpExistingFileName, lpNewFileName: LPCSTR): BOOL; stdcall;
MoveFileW_np: function(lpExistingFileName, lpNewFileName: LPCWSTR): BOOL; stdcall;
MoveFileExA_np: function(lpExistingFileName, lpNewFileName: LPCSTR; dwFlags: DWORD): BOOL; stdcall;
MoveFileExW_np: function(lpExistingFileName, lpNewFileName: LPCWSTR; dwFlags: DWORD): BOOL; stdcall;
MoveFileWithProgressA_np: function (lpExistingFileName, lpNewFileName: LPCSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; dwFlags: DWORD): BOOL; stdcall;
MoveFileWithProgressW_np: function (lpExistingFileName, lpNewFileName: LPCWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; dwFlags: DWORD): BOOL; stdcall;
SHFileOperationA_np: function(const lpFileOp: TSHFileOpStructA): Integer; stdcall;
SHFileOperationW_np: function(const lpFileOp: TSHFileOpStructW): Integer; stdcall;
function SHFileOperationA_cb(const lpFileOp: TSHFileOpStructA): Integer; stdcall;
begin
if MessageBoxA(0, PAnsiChar('SHFileOperationA'), 'Allow?', MB_YESNO) = ID_YES then
Result := SHFileOperationA_np(lpFileOp);
end;
function SHFileOperationW_cb(const lpFileOp: TSHFileOpStructW): Integer; stdcall;
begin
if MessageBoxA(0, PAnsiChar('SHFileOperationW'), 'Allow?', MB_YESNO) = ID_YES then
Result := SHFileOperationW_np(lpFileOp);
end;
function MoveFileWithProgressA_cb(lpExistingFileName, lpNewFileName: LPCSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; dwFlags: DWORD): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('MoveFileWithProgressA from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := MoveFileWithProgressA_np(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags);
end;
function MoveFileWithProgressW_cb(lpExistingFileName, lpNewFileName: LPCWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; dwFlags: DWORD): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('MoveFileWithProgressW from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := MoveFileWithProgressW_np(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags);
end;
function CopyFileA_cb(lpExistingFileName, lpNewFileName: LPCSTR; bFailIfExists: BOOL): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('CopyFileA from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := CopyFileA_np(lpExistingFileName, lpNewFileName, bFailIfExists);
end;
function CopyFileW_cb(lpExistingFileName, lpNewFileName: LPCWSTR; bFailIfExists: BOOL): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('CopyFileW from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := CopyFileW_np(lpExistingFileName, lpNewFileName, bFailIfExists);
end;
function CopyFileExA_cb(lpExistingFileName, lpNewFileName: LPWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('CopyFileExA from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := CopyFileExA_np(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags);
end;
function CopyFileExW_cb(lpExistingFileName, lpNewFileName: LPCWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('CopyFileExW from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := CopyFileExA_np(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags);
end;
function ReplaceFileA_cb(lpReplacedFileName, lpReplacementFileName, lpBackupFileName: LPCSTR; dwReplaceFlags: DWORD; lpExclude, lpReserved: Pointer): BOOL; stdcall;
begin
Result := MessageBoxA(0, PAnsiChar('ReplaceFileA from: ' + lpReplacedFileName + #13#10 + 'to: ' + lpReplacementFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := ReplaceFileA_np(lpReplacedFileName, lpReplacementFileName, lpBackupFileName, dwReplaceFlags, lpExclude, lpReserved);
end;
function ReplaceFileW_cb(lpReplacedFileName, lpReplacementFileName, lpBackupFileName: LPCWSTR; dwReplaceFlags: DWORD; lpExclude, lpReserved: Pointer): BOOL; stdcall;
begin
Result := MessageBoxA(0, PAnsiChar('ReplaceFileW from: ' + lpReplacedFileName + #13#10 + 'to: ' + lpReplacementFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := ReplaceFileW_np(lpReplacedFileName, lpReplacementFileName, lpBackupFileName, dwReplaceFlags, lpExclude, lpReserved);
end;
function CopyFileTransactedA_cb(lpExistingFileName, lpNewFileName: LPSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD; hTransaction: THandle): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('CopyFileTransactedA from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := CopyFileTransactedA_np(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags, hTransaction);
end;
function CopyFileTransactedW_cb(lpExistingFileName, lpNewFileName: LPCWSTR; lpProgressRoutine: TFNProgressRoutine; lpData: Pointer; pbCancel: PBool; dwCopyFlags: DWORD; hTransaction: THandle): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('CopyFileTransactedW from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := CopyFileTransactedW_np(lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, pbCancel, dwCopyFlags, hTransaction);
end;
function MoveFileA_cb(lpExistingFileName, lpNewFileName: LPCSTR): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('MoveFileA from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := MoveFileA_np(lpExistingFileName, lpNewFileName);
end;
function MoveFileW_cb(lpExistingFileName, lpNewFileName: LPCWSTR): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('MoveFileW from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := MoveFileW_np(lpExistingFileName, lpNewFileName);
end;
function MoveFileExA_cb(lpExistingFileName, lpNewFileName: LPCSTR; dwFlags: DWORD): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('MoveFileExA from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := MoveFileExA_np(lpExistingFileName, lpNewFileName, dwFlags);
end;
function MoveFileExW_cb(lpExistingFileName, lpNewFileName: LPCWSTR; dwFlags: DWORD): BOOL;
begin
Result := MessageBoxA(0, PAnsiChar('MoveFileExW from: ' + lpExistingFileName + #13#10 + 'to: ' + lpNewFileName ), 'Allow?', MB_YESNO) = ID_YES;
if Result then
Result := MoveFileExW_np(lpExistingFileName, lpNewFileName, dwFlags);
end;
procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
CoCreateInstance_np := InterceptCreate('ole32.dll', 'CoCreateInstance', @CoCreateInstance_cb);
CopyFileA_np := InterceptCreate('Kernel32.dll', 'CopyFileA', @CopyFileA_cb);
CopyFileW_np := InterceptCreate('Kernel32.dll', 'CopyFileW', @CopyFileW_cb);
CopyFileExA_np := InterceptCreate('Kernel32.dll', 'CopyFileExA', @CopyFileExA_cb);
CopyFileExW_np := InterceptCreate('Kernel32.dll', 'CopyFileExW', @CopyFileExW_cb);
ReplaceFileA_np := InterceptCreate('Kernel32.dll', 'ReplaceFileA', @ReplaceFileA_cb);
ReplaceFileW_np := InterceptCreate('Kernel32.dll', 'ReplaceFileW', @ReplaceFileW_cb);
CopyFileTransactedA_np := InterceptCreate('Kernel32.dll', 'CopyFileTransactedA', @CopyFileTransactedA_cb);
CopyFileTransactedW_np := InterceptCreate('Kernel32.dll', 'CopyFileTransactedW', @CopyFileTransactedW_cb);
MoveFileA_np := InterceptCreate('Kernel32.dll', 'MoveFileA', @MoveFileA_cb);
MoveFileW_np := InterceptCreate('Kernel32.dll', 'MoveFileW', @MoveFileW_cb);
MoveFileExA_np := InterceptCreate('Kernel32.dll', 'MoveFileExA', @MoveFileExA_cb);
MoveFileExW_np := InterceptCreate('Kernel32.dll', 'MoveFileExW', @MoveFileExW_cb);
MoveFileWithProgressA_np := InterceptCreate('Kernel32.dll', 'MoveFileWithProgressA', @MoveFileWithProgressA_cb);
MoveFileWithProgressW_np := InterceptCreate('Kernel32.dll', 'MoveFileWithProgressW', @MoveFileWithProgressW_cb);
SHFileOperationA_np := InterceptCreate('Shell32.dll', 'SHFileOperationA', @SHFileOperationA_cb);
SHFileOperationW_np := InterceptCreate('Shell32.dll', 'SHFileOperationW', @SHFileOperationW_cb);
end;
DLL_PROCESS_DETACH:
begin
InterceptRemove(@CoCreateInstance_np);
InterceptRemove(@CopyFileA_np);
InterceptRemove(@CopyFileW_np);
InterceptRemove(@CopyFileExA_np);
InterceptRemove(@CopyFileExW_np);
InterceptRemove(@ReplaceFileA_np);
InterceptRemove(@ReplaceFileW_np);
InterceptRemove(@CopyFileTransactedA_np);
InterceptRemove(@CopyFileTransactedW_np);
InterceptRemove(@MoveFileA_np);
InterceptRemove(@MoveFileW_np);
InterceptRemove(@MoveFileExA_np);
InterceptRemove(@MoveFileExW_np);
InterceptRemove(@MoveFileWithProgressA_np);
InterceptRemove(@MoveFileWithProgressW_np);
InterceptRemove(@SHFileOperationA_np);
InterceptRemove(@SHFileOperationW_np);
end;
end;
end;
begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.