cbSize: DWORD;
fMask: ULONG;
Wnd: HWND;
lpVerb: PAnsiChar;
lpFile: PAnsiChar;
lpParameters: PAnsiChar;
lpDirectory: PAnsiChar;
nShow: Integer;
hInstApp: HINST;
{ Optional fields }
lpIDList: Pointer;
lpClass: PAnsiChar;
hkeyClass: HKEY;
dwHotKey: DWORD;
hIcon: THandle;
hProcess: THandle;
end;
TShellExecuteInfo结构中还记录了要运行程序的很多信息,然而这里我们只能在Execute方法中修改nCmdShow参数,nCmdShow参数定义了窗口在运行后的显示状态,包括最大化、最小化、正常等选项,对于其他参数的修改都会被外壳忽略。除此之外,在Execute方法中可以根据情况允许外壳继续缺省的任务或通知外壳取消执行,这可以通过Execute函数的返回值来实现。
如果Execute的返回值为S_FALSE,外壳就继续缺省的任务,如果返回S_OK,则外壳认为扩展已经成功,就不再继续执行了。另外如果返回一个错误代码或系统无法识别的值,则外壳会弹出错误信息。这给了我们一个控制程序运行的机会,比如可以限制任何对记事本的调用,代码如下:
function TTShellExecuteHook.Execute(
var ShellExecuteInfo: TShellExecuteInfo): HResult;
var
FileName: String;
begin
Result := S_FALSE;
with ShellExecuteInfo do
begin
FileName := UpperCase(ExtractFileName(lpFile));
if Pos('NOTEPAD', FileName) = 1 then
begin
Result := S_OK;
hInstApp := 32;
MessageBox(Wnd, '不允许记事本运行!', '错误', MB_OK or MB_ICONERROR);
end;
end;
end;
进一步,我们甚至可以利用这点实现一个自定义的安全认证机制,根据用户要求限制运行的程序。有兴趣的朋友可以试验一下,一定很有意思。
有一点要注意的是,在Execute方法下不能调用ShellExecute和ShellExecuteEx函数外部程序,如果是这样的话,我们的Execute方法又会被新的ShellExecute调用,这样系统就会进入死循环。如果我们确实想在Execute方法中调用外部程序的话,可以使用CreateProcess或WinExec函数来替代。这两个函数不会被ShellExecuteHook截获。
对于外壳动作记录器来说,只要在Execute方法中记录程序信息到日志文件中就可以了,代码非常简单,因为所有需要的信息都在TShellExecuteInfo记录中包含了,这里只记录运行的动作、文件名和时间,需要记录其他信息的话,大家可自行修改,代码示意如下:
function TTShellExecuteHook.Execute(
var ShellExecuteInfo: TShellExecuteInfo): HResult;
var
FileStream: TFileStream;
a:TStringList;
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-30580-2.html
crystal