Is it possible to move the desktop shortcuts?? perhaps let them flee when the cursor wants to click them ;)
Posted on 2004-02-27 16:14:14 by chromos
I've never tried it but, IIRC the desktop is nothing more than a big list-view control. So use FindWindow(Ex) to get a handle to the SysListView32 (it should be a child control of a window called 'program manager') and then send LVM_SETITEMPOSITION messages to rearrange the icons. Also use SetWindowLong() to remove the LVS_AUTOARRANGE style, and maybe use SetWindowPos() to make sure the style was removed.

If that doesn't work try subclassing the control and blocking some messages that it might be using to keep other applications from messing with it.
Posted on 2004-02-27 16:31:08 by iblis
thanx a lot.
I'll try that
Posted on 2004-02-28 07:49:24 by chromos
I wasn't able to retrieve the SysListView32 Handle via FindWindowEx(). So i had to call WindowFromPoint() and finally got the handle.
Now my Question:
Is there another way to get the handle beside mine WindowFromPoint() call, wich means also minimizin all opened windows to get the handle?
Posted on 2004-02-28 11:09:51 by chromos
Try this :

invoke GetDesktopWindow

invoke EnumChildWindows,eax,OFFSET EnumProc,OFFSET hListview

EnumProc FRAME hwnd,lParam
LOCAL ClassName[256] :B

invoke GetClassName,[hwnd],OFFSET ClassName,256
invoke lstrcmpi,OFFSET ClassName,"SysListView32"
or eax,eax
jnz >
mov ecx,[lParam]
mov eax,[hwnd]
mov [ecx],eax
mov eax,FALSE
ret
:
RET
ENDF


The handle of the Listview is returned in hListview
Posted on 2004-02-28 12:27:08 by donkey
A quick scan with WinSpy yields this window hierarchy:


#32769 (Desktop window)

|
|____Progman (Program Manager)
|
|____SHELLDLL_DefView
|
|____SysListView32 (FolderView)


That's on Windows XP, I don't know about the other windows versions.
So the window you want is a few more levels deep than I had originally thought.

I just tried moving the icons around and it works. But for some reason LVM_GETITEMPOSITION fails to report the correct item positions, so I was unable to return the icons to their original positions. LVM_GETITEMPOSITION returns TRUE, but still it fails to fill in the POINT struct I send to it.

/shrug.
Posted on 2004-02-28 14:04:36 by iblis
Hi Iblis

Working on the assumption that it is the lowest listview in the Z-Order no matter what, the proc I posted should acutally be like this, then it will find it reliably :

invoke GetDesktopWindow

invoke EnumChildWindows,eax,OFFSET EnumProc,OFFSET hListview

EnumProc FRAME hwnd,lParam
LOCAL ClassName[256] :B

invoke GetClassName,[hwnd],OFFSET ClassName,256
invoke lstrcmpi,OFFSET ClassName,"SysListView32"
or eax,eax
jnz >
mov ecx,[lParam]
mov eax,[hwnd]
mov [ecx],eax
:
[b]mov eax,TRUE[/b]
ret
ENDF
Posted on 2004-02-28 14:15:35 by donkey
The way I did it was just:

invoke FindWindow, "progman", 0

invoke FindWindowEx, eax, 0, "SHELLDLL_DefView", 0
invoke FindWindowEx, eax, 0, "SysListView32", 0
mov hListView, eax


Whatever works is fine I suppose. Finding the window is easy.

I'm still trying to figure out why the desktop list-view ignores the LVM_GETITEMPOSITION message. Or rather, it ignores the reference to the POINT structure. I know that it is acknowledging the reference because, just to test, I sent a NULL reference and received a FALSE return value, and then I tried an invalid address, and explorer crashes. So apparently it's doing something with that POINT reference, but whatever it's doing, it's not filling in the structure with the requested info.

So not being able to retrieve the position of the desktop items will make it more difficult to perpetuate the idea that chromos had, which was to make the icon dance around the screen out of the user's reach as the mouse moves over it.
Posted on 2004-02-28 17:06:21 by iblis
If I remember correctly, the only way to get this to work is to make a dll that gets injected into explorer.exe's address space. A Jeffrey Richter book I have at work explains how and why. I'll post more details when I bring it home.
Posted on 2004-02-28 19:04:48 by Mecurius
Cool, Mercurius.

That would be great.
Posted on 2004-02-28 22:58:53 by iblis
Mmmm,

I think you would just be required to create a memory buffer in the process of the desktop. This doesn't necessarily imply a DLL, I will try to experiment with VirtualAllocEx and create a buffer in the desktop process. Might be simpler and you could handle it inside the app.
Posted on 2004-02-28 23:48:34 by donkey
This appears to work :

GetItemPos FRAME hlv,iItem,pPoint

LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D

invoke GetWindowThreadProcessId, [hlv], OFFSET PID
invoke OpenProcess, PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess], eax

invoke VirtualAllocEx, eax, NULL, 1024, MEM_COMMIT, PAGE_READWRITE
mov [pMem], eax

invoke SendMessage, [hlv], LVM_GETITEMPOSITION, [iItem], [pMem]

invoke ReadProcessMemory, [hProcess], [pMem], [pPoint], 8,OFFSET cbWritten

invoke VirtualFreeEx, [hProcess], [pMem], 1024, MEM_RELEASE
invoke CloseHandle, [hProcess]

RET
ENDF
Posted on 2004-02-29 00:10:42 by donkey
A little more complex is to read and write to the desktop to get the LV_ITEM structure, you must also take into account the buffer that will be used to hold the text:

GetRemoteItem FRAME hlv,pLVItem

uses ebx
LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D

invoke GetWindowThreadProcessId,[hlv],OFFSET PID
invoke OpenProcess,PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess],eax

invoke VirtualAllocEx, eax, NULL, 1024, MEM_COMMIT, PAGE_READWRITE
mov [pMem],eax

mov eax,[pMem]
add eax,256
mov ecx,[pLVItem]
mov ebx,[ecx+LV_ITEM.pszText]
mov [ecx+LV_ITEM.pszText],eax
invoke WriteProcessMemory, [hProcess], [pMem],\
[pLVItem], SIZEOF LV_ITEM, OFFSET cbWritten

invoke SendMessage,[hlv],LVM_GETITEM,0,[pMem]

invoke ReadProcessMemory, [hProcess], [pMem], \
[pLVItem], SIZEOF LV_ITEM, OFFSET cbWritten

mov eax,[pLVItem]
mov ecx,[eax+LV_ITEM.cchTextMax]
mov [eax+LV_ITEM.pszText],ebx

mov eax,[pMem]
add eax,256
invoke ReadProcessMemory, [hProcess], eax, ebx, ecx, OFFSET cbWritten

invoke VirtualFreeEx, [hProcess], [pMem], 1024, MEM_RELEASE
invoke CloseHandle, [hProcess]

RET
ENDF


Called it with this:

mov D[lvi.imask],LVIF_TEXT

mov D[lvi.pszText],OFFSET lvtext
mov D[lvi.cchTextMax],255
mov D[lvi.iItem],0
invoke GetRemoteItem,[hListView],OFFSET lvi

PrintString(lvtext)

Output was :

Line 50: lvtext = My Documents
Posted on 2004-02-29 00:34:50 by donkey
wow cool that some people find dancing icon as interesting as i do :).
I'll try some of your ways.
Posted on 2004-02-29 06:06:38 by chromos

wow cool that some people find dancing icon as interesting as i do :).
I'll try some of your ways.

Well, more interested in the problem actually, I'm not quite clear on what the icons will do or why but it is an interesting coding problem given that it requires a little thinking to get the information you need.
Posted on 2004-02-29 11:09:38 by donkey
Oh, I see. I had figured that since it was a systemwide control that interprocess issues wouldn't be a problem. I guess explorer subclasses it or something.

Good job Donkey. I wonder if the IShell interface has any means to do this? I haven't worked with it enough to know.
Posted on 2004-02-29 12:48:28 by iblis
Hi iblis,

My first instinct was IShellView2, the SelectAndPositionItem method might be used for this if you can get an interface to the destop listview. Haven't tried it but I imagine it could be done.
Posted on 2004-02-29 13:12:34 by donkey
There was a rather disasterous memory leak in the code I posted, the VirtualFreeEx line should read:

invoke VirtualFreeEx,,,0,MEM_RELEASE

This is the final version :

GetItemPos FRAME hlv,iItem,pPoint

LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D

invoke GetWindowThreadProcessId,[hlv],OFFSET PID
invoke OpenProcess,PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess],eax

invoke VirtualAllocEx, eax, NULL, 8, MEM_COMMIT, PAGE_READWRITE
mov [pMem],eax

invoke SendMessage, [hlv], LVM_GETITEMPOSITION, [iItem], [pMem]

invoke ReadProcessMemory, [hProcess], [pMem], [pPoint], 8, OFFSET cbWritten

invoke VirtualFreeEx,[hProcess],[pMem],0,MEM_RELEASE
invoke CloseHandle,[hProcess]

RET
ENDF

GetRemoteItem FRAME hlv,pLVItem
uses ebx,edi,esi
LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D

invoke GetWindowThreadProcessId,[hlv],OFFSET PID
invoke OpenProcess,PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess],eax

mov edi,[pLVItem]

mov ecx,SIZEOF LV_ITEM
add ecx,[edi+LV_ITEM.cchTextMax]
inc ecx

invoke VirtualAllocEx, eax, NULL, ecx, MEM_COMMIT, PAGE_READWRITE
mov [pMem],eax

; Substitute the address of the local pszText buffer for the remote one
mov esi,eax
add esi,SIZEOF LV_ITEM

mov ebx,[edi+LV_ITEM.pszText]
mov [edi+LV_ITEM.pszText],esi

invoke WriteProcessMemory,[hProcess],[pMem],[pLVItem],\
SIZEOF LV_ITEM,OFFSET cbWritten

invoke SendMessage,[hlv],LVM_GETITEM,0,[pMem]

invoke ReadProcessMemory,[hProcess],[pMem],[pLVItem],\
SIZEOF LV_ITEM,OFFSET cbWritten

; reset the address of the pszText buffer
mov [edi+LV_ITEM.pszText],ebx

; copy the text from the remote buffer
invoke ReadProcessMemory,[hProcess],esi,ebx,\
[edi+LV_ITEM.cchTextMax],OFFSET cbWritten

invoke VirtualFreeEx,[hProcess],[pMem],0,MEM_RELEASE
invoke CloseHandle,[hProcess]

RET
ENDF
Posted on 2004-02-29 20:54:52 by donkey
perhaps i should have said that i write in c, i understand also most of your code, but i dont understand, why i do not get the Handle via inline asm, how Iblis got it.

invoke FindWindow, "progman", 0
invoke FindWindowEx, eax, 0, "SHELLDLL_DefView", 0
invoke FindWindowEx, eax, 0, "SysListView32", 0
mov hListView, eax

PS: Of course I didn't use the masm Syntax in c.

Perhaps i was yesterday also only too tired, to get the code working. I'll have a look at it this evening.
Posted on 2004-03-01 01:07:32 by chromos
wow hm pretty amazing, the FindWindow calls return always 0 as handle, although they got the handle of "SysListView32".
According to the msdn Description of the return value, I quoute :
"If the function fails, the return value is NULL."

hm strange, and this took me 3 days to solve .... omg.
Posted on 2004-03-02 07:24:08 by chromos