Thema: LuckieDIPS

Einzelnen Beitrag anzeigen

NicoDE
(Gast)

n/a Beiträge
 
#31

Re: LuckieDIPS

  Alt 18. Feb 2005, 16:41
Wenn wir schon dabei sind, 64-Bit Support...

GetDesktopIconInfo()
Delphi-Quellcode:
const
  ItemBufferBlockSize = $1000;

type
  PLvItemBuffer = ^TLvItemBuffer;
  TLvItemBuffer = packed record
    case Integer of
      0: (
        LvItem32: packed record
          mask : LongWord;
          iItem : LongInt;
          iSubItem : LongInt;
          state : LongWord;
          stateMask : LongWord;
          pszText : LongWord;
          cchTextMax: LongInt;
          iImage : LongInt;
          lParam : LongWord;
          iIndent : LongInt;
          iGroupId : LongInt;
          cColumns : LongWord;
          puColumns : LongWord
        end);
      1: (
        LvItem64: packed record
          mask : LongWord;
          iItem : LongInt;
          iSubItem : LongInt;
          state : LongWord;
          stateMask : LongWord;
          _align1 : LongWord;
          pszText : Int64;
          cchTextMax: LongInt;
          iImage : LongInt;
          lParam : Int64;
          iIndent : LongInt;
          iGroupId : LongInt;
          cColumns : LongWord;
          _align2 : LongWord;
          puColumns : Int64;
        end);
      2: (LvItemBuff: array [0..ItemBufferBlockSize - 1] of Byte;
    case Integer of
      0: (AnsiText: array [0..ItemBufferBlockSize - 1] of AnsiChar);
      1: (WideText: array [0..ItemBufferBlockSize div 2 - 1] of WideChar);
      2: (ItemText: array [0..ItemBufferBlockSize div SizeOf(Char)-1] of Char));
  end;

type
  TFNIsWow64Process = function(hProcess: THandle; out Wow64Process: BOOL): BOOL;
    stdcall;

var
  FNIsWow64Process: TFNIsWow64Process;

function IsWow64Process(hProcess: THandle): Boolean;
var
  Wow64Process: BOOL;
begin
  if not Assigned(FNIsWow64Process) then
    FNIsWow64Process := TFNIsWow64Process(
      GetProcAddress(GetModuleHandle(kernel32), 'IsWow64Process'));
  if not Assigned(FNIsWow64Process) then
    Result := False
  else
    Result := FNIsWow64Process(hProcess, Wow64Process) and Wow64Process;
end;

function GetDesktopIconInfo: TDesktopIconInfoArray;
var
  ListView : HWND;
  ProcessId: DWORD;
  Process : THandle;
  Size : Cardinal; // SIZE_T
  MemLocal : PLvItemBuffer;
  MemRemote: PLvItemBuffer;
  NumBytes : Cardinal; // SIZE_T
  IconCount: DWORD;
  IconIndex: Integer;
  IconLabel: string;
  IconPos : TPoint;
  DesktopIconInfoArray: TDesktopIconInfoArray;
begin
  // Fensterhandle des Desktop-ListView ermitteln und Prozess oeffnen
  ListView := GetDesktopListView;
  ProcessId := 0;
  GetWindowThreadProcessId(ListView, @ProcessId);
  Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or
    PROCESS_VM_READ or PROCESS_VM_WRITE, False, ProcessId);
  if Process <> 0 then
  try
    // Lokalen und entfernten (im Zielprozess) Puffer anlegen
    Size := SizeOf(TLvItemBuffer);
    MemLocal := VirtualAlloc(nil, Size, MEM_COMMIT, PAGE_READWRITE);
    MemRemote := VirtualAllocEx(Process, nil, Size, MEM_COMMIT, PAGE_READWRITE);
    if Assigned(MemLocal) and Assigned(MemRemote) then
    try
      // Anzahl der Symbole ermitteln und in einer Schleife durchlaufen
      IconCount := SendMessage(ListView, LVM_GETITEMCOUNT, 0, 0);
      Setlength(DesktopIconInfoArray, IconCount);
      for IconIndex := 0 to IconCount - 1 do
      begin
        // Symboltext auslesen
        // (es gibt zwei identische Strukturen, jeweils eine in diesem und eine
        // im Zielprozess. Wobei die Daten zwischen den Puffern hin und her
        // kopiert werden muessen. Dieser Aufwand ist noetig, da LVM_GETITEM
        // eine Struktur liest und schreibt, die sich im Adressraum des
        // Prozesses befindet, dem das entsprechende Fenster gehoert...)
        ZeroMemory(MemLocal, SizeOf(TLvItemBuffer));
        with MemLocal^ do
          if IsWow64Process(GetCurrentProcess) and
            not IsWow64Process(Process) then
          begin
            LvItem64.mask := LVIF_TEXT;
            LvItem64.iItem := IconIndex;
            LvItem64.pszText := Cardinal(MemRemote) + ItemBufferBlockSize;
            LvItem64.cchTextMax := High(MemLocal.ItemText) + 1;
          end
          else
          begin
            LvItem32.mask := LVIF_TEXT;
            LvItem32.iItem := IconIndex;
            LvItem32.pszText := Cardinal(MemRemote) + ItemBufferBlockSize;
            LvItem32.cchTextMax := High(MemLocal.ItemText) + 1;
          end;
        NumBytes := 0;
        if WriteProcessMemory(Process, MemRemote, MemLocal, Size, NumBytes) and
          Boolean(SendMessage(ListView, LVM_GETITEM, 0, LPARAM(MemRemote))) and
          ReadProcessMemory(Process, MemRemote, MemLocal, Size, NumBytes) then
        begin
          IconLabel := string(MemLocal.ItemText);
          // Position auslesen
          // (-1, -1 ist nur ein Indiz fuer einen Fehlschlag, da diese Position
          // natuerlich moeglich ist...)
          IconPos.X := -1;
          IconPos.Y := -1;
          if Boolean(SendMessage(ListView, LVM_GETITEMPOSITION, IconIndex,
            LPARAM(MemRemote))) and ReadProcessMemory(Process, MemRemote,
            MemLocal, Size, NumBytes) then
          begin
            IconPos := PPoint(MemLocal)^;
          end;
          // Speichern ;)
          DesktopIconInfoArray[IconIndex].Caption := IconLabel;
          DesktopIconInfoArray[IconIndex].Position.X := IconPos.X;
          DesktopIconInfoArray[IconIndex].Position.Y := IconPos.Y;
        end;
        result := DesktopIconInfoArray;
      end;
    except
      // Exceptions ignorieren
    end;
    // Aufraeumen
    if Assigned(MemRemote) then
      VirtualFreeEx(Process, MemRemote, 0, MEM_RELEASE);
    if Assigned(MemLocal) then
      VirtualFree(MemLocal, 0, MEM_RELEASE);
  finally
    CloseHandle(Process);
  end;
end;
SetDesktopIconPos()
Delphi-Quellcode:
function SetDesktopIconPos(DesktopIconInfoArray: TDesktopIconInfoArray):
  Boolean;
var
  Listview : HWND;
  ProcessId: DWORD;
  Process : THandle;
  Size : Cardinal;
  MemLocal : PLvItemBuffer;
  MemRemote: PLvItemBuffer;
  IconCount: Integer;
  IconIndex: Integer;
  IconLabel: string;
  IconPos : TPoint;
  NumBytes : Cardinal;
  Loop : Integer;
begin
  Result := False;
  // Kommentare siehe GetDesktopIconInfo ;o)
  ListView := GetDesktopListView();
  ProcessId := 0;
  GetWindowThreadProcessId(ListView, @ProcessId);
  Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or
    PROCESS_VM_READ or PROCESS_VM_WRITE, False, ProcessId);
  if Process <> 0 then
  try
    Size := SizeOf(TLVItemBuffer);
    MemLocal := VirtualAlloc(nil, Size, MEM_COMMIT, PAGE_READWRITE);
    MemRemote := VirtualAllocEx(Process, nil, Size, MEM_COMMIT, PAGE_READWRITE);
    if Assigned(MemLocal) and Assigned(MemRemote) then
    try
      IconCount := SendMessage(ListView, LVM_GETITEMCOUNT, 0, 0);
      for IconIndex := 0 to IconCount - 1 do
      begin
        ZeroMemory(MemLocal, SizeOf(TLvItemBuffer));
        with MemLocal^ do
          if IsWow64Process(GetCurrentProcess) and
            not IsWow64Process(Process) then
          begin
            LvItem64.mask := LVIF_TEXT;
            LvItem64.iItem := IconIndex;
            LvItem64.pszText := Cardinal(MemRemote) + ItemBufferBlockSize;
            LvItem64.cchTextMax := High(MemLocal.ItemText) + 1;
          end
          else
          begin
            LvItem32.mask := LVIF_TEXT;
            LvItem32.iItem := IconIndex;
            LvItem32.pszText := Cardinal(MemRemote) + ItemBufferBlockSize;
            LvItem32.cchTextMax := High(MemLocal.ItemText) + 1;
          end;
        NumBytes := 0;
        if WriteProcessMemory(Process, MemRemote, MemLocal, Size, NumBytes) and
          Boolean(SendMessage(ListView, LVM_GETITEM, 0, LPARAM(MemRemote))) and
          ReadProcessMemory(Process, MemRemote, MemLocal, Size, NumBytes) then
        begin
          IconLabel := string(MemLocal.ItemText);
          for Loop := 0 to Length(DesktopIconInfoArray) - 1 do
          begin
            if DesktopIconInfoArray[Loop].Caption = IconLabel then
            begin
              IconPos.X := DesktopIconInfoArray[IconIndex].Position.X;
              IconPos.Y := DesktopIconInfoArray[IconIndex].Position.Y;
              Result := BOOL(SendMessage(Listview, LVM_SETITEMPOSITION, Loop,
                MAKELPARAM(IconPos.X, IconPos.Y)));
            end;
          end;
        end;
      end;
    except
      // Exceptions ignorieren
    end;
    if Assigned(MemLocal) then
      VirtualFree(MemLocal, 0, MEM_RELEASE);
    if Assigned(MemRemote) then
      VirtualFreeEx(Process, MemRemote, 0, MEM_RELEASE);
  finally
    CloseHandle(Process);
  end;
end;
BTW, in der Schleife von GetDesktopIconInfoFromIni() sollte überprüft werden ob Length(IniSections[Loop]) > 0 ist (sonst kommt es bei einer (angeblich) leeren Section zu einer Zugriffsverletzung).


Gruss Nico

ps: für Unicode müsste man das Programm komplett umschreiben (habe Dateien mit japanischen Symbolen auf dem Desktop...)
  Mit Zitat antworten Zitat