首页
社区
课程
招聘
[求助]大家来帮我看一个线程,读内存错误
发表于: 2008-5-8 17:03 3794

[求助]大家来帮我看一个线程,读内存错误

2008-5-8 17:03
3794
线程单元:

unit ShellChangeNotifierThread;

interface
   
uses
  Windows, SysUtils, Classes, comctrls, CommCtrl, IniFiles;
   
type
    TMyShellChangeThread = class(TThread)
  private
    FMutex,
    FWaitHandle: Integer;
    FWatchSubTree: Boolean;
    FWaitChanged : Boolean;
    //FNotifyOptionFlags: DWORD;
  protected
    procedure Execute; override;
  public
    procedure GetDesktopIconPosition;
    constructor Create; virtual;
    destructor Destroy; override;
  end;

var
  CS : TRTLCriticalSection; // 临界区
const
  MyDesktop : Pchar ='Z:\桌面';
  StrVIPSet = 'Z:\VIPSet\VIPSet.ini';

{ 多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。
  为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。
  这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。 }
implementation
   
//uses Dialogs;

//------------------------------------------------------------------------------

function GetDesktopHand: THandle;
begin
  Result:=FindWindow('Progman', nil);
  Result:=GetWindow(Result, GW_Child);
  Result:=GetWindow(Result, GW_Child);
end;

//------------------------------------------------------------------------------

constructor TMyShellChangeThread.Create;
begin
  FreeOnTerminate := True;
  //FChangeEvent := ChangeEvent;
  FMutex := CreateMutex(nil, True, nil);
  //Mutex is used to wake up the thread as it waits for any change notifications.
  WaitForSingleObject(FMutex, INFINITE); //Grab the mutex.
  FWaitChanged := false;
  inherited Create(True);
end;

destructor TMyShellChangeThread.Destroy;
begin
  if FWaitHandle <> ERROR_INVALID_HANDLE then
    FindCloseChangeNotification(FWaitHandle);
  CloseHandle(FMutex);
  DeleteCriticalSection(CS);
  inherited Destroy;
end;

//------------------------------------------------------------------------------

procedure TMyShellChangeThread.GetDesktopIconPosition;
const
  MaxTextLen = 1023;
  StrDesktopIconPosition = 'DesktopIconPosition';
var
  DeskTopHandle : THandle;
  ItemText: array[0..MaxTextLen] of char;
  Item: TLvItem;

  dwProcessID: DWORD;
  hProcess: THandle;
  lpTextRemote: Pointer;
  lpPositionRemote: Pointer;
  lpListItemRemote: Pointer;

  lpData: Pointer;
  I, J, IntA, vItemCount : Integer;
  dwBytesRead, dwBytesWrite: DWORD;
  ptPosition : TPoint;
  Ini : TIniFile;
  IsExit : Boolean;
  KeyList: TStringList;
  InocPosition : array of Integer;
begin
  //Sleep(2000);
  IsExit:=False;
  I:=0;
    repeat
      DeskTopHandle:=GetDesktopHand;
      if DeskTopHandle = 0 then Sleep(100);
      Inc(I);
    until (DeskTopHandle > 0) or (I > 50);

  GetWindowThreadProcessId(DeskTopHandle, @dwProcessID);
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessID);

  if hProcess = 0 then
  begin
  GetWindowThreadProcessId(DeskTopHandle, @dwProcessID);
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessID);
   if hProcess = 0 then Exit; //得不到指定進程的句柄
  end;

  KeyList:= TStringList.Create;
  Ini:=TIniFile.Create(StrVIPSet);
  Ini.ReadSection(StrDesktopIconPosition,  KeyList);
  if KeyList.Count = 0 then Exit;
  SetLength(InocPosition, KeyList.Count);
  for I := 0 to KeyList.Count -1 do
  InocPosition[I]:=Ini.ReadInteger(StrDesktopIconPosition, KeyList[I], 0);

  try
    lpData := VirtualAllocEx(hProcess, nil, MaxTextLen + 1 + SizeOf(TPoint) + SizeOf(TLvItem), MEM_COMMIT, PAGE_READWRITE);

    if not Assigned(lpData) then Exit;

    lpTextRemote := lpData;
    lpPositionRemote := PChar(lpData) + MaxTextLen + 1;
    lpListItemRemote := PChar(lpData) + MaxTextLen + 1 + SizeOf(TPoint);

    try
      ZeroMemory(@ItemText, MaxTextLen + 1);
      WriteProcessMemory(hProcess, lpTextRemote, @ItemText, MaxTextLen + 1, dwBytesWrite);
      WriteProcessMemory(hProcess, lpPositionRemote, @ptPosition, SizeOf(TPoint), dwBytesWrite);

      ZeroMemory(@Item, SizeOf(TLvItem));
      with Item do
      begin
      mask := LVIF_TEXT;
      iItem := 0;
      iSubItem := 0;
      pszText := lpTextRemote;
      cchTextMax := MaxTextLen;
      end;
      dwBytesWrite := 0;

      if not WriteProcessMemory(hProcess, lpListItemRemote, @Item, sizeof(TLvItem), dwBytesWrite) then Exit;

          vItemCount := ListView_GetItemCount(DeskTopHandle);

          for I:=0 to vItemCount -1 do
          begin
          IntA:= 0;
          SendMessage(DeskTopHandle, LVM_GETITEMTEXT, I, LPARAM(lpListItemRemote));
          SendMessage(DeskTopHandle, LVM_GETITEMPOSITION, I, LPARAM(lpPositionRemote));
          ReadProcessMemory(hProcess, lpTextRemote, @ItemText, MaxTextLen + 1, dwBytesRead);
          ReadProcessMemory(hProcess, lpPositionRemote, @ptPosition, SizeOf(TPoint), dwBytesRead);
            for J:= 0 to KeyList.Count -1 do
            begin
              if KeyList[J] = ItemText then
              begin
              IntA:= MakeLparam(ptPosition.X, ptPosition.Y);
                if InocPosition[J] <> IntA then
                begin
                Ini.WriteInteger(StrDesktopIconPosition, ItemText, IntA);
                InocPosition[J]:=IntA;
                //Form_SaveVIPSet.Memo1.Lines.Add(ItemText + '  ' +  InttoStr(IntA));
                Break;
                end;
              end;
            end;  { for J:= 0 to KeyList.Count -1 do }

            if IntA = 0 then
            begin
            IntA:= MakeLparam(ptPosition.X, ptPosition.Y);
            Ini.WriteInteger(StrDesktopIconPosition, ItemText, IntA);
            KeyList.Add(ItemText);
            SetLength(InocPosition, KeyList.Count);
            InocPosition[KeyList.Count-1]:=IntA;
            //Form_SaveVIPSet.Memo1.Lines.Add(ItemText + '  ' +  InttoStr(IntA));
            end;
          end;

    finally
      VirtualFreeEx(hProcess, lpData, 0, MEM_RELEASE);
    end;
  finally
    CloseHandle(hProcess);
  end;

end;

//------------------------------------------------------------------------------

procedure TMyShellChangeThread.Execute;
var
  Obj: DWORD;
  Handles: array[0..1] of DWORD;
begin
  InitializeCriticalSection(CS);
  EnterCriticalSection(CS);
  FWaitHandle := FindFirstChangeNotification(MyDesktop, // 要监视的目录
                                             False, // 如果为TRUE,表示监视lpPathName的所有子目录
                                             FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_SIZE);  // 带有前缀FILE_NOTIFY_CHANGE_???前缀的一个或多个常数,它们指定了对象发出信号的条件

  LeaveCriticalSection(CS);
  if FWaitHandle = ERROR_INVALID_HANDLE then Exit;
  while not Terminated do
  begin
    Handles[0] := FWaitHandle;
    Handles[1] := FMutex;
    Obj := WaitForMultipleObjects(2, @Handles, False, INFINITE);
    case Obj of
      WAIT_OBJECT_0:
        begin
          Synchronize(GetDesktopIconPosition);     // FChangeEvent
          FindNextChangeNotification(FWaitHandle);
        end;
      WAIT_OBJECT_0 + 1:
        ReleaseMutex(FMutex);
      WAIT_FAILED:
        Exit;
    end;
    EnterCriticalSection(CS);
    if FWaitChanged then
    begin
      FWaitHandle := FindFirstChangeNotification(MyDesktop,
         False, FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_SIZE);
      FWaitChanged := false;
    end;
    LeaveCriticalSection(CS);
  end;
end;

end.

调用:

uses ShellChangeNotifierThread;

var
  MyShellChangeThreadA : TMyShellChangeThread;

begin
  MyShellChangeThreadA.Create;  // 一运行到这句就读内存出错!!!不知是什么原因!!!
end;

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 189
活跃值: (4810)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
顶起!!!!!!!!!!!!!!
2008-5-9 14:46
0
游客
登录 | 注册 方可回帖
返回
//