////////////////////////////////////////////////////////////////////////////////
// Diese Funktion ist zwar einfach, aber nicht sicher genug (WinXP)
{-----------------------------------------------------------------------------
Procedure : GetDesktopListView - Author : -
Purpose : Desktop Listview Handle ermitteln
Result : HWND
-----------------------------------------------------------------------------}
function GetDesktopListView(): HWND;
var
ClassName :
string;
begin
Result := FindWindow('
ProgMan',
nil);
Result := GetWindow(Result, GW_CHILD);
Result := GetWindow(Result, GW_CHILD);
SetLength(ClassName, 40);
SetLength(ClassName, GetClassName(Result, PChar(ClassName), 39));
if (ClassName <> '
SysListView32')
then
begin
MessageBox(0, PChar(ERROR_GETDESKTOPHANDLE), APPNAME, MB_ICONERROR
or MB_OK);
Result := 0;
end;
end;
////////////////////////////////////////////////////////////////////////////////
// Durch die Verwendung von VirtualAllocEx() funktioniert dieser Code nur auf NT
{-----------------------------------------------------------------------------
Procedure : GetDesktopIconInfo - Author : Nico Bendlin
Purpose : Gets the caption and the position of the desktopicons
Result : TDesktopIconInfoArray
-----------------------------------------------------------------------------}
function GetDesktopIconInfo(): TDesktopIconInfoArray;
var
ListView : HWND;
ProcessId : DWORD;
Process : THandle;
Size : Cardinal;
// SIZE_T
MemLocal : Pointer;
MemRemote : Pointer;
NumBytes : Cardinal;
// SIZE_T
IconCount : DWORD;
IconIndex : Integer;
IconLabel :
string;
IconPos : TPoint;
DesktopIconInfoArray: TDesktopIconInfoArray;
begin
// Fensterhandle des Desktop-ListView ermitteln und Prozess oeffnen
ProcessId := 0;
ListView := GetDesktopListView();
GetWindowThreadProcessId(ListView, @ProcessId);
Process := OpenProcess(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(TLVItem) + SizeOf(Char) * MAX_PATH + 1;
MemLocal := VirtualAlloc(
nil, Size, MEM_RESERVE
or MEM_COMMIT,
PAGE_READWRITE);
MemRemote := VirtualAllocEx(Process,
nil, Size, MEM_RESERVE
or 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(TLVItem));
with PLVItem(MemLocal)^
do
begin
mask := LVIF_TEXT;
iItem := IconIndex;
// Der Puffer fuer den Text liegt direkt hinter der TLVItem-Struktur
pszText := LPTSTR(Cardinal(MemRemote) + Cardinal(SizeOf(TLVItem)));
cchTextMax := MAX_PATH;
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(
PChar(Cardinal(MemLocal) + Cardinal(SizeOf(TLVItem))));
// 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;