Opened 8 years ago

Closed 23 months ago

#3159 closed Bug (Fixed)

ObjCreateInterface and BOOL type.

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


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

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
	$sId = DllStructGetData(DllStructCreate("wchar ID[" & __Audio_WinAPI_PtrStringLenW($pID) & "]", $pID), "ID")
	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 With and later (including 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 to so if it broke somewhere earlier I missed the exact build. I'm running Windows 10 x64 but this isn't OS specific.

Attachments (0)

Change History (4)

comment:1 Changed 6 years ago by Jpm

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

comment:2 Changed 4 years ago by Jpm

not working in X64 only after

comment:3 Changed 4 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 4 years ago by Jpm (previous) (diff)

comment:4 Changed 23 months 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 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

Modify Ticket

as closed The owner will remain Jon.

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

Note: See TracTickets for help on using tickets.