Modify

Opened 9 years ago

Closed 3 years ago

#3159 closed Bug (Fixed)

ObjCreateInterface and BOOL type.

Reported by: Valik Owned by: Jon
Milestone: Component: AutoIt
Version: 3.3.14.0 Severity: None
Keywords: Cc:

Description

Apologies for the large script but this is the minimum I could get it down to to demonstrate the bug.

; Interface description for IMMDeviceEnumerator.
Global Const $__Audio_CLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
Global Const $__Audio_IID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
Global Const $__Audio_tagIMMDeviceEnumerator = "EnumAudioEndpoints hresult(dword;dword;ptr*);" & _
	"GetDefaultAudioEndpoint hresult(dword;dword;ptr*);" & _
	"GetDevice hresult(wstr;ptr*);" & _
	"RegisterEndpointNotificationCallback hresult(ptr);" & _
	"UnregisterEndpointNotificationCallback hresult(ptr);"

; Interface description for IMMDevice.
Global Const $__Audio_IID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
Global Const $__Audio_tagIMMDevice = "Activate hresult(clsid;dword;variant*;ptr*);" & _
	"OpenPropertyStore hresult(dword;ptr*);" & _
	"GetId hresult(ptr*);" & _
	"GetState hresult(dword*);"

; Interface description for IAudioEndpointVolume
Global Const $__Audio_IID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
Global Const $__Audio_tagIAudioEndpointVolume = "RegisterControlChangeNotify hresult(ptr);" & _
	"UnregisterControlChangeNotify hresult(ptr);" & _
	"GetChannelCount hresult(UINT*);" & _
	"SetMasterVolumeLevel hresult(float;ptr);" & _
	"SetMasterVolumeLevelScalar hresult(float;ptr);" & _
	"GetMasterVolumeLevel hresult(float*);" & _
	"GetMasterVolumeLevelScalar hresult(float*);" & _
	"SetChannelVolumeLevel hresult(UINT;float;ptr);" & _
	"SetChannelVolumeLevelScalar hresult(UINT;float;ptr);" & _
	"GetChannelVolumeLevel hresult(UINT;float*);" & _
	"GetChannelVolumeLevelScalar hresult(UINT;float*);" & _
	"SetMute hresult(BOOL;ptr);" & _		; <--- This method doesn't work. Change "BOOL" to "int" and it suddenly works agian.
	"GetMute hresult(BOOL*);" & _
	"GetVolumeStepInfo hresult(UINT*;UINT*);" & _
	"VolumeStepUp hresult(ptr);" & _
	"VolumeStepDown hresult(ptr);" & _
	"QueryHardwareSupport hresult(DWORD*);" & _
	"GetVolumeRange hresult(float*;float*;float*);"

Global Const $__Audio_eRender = 0
Global Const $__Audio_eMultimedia = 1
Global Const $__AUDIO_CLSCTX_ALL = BitOR(0x1, 0x2, 0x4, 0x10)	; CLSCTX_INPROC_SERVER, CLSCTX_INPROC_HANDLER, CLSCTX_LOCAL_SERVER, CLSCTX_REMOTE_SERVER

Func Audio_GetDefaultAudioEndpoint()
	Local $oEnumerator = ObjCreateInterface($__Audio_CLSID_MMDeviceEnumerator, $__Audio_IID_IMMDeviceEnumerator, $__Audio_tagIMMDeviceEnumerator)

	Local $pEndpoint
	$oEnumerator.GetDefaultAudioEndpoint($__Audio_eRender, $__Audio_eMultimedia, $pEndpoint)
	Local $oEndpoint = ObjCreateInterface($pEndpoint, $__Audio_IID_IMMDevice, $__Audio_tagIMMDevice)

	Local $pID, $sId
	; Collect ID
	$oEndpoint.GetId($pID)
	$sId = DllStructGetData(DllStructCreate("wchar ID[" & __Audio_WinAPI_PtrStringLenW($pID) & "]", $pID), "ID")
	__Audio_WinAPI_CoTaskMemFree($pID)
	Return $sId
EndFunc	; Audio_GetDefaultAudioEndpoint()

Func Audio_SetDeviceMute($sDeviceID, $bMute)
	; Create the IMMDeviceEnumerator object.
	Local $oEnumerator = ObjCreateInterface($__Audio_CLSID_MMDeviceEnumerator, $__Audio_IID_IMMDeviceEnumerator, $__Audio_tagIMMDeviceEnumerator)

	; Get device pointer.
	Local $pDevice
	$oEnumerator.GetDevice($sDeviceID, $pDevice)

	; Convert the device pointer into an object.
	Local $oDevice = ObjCreateInterface($pDevice, $__Audio_IID_IMMDevice, $__Audio_tagIMMDevice)

	; Get the IAudioEndpointVolume pointer.
	Local $pAudioEndpointVolume
	$oDevice.Activate($__Audio_IID_IAudioEndpointVolume, $__AUDIO_CLSCTX_ALL, 0, $pAudioEndpointVolume)

	; Convert the IAudioEndpointVolume pointer into an object.
	Local $oAudioEndpointVolume = ObjCreateInterface($pAudioEndpointVolume, $__Audio_IID_IAudioEndpointVolume, $__Audio_tagIAudioEndpointVolume)

	; Set the mute state.
	$oAudioEndpointVolume.SetMute($bMute, 0)
EndFunc	; Audio_SetDeviceMute()

Func __Audio_WinAPI_CoTaskMemFree($pMem)
	DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pMem)
	If @error Then Return SetError(1, 0, False)
	Return True
EndFunc	; __Audio_WinAPI_CoTaskMemFree()

Func __Audio_WinAPI_PtrStringLenW($pString)
	Local $aCall = DllCall("kernel32.dll", "dword", "lstrlenW", "ptr", $pString)
	If @error Then Return SetError(1, 0, 0)
	Return $aCall[0]
EndFunc	; __Audio_WinAPI_PtrStringLenW()

Audio_SetDeviceMute(Audio_GetDefaultAudioEndpoint(), 1)

The last line is a called to Audio_SetDeviceMute() to mute the currently active audio device. The call worked fine in 3.3.8.1. With 3.3.14.0 and later (including 3.3.15.0) it doesn't work when I declare SetMute() as a BOOL:

SetMute hresult(BOOL;ptr);

If I change BOOL to int it works. It seems somewhere along the way AutoIt's conversion to BOOL in this case is failing. Passing a 0 will correctly unmute a muted device. Passing a 1 (the value of TRUE in the Windows SDK) fails.

To reiterate, this is a regression. It used to work fine. With the latest versions of AutoIt, it does not. Unfortunately I jumped straight from 3.3.8.1 to 3.3.14.0 so if it broke somewhere earlier I missed the exact build. I'm running Windows 10 x64 but this isn't OS specific.

Change History (4)

comment:1 Changed 7 years ago by Jpm

  • Owner set to Jon
  • Status changed from new to assigned

comment:2 Changed 5 years ago by Jpm

not working in X64 only after 3.3.12.0

comment:3 Changed 5 years ago by Jpm

it looks like Jon as change something in the way it produce the code.
When I try to reproduce without signing the code X64 is working fine.
I hope JON can find why. I am running under Windows 10 (2004) and use the Visual studio 2017 (community)

Edited: I can add that my test don't use the code optimisation (PGO)

Last edited 5 years ago by Jpm (previous) (diff)

comment:4 Changed 3 years ago by Jpm

  • Resolution set to Fixed
  • Status changed from assigned to closed

It was related with code optimisation (PGO).
It has been fixed since 3.3.15.1 when Jon fix the PGO process

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.