procedure FillProcessTree(ATreeView: TTreeView);
var
  hProcessSnapshot, hModuleSnapshot: Cardinal;
  pe: TProcessEntry32;
  me: TModuleEntry32;
  ProcessNode: TTreeNode;
  procedure AdjustPrivileges;
  var
    hToken: Cardinal;
    tp: TTokenPrivileges;
    nSize: Cardinal;
  begin
    if not OpenProcessToken(GetCurrentProcess, TOKEN_ALL_ACCESS, hToken) then Exit;
    tp.PrivilegeCount := 1;
    LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid);
    tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken, False, tp, SizeOf(tp), tp, nSize);
    CloseHandle(hToken);
  end;
begin
  AdjustPrivileges;
  ATreeView.Items.BeginUpdate;
  try
    hProcessSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    pe.dwSize := SizeOf(pe);
    me.dwSize := SizeOf(me);
    Process32First(hProcessSnapshot, pe);
    repeat
      ProcessNode := ATreeView.Items.AddChild(nil, pe.szExeFile);
      hModuleSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPALL, pe.th32ProcessID);
      Module32First(hModuleSnapshot, me);
      repeat
        ATreeView.Items.AddChild(ProcessNode, me.szExePath).Data := Pointer(pe.th32ProcessID);
      until not Module32Next(hModuleSnapshot, me);
      CloseHandle(hModuleSnapshot);
    until not Process32Next(hProcessSnapshot, pe);
    CloseHandle(hProcessSnapshot);
  finally
    ATreeView.Items.EndUpdate;
  end;
end;procedure UnloadDll(ProcessId: Cardinal; DllName: string);
const
  MAX_TRY = 10;
var
  hProcess: Cardinal;
  pBuf, pFreeLibrary, pGetModuleHandle: Pointer;
  hThread, ThreadId, hDll, FreeCount: Cardinal;
  DllPath: array[0..MAX_PATH] of Char;
begin
  pBuf := nil;
  FreeCount := 0;
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessId);
  if hProcess = 0 then Exit;
  try
    FillChar(DllPath, SizeOf(DllPath), 0);
    StrCopy(DllPath, PChar(DllName));
    pBuf := VirtualAllocEx(hProcess, nil, SizeOf(DllPath), MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(hProcess, pBuf, @DllPath, SizeOf(DllPath), hDll);
    pFreeLibrary := GetProcAddress(GetModuleHandle('kernel32.dll'), 'FreeLibrary');
    pGetModuleHandle := GetProcAddress(GetModuleHandle('kernel32.dll'), 'GetModuleHandleA');
    while FreeCount < MAX_TRY do
    begin
      hThread := CreateRemoteThread(hProcess, nil, 0, pGetModuleHandle, pBuf, 0, ThreadId);
      GetExitCodeThread(hThread, hDll);
      CloseHandle(hThread);
      if hDll = 0 then Break;
      hThread := CreateRemoteThread(hProcess, nil, 0, pFreeLibrary, Pointer(hDll), 0, ThreadId);
      CloseHandle(hThread);
      Inc(FreeCount);
    end;
  finally
    if pBuf <> nil then VirtualFree(pBuf, Length(DllName) + 1, MEM_FREE);
    if hProcess <> 0 then CloseHandle(hProcess);
  end;
end;procedure TForm1.TreeView1DblClick(Sender: TObject);
begin
  if (TreeView1.Selected = nil) or (TreeView1.Selected.Data = nil) then Exit;
  UnloadDll(Cardinal(TreeView1.Selected.Data), TreeView1.Selected.Text);
end;procedure TForm1.Button1Click(Sender: TObject);
begin
  TreeView1.Items.Clear;
  FillProcessTree(TreeView1);
end;
我测试过了,不管双击treeview1是的哪个dll都无法卸载 
?请问一下,是哪里的错?

解决方案 »

  1.   

    显示部分没有问题,就是结束的代码上面有问题
    procedure UnloadDll(ProcessId: Cardinal; DllName: string); 
    const 
      MAX_TRY = 10; 
    var 
      hProcess: Cardinal; 
      pBuf, pFreeLibrary, pGetModuleHandle: Pointer; 
      hThread, ThreadId, hDll, FreeCount: Cardinal; 
      DllPath: array[0..MAX_PATH] of Char; 
    begin 
      pBuf := nil; 
      FreeCount := 0; 
      hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, ProcessId); 
      if hProcess = 0 then Exit; 
      try 
        FillChar(DllPath, SizeOf(DllPath), 0); 
        StrCopy(DllPath, PChar(DllName)); 
        pBuf := VirtualAllocEx(hProcess, nil, SizeOf(DllPath), MEM_COMMIT, PAGE_READWRITE); 
        WriteProcessMemory(hProcess, pBuf, @DllPath, SizeOf(DllPath), hDll); 
        pFreeLibrary := GetProcAddress(GetModuleHandle('kernel32.dll'), 'FreeLibrary'); 
        pGetModuleHandle := GetProcAddress(GetModuleHandle('kernel32.dll'), 'GetModuleHandleA'); 
        while FreeCount < MAX_TRY do 
        begin 
          hThread := CreateRemoteThread(hProcess, nil, 0, pGetModuleHandle, pBuf, 0, ThreadId); 
          GetExitCodeThread(hThread, hDll); 
          CloseHandle(hThread); 
          if hDll = 0 then Break; 
          hThread := CreateRemoteThread(hProcess, nil, 0, pFreeLibrary, Pointer(hDll), 0, ThreadId); 
          CloseHandle(hThread); 
          Inc(FreeCount); 
        end; 
      finally 
        if pBuf <> nil then VirtualFree(pBuf, Length(DllName) + 1, MEM_FREE); 
        if hProcess <> 0 then CloseHandle(hProcess); 
      end; 
    end; procedure TForm1.TreeView1DblClick(Sender: TObject); 
    begin 
      if (TreeView1.Selected = nil) or (TreeView1.Selected.Data = nil) then Exit; 
      UnloadDll(Cardinal(TreeView1.Selected.Data), TreeView1.Selected.Text); 
    end; procedure TForm1.Button1Click(Sender: TObject); 
    begin 
      TreeView1.Items.Clear; 
      FillProcessTree(TreeView1); 
    end;