ComObjQuery / vtable

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

ComObjQuery / vtable

09 Jan 2015, 19:06

Regarding the first example on the ComObjQuery docs page, how do you tell which function is at an nth position in a virtual function table?
Coco-guest

Re: ComObjQuery / vtable

09 Jan 2015, 19:19

I would usually do a web search with something like "IDispatch methods in vtable order" etc. Not really sure, maybe if you install Windows SDK, you can check the header file...
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: ComObjQuery / vtable

10 Jan 2015, 02:51

View the interface definition in its header file. If you don't have the SDK on hand, you might find the appropriate header file via Google or searchcode.com. Searching for the plain C definition (typedef struct InterfaceNameVtbl) might get more relevant results. It also saves you having to take into account which methods are inherited from other interfaces, because they're defined explicitly.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: ComObjQuery / vtable

10 Jan 2015, 03:13

lexikos wrote:Searching for the plain C definition (typedef struct InterfaceNameVtbl) might get more relevant results.
Thanks for this.
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: ComObjQuery / vtable

11 Jan 2015, 01:26

I tried to recreate the example here (See "Bringing it All Together - Sample Code"). The script should use IActiveDesktop::GetWallpaper to get the name of the current wallpaper.
I think I found the correct vtable offset by looking in Shlobj.h, but I am still failing to understand something because the script crashes.

Code: Select all

AD_GETWP_BMP := 0
CLSID_ActiveDesktop := "{75048700-EF1F-11D0-9888-006097DEACF9}"
IID_IActiveDesktop := "{f490eb00-1240-11d1-9888-006097deacf9}"
cchWallpaper := 260
AD := ComObjCreate(CLSID_ActiveDesktop, IID_IActiveDesktop)
hr := DllCall(vtable(AD, 4), "Ptr", AD, "Ptr*", wszWallpaper, "UInt", cchWallpaper, "UInt", AD_GETWP_BMP) ; GetWallpaper
Wallpaper := StrGet(wszWallpaper, "UTF-16")
MsgBox, % "hr: " hr "`nWallpaper: " Wallpaper
ObjRelease(AD)
ExitApp

vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: ComObjQuery / vtable

11 Jan 2015, 02:19

hr := DllCall(vtable(AD, 4), "Ptr", AD, "Ptr", wszWallpaper := 0, "UInt", cchWallpaper, "UInt", AD_GETWP_BMP), the one in red prevents the crash but HRESULT != 0

This one kinda works (changed Ptr to Str), but I only get C:\:

Code: Select all

AD_GETWP_BMP := 0
CLSID_ActiveDesktop := "{75048700-EF1F-11D0-9888-006097DEACF9}"
IID_IActiveDesktop := "{f490eb00-1240-11d1-9888-006097deacf9}"
cchWallpaper := 260
AD := ComObjCreate(CLSID_ActiveDesktop, IID_IActiveDesktop)
hr := DllCall(vtable(AD, 4), "Ptr", AD, "Str", wszWallpaper := 0, "UInt", cchWallpaper, "UInt", AD_GETWP_BMP) ; GetWallpaper
; Wallpaper := StrGet(wszWallpaper, "UTF-16")
MsgBox, % "hr: " hr "`nWallpaper: " . wszWallpaper ; Wallpaper
ObjRelease(AD)
ExitApp

vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: ComObjQuery / vtable

11 Jan 2015, 02:32

Yes, when I try that I get 0x80070057, which is E_INVALIDARG - One or more arguments are not valid.
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: ComObjQuery / vtable

11 Jan 2015, 02:37

Coco wrote:This one kinda works (changed Ptr to Str), but I only get C:\
I posted before I saw your edit. I just get C:\ too, not sure why.
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: ComObjQuery / vtable

11 Jan 2015, 02:41

Thanks Coco, I think I got it. I added VarSetCapacity() for wszWallpaper.

Code: Select all

AD_GETWP_BMP := 0
CLSID_ActiveDesktop := "{75048700-EF1F-11D0-9888-006097DEACF9}"
IID_IActiveDesktop := "{f490eb00-1240-11d1-9888-006097deacf9}"
cchWallpaper := 260
AD := ComObjCreate(CLSID_ActiveDesktop, IID_IActiveDesktop)
VarSetCapacity(wszWallpaper, A_IsUnicode ? 520 : 260, 0)
hr := DllCall(vtable(AD, 4), "Ptr", AD, "str", wszWallpaper := 0, "UInt", cchWallpaper, "UInt", AD_GETWP_BMP) ; GetWallpaper
MsgBox, % "hr: " hr "`nWallpaper: " . wszWallpaper
ObjRelease(AD)
ExitApp

vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
Based on the ComObjQuerry example in the docs I expected "Ptr*" to work.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ComObjQuery / vtable

11 Jan 2015, 02:49

When this method returns, contains a pointer to a null-terminated, Unicode buffer that contains the file name of the wallpaper.

Code: Select all

#NoEnv
AD_GETWP_BMP := 0
AD_GETWP_LAST_APPLIED := 0x00000002
CLSID_ActiveDesktop := "{75048700-EF1F-11D0-9888-006097DEACF9}"
IID_IActiveDesktop := "{f490eb00-1240-11d1-9888-006097deacf9}"
cchWallpaper := 260
VarSetCapacity(wszWallpaper, cchWallpaper * 2, 0)
AD := ComObjCreate(CLSID_ActiveDesktop, IID_IActiveDesktop)
hr := DllCall(vtable(AD, 4), "Ptr", AD, "Ptr", &wszWallpaper, "UInt", cchWallpaper, "UInt", AD_GETWP_LAST_APPLIED) ; GetWallpaper
Wallpaper := StrGet(&wszWallpaper, "UTF-16")
MsgBox, % "hr: " hr "`nWallpaper: " Wallpaper
ObjRelease(AD)
ExitApp

vtable(ptr, n) {
    ; NumGet(ptr+0) returns the address of the object's virtual function
    ; table (vtable for short). The remainder of the expression retrieves
    ; the address of the nth function's address from the vtable.
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: ComObjQuery / vtable

11 Jan 2015, 02:54

Thanks just me! Silly mistake on my part, since all strings returned from COM methods should be Unicode regardless of the AHK version. "Ptr", &wszWallpaper makes more sense to me now too.
Coco
Posts: 771
Joined: 29 Sep 2013, 20:37
Contact:

Re: ComObjQuery / vtable

11 Jan 2015, 03:07

We totally forgot that we need to initialize wszWallpaper...lol
User avatar
theimmersion
Posts: 181
Joined: 09 Jul 2016, 08:34
Location: Serbia

Re: ComObjQuery / vtable

13 Mar 2018, 09:18

Late to this conversation but hope someone might still be looking at this and have an answer.

I found some info about IActiveDesktop to be able to change a wallpaper with fade like when dekstop wallpaper slide is enabled.
Can you somehow make a code like the above to also set a wallpaper via IActiveDesktop?
I could not find anything else in regards to changing wallpapers via AHK but with fade effect. Im not gonna even try go the hack/workaround (draw fake background etc) route, dont think its viable at all unless with some form of native MS stuff.
So far, im using "DllCall("SystemParametersInfo", UINT, 0x14, UINT, 0, STR, image_file, UINT, 2)" to change wallpapers but by God, its ugly when it does that.
Thanks for the above, will come in handy as well one day. :)

I dont even understand why MS didnt do the fade effect on that call as well. I see no point to have such a behavior as a default.

Even the right click context "Set as desktop background" does not fade and i really dont see the reason why.
At least not on Win 10. I thought we improved with soft/hardware enough to have something this simple yet pleasing feature (that could also be optional of course but easier accessible). Oh well. xD

This was my attempt and of course it doesnt work.

Code: Select all

	CLSID_ActiveDesktop := "{75048700-EF1F-11D0-9888-006097DEACF9}"
	IID_IActiveDesktop := "{f490eb00-1240-11d1-9888-006097deacf9}"
	cchWallpaper := 260
	VarSetCapacity(file, cchWallpaper * 2, 0)
	file := A_Desktop . "\the_purge__election_year___vector_wallpaper_2_by_elclon-da9w8qe.png"
	AD := ComObjCreate(CLSID_ActiveDesktop, IID_IActiveDesktop)
	hr := DllCall(vtable(AD, 4), "Ptr", file, "UInt", 0)
	ObjRelease(AD)
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ComObjQuery / vtable

13 Mar 2018, 09:47

Code: Select all

file := A_Desktop . "\the_purge__election_year___vector_wallpaper_2_by_elclon-da9w8qe.png"
hr := DllCall(vtable(AD, 5), "Ptr", AD, "WStr", file, "UInt", 0, "UInt") ; IActiveDesktop::SetWallpaper
?
User avatar
theimmersion
Posts: 181
Joined: 09 Jul 2016, 08:34
Location: Serbia

Re: ComObjQuery / vtable

13 Mar 2018, 09:58

Doesnt seem to do anything.
Am i missing a mistake i made?

Code: Select all

	CLSID_ActiveDesktop := "{75048700-EF1F-11D0-9888-006097DEACF9}"
	IID_IActiveDesktop := "{f490eb00-1240-11d1-9888-006097deacf9}"
	cchWallpaper := 260
	VarSetCapacity(file, cchWallpaper * 2, 0)
	file := A_Desktop . "\the_purge__election_year___vector_wallpaper_2_by_elclon-da9w8qe.png"
	AD := ComObjCreate(CLSID_ActiveDesktop, IID_IActiveDesktop)
	hr := DllCall(vtable(AD, 5), "Ptr", AD, "WStr", file, "UInt", 0, "UInt") ; IActiveDesktop::SetWallpaper
	ObjRelease(AD)
Edit, also hr returns 0. It should return something like an ms error code on fail or S_OK.
Thanks for trying to help! :D
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ComObjQuery / vtable

13 Mar 2018, 10:23

S_OK = 0. I cannot see a mistake in your attempt. Sorry!
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ComObjQuery / vtable

13 Mar 2018, 10:37

Maybe you need to call IActiveDesktop::ApplyChanges additionally:

Code: Select all

hr := DllCall(vtable(AD, 5), "Ptr", AD, "WStr", file, "UInt", 0, "UInt") ; IActiveDesktop::SetWallpaper
hr := DllCall(vtable(AD, 3), "Ptr", AD, "UInt", 0x07, "UInt") ; IActiveDesktop::ApplyChanges - AD_APPLY_ALL

Code: Select all

////////////////////////////////////////////
// Flags for IActiveDesktop::ApplyChanges()
#define AD_APPLY_SAVE             0x00000001
#define AD_APPLY_HTMLGEN          0x00000002
#define AD_APPLY_REFRESH          0x00000004
#define AD_APPLY_ALL              (AD_APPLY_SAVE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH)
#define AD_APPLY_FORCE            0x00000008
#define AD_APPLY_BUFFERED_REFRESH 0x00000010
#define AD_APPLY_DYNAMICREFRESH   0x00000020
User avatar
theimmersion
Posts: 181
Joined: 09 Jul 2016, 08:34
Location: Serbia

Re: ComObjQuery / vtable

13 Mar 2018, 11:18

This works, but still no fade effect. :headwall:
Ok, so i experimented a bit and its the AD_APPLY_SAVE that triggers the change (but instant). Trying different combinations but so far no luck.
jeuneperkersauvage

Re: ComObjQuery / vtable

13 Mar 2018, 11:30

Active Desktop hasn't been a thing on Windows for a long time now. And good riddance. It might have been the IE part that provided the fade effect.

On Windows 10, you should be using IDesktopWallpaper - https://msdn.microsoft.com/en-us/librar ... s.85).aspx

SetWallpaper might do the fade effect, but it's unlikely. Instead, you might try this sequence as a last resort:

* SetSlideshowOptions to disable shuffling (maybe optional) and set a long transition time (and maybe GetSlideshowOptions to get the current results so that you can save them for later)
* GetWallpaper to get the path of a current wallpaper
* SetSlideshow to add that current wallpaper and the new wallpaper to a slideshow
* AdvanceSlideshow to go to the new wallpaper with the fade effect
* SetWallpaper to set the wallpaper to the same thing, removing the slideshow, but without any aesthetically displeasing "jolts" to the new wallpaper
User avatar
theimmersion
Posts: 181
Joined: 09 Jul 2016, 08:34
Location: Serbia

Re: ComObjQuery / vtable

13 Mar 2018, 11:53

Yeah, ive seen that everyone said how IActiveDesktop was not used anymore past Windows XP but still worked in Vista and 7 and i think i read 8 as well.
But all those codes i saw are for C/C++ and i dont know how and if possible to translate into AHK code.

Heres one site i saw for Win 7 apparently working.
https://www.neowin.net/forum/topic/1035 ... wallpaper/
Heres another interesting one.
https://stackoverflow.com/questions/147 ... er-restart

All have one thing in common i guess and its the handle. I made sure WorkerW is the handle but still no fade.
Also, i saw somewhere it was possible in C/C++ to trigger WorkerW to become desktops handle without going in task view or personalize->wallpaper.
But again, no idea how to turn the code into AHK if even possible.

Man, MS did some BS for a simple wallpaper change with fade. -.-

How would IDesktopWallpaper look like? No idea how to swap that for IActiveDesktop to give it a try.
In mean time, ill keep digging and experimenting.

How you know which of these options you mentioned are the number for (i assume) vtable(AD, *option number*) ?

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 240 guests