Page 1 of 1

VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 15 Jun 2020, 07:49
by uname
Recently I've noticed my main persistent script hangs sometimes, I've traced the issue to the VA_IAudioSessionControl2_GetProcessId call, the script below never show the Msgbox and can be closed by process termination only.

Code: Select all

IID_IAudioSessionManager2 := "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}"

dev := VA_GetDevice()
VA_IMMDevice_Activate(dev, IID_IAudioSessionManager2, 7, 0, mgr)
ObjRelease(dev)
VA_IAudioSessionManager2_GetSessionEnumerator(mgr, enm)
ObjRelease(mgr)
VA_IAudioSessionEnumerator_GetSession(enm, 0, ssn)
VA_IAudioSessionControl2_GetProcessId(ssn, PID)
ObjRelease(ssn)
ObjRelease(enm)

MsgBox % PID
The code has worked flawlessly for last 8 years, something changed in my system and I can't find the problem myself
AHK 1.1.32.00 x64 and WIndows 10 x64 Pro 2004

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 21 Jun 2020, 22:02
by uname
Can somebody test the code on Windows 10 2004 please.

Re: VA_IAudioSessionControl2_GetProcessId hangs the script  Topic is solved

Posted: 01 Jul 2020, 04:08
by lexikos
I have deleted the "duplicate" topic from Bug Reports. An issue in a user-defined function occurring after a Windows update is clearly not an AutoHotkey bug.

In this case, I'm fairly certain the issue is because you are making an invalid call. IAudioSessionEnumerator::GetSession() is documented as returning IAudioSessionControl, not IAudioSessionControl2. As the latter inherits from the former, you might get an IAudioSessionControl2 anyway, but it was never guaranteed. You must query for the correct interface with ComObjQuery.

On my system (Windows 2004) your script does not stall, but returns PID 0 for every session.

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 01 Jul 2020, 16:36
by uname
Thank you!

So all this time my script was missing the lines

Code: Select all

VA_IAudioSessionEnumerator_GetSession(enm, 0, IAudioSessionControl)
ssn := ComObjQuery(IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}")
ObjRelease(IAudioSessionControl)
By the way, the source was posted here

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 01 Jul 2020, 18:33
by malcev
To get a reference to the IAudioSessionControl2 interface, the application must call IAudioSessionControl::QueryInterface to request the interface pointer from the stream object's IAudioSessionControl interface
https://docs.microsoft.com/en-us/windows/win32/api/audiopolicy/nn-audiopolicy-iaudiosessioncontrol2
It is not good that library va.ahk does not check errors.

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 03 Jul 2020, 21:33
by lexikos
@malcev, as with DllCall, if you pass invalid parameters, that's your problem. One can only check the type of an interface pointer if it is a valid interface pointer derived from IUnknown, which is the case here, but not for all invalid parameters. These functions are basic low level wrappers for interface methods. A higher level library is safer and has no need for interface type checks, because you do not deal with interface pointers - for instance, VA_GetMasterVolume("", "playback").

I don't know why you linked to IAudioSessionControl2. Anyone can find the documentation by searching.

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 05 Jul 2020, 19:38
by malcev
lexikos wrote:
03 Jul 2020, 21:33
@malcev, as with DllCall, if you pass invalid parameters, that's your problem.
I do not agree with You.
If You add error checking then the topicstarter would get error, that will help him to understand that this error is not autohotkey bug, but error calling GetProcessId method.
ERROR_SXS_KEY_NOT_FOUND

Code: Select all

VA_IAudioSessionControl2_GetProcessId(this, ByRef pid)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "uint*", pid)
   if hr or ErrorLevel
      msgbox % hr "`n" ErrorLevel "`n" A_LastError
}

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 06 Jul 2020, 05:10
by lexikos
There is no guarantee that calling an invalid virtual function will result in an error code return. You don't even know which function you're calling, or that there's even a function at that slot in the virtual function table. The added error checking would be a waste of space, because passing an invalid interface pointer still means that the program logic cannot be relied upon. Worse, it would mislead you into thinking the function will protect you from your own mistakes.

If you pass an invalid interface pointer, there is no guarantee that you will even be able to get far enough to attempt to call the function.

Re: VA_IAudioSessionControl2_GetProcessId hangs the script

Posted: 06 Jul 2020, 05:36
by malcev
There is no guarantee, but there is a small chance that when You call invalid virtual function or You pass invalid parameters You will not get error code.
When I worked with complex Directx11 and Microsoft Media Foundation stuff, error checking helps me understand what I did wrong.
And there was situation when method`s return value was OK, but Errorlevel = 0xc0000005 (because of old videocard driver I think).
By the way if You think that error checking is waste of space why did You check each method for errors in Your directx wrapper?

Code: Select all

ERRq(....)
https://www.autohotkey.com/boards/viewtopic.php?t=28834