Marinus posted a cute TTS example here (http://masm32.com/board/index.php?topic=2096.msg21923#msg21923) five years ago. When playing with it, I noticed that it works fine as long as you don't debug it. The exception happens here (Win7-64):
InterlockedDecreme Ú$ 8B4C24 04 mov ecx, [esp+4] ; KERNELBASE.InterlockedDecrement(guessed Arg1)
77666A98 ³. B8 FFFFFFFF mov eax, -1
77666A9D ³. F0:0FC101 lock xadd [ecx], eax
77666AA1 ³. 48 dec eax
77666AA2 À. C2 0400 retn 4
Chasing the problem is a bit difficult because InterlockedDecrement gets called a Million times. Any idea if this is a bug, a feature, whatever?
P.S.: No crash in my XP VM (but the voice is awful). On Win10, it works fine in normal mode but crashes when debugging. And surprisingly, the voice is female and talks Italian. On my Italian Win7-64, the voice is male and talks English.
Hi,
on my windows 10 enterprise everything works as it should, code can be debugged, only if you do not enter the system libraries, otherwise, the debugger interacts with system exceptions, and you get exceptions like yours, this can be corrected, you can add regions that exclude exception handling in the debugger program... :t
Thanks, I've tried (Olly 2.0) to add the InterlockedDecrement range, to ignore all access violations, nothing works :(
Interesting phenomenon, maybe we can use it as an anti debug feature?
Yep, turn a bug into a feature :t
Still, I would like to understand what causes the exception... does anybody have ISpVoice::Speak code that does not trigger this exception when being debugged?
Example
The following is an example to enumerate all the available voices registered under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices.
// Declare local identifiers:
HRESULT hr = S_OK;
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
CComPtr<ISpVoice> cpVoice;
ULONG ulCount = 0;
// Create the SAPI voice.
hr = cpVoice.CoCreateInstance(CLSID_SpVoice);
if (SUCCEEDED (hr))
{
// Enumerate the available voices.
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum;);
}
if (SUCCEEDED (hr))
{
// Get the number of voices.
hr = cpEnum->GetCount(&ulCount;);
}
// Obtain a list of available voice tokens, set
// the voice to the token, and call Speak.
while (SUCCEEDED(hr) && ulCount--)
{
cpVoiceToken.Release();
if (SUCCEEDED (hr))
{
hr = cpEnum->Next(1, &cpVoiceToken;, NULL);
}
if (SUCCEEDED (hr))
{
hr = cpVoice->SetVoice(cpVoiceToken);
}
if (SUCCEEDED (hr))
{
hr = cpVoice->Speak( L"How are you?", SPF_DEFAULT, NULL );
}
}
if (SUCCEEDED (hr))
{
// Do more stuff here.
}
Probably not all exceptions are added, x64dbg produce the same reaction?
For poasm:.486
.model flat, stdcall
extern stdcall _imp__CoInitialize@4 :proc
extern stdcall _imp__CoCreateInstance@20 :proc
extern stdcall _imp__CoUninitialize@0 :proc
extern stdcall _imp__ExitProcess@4 :proc
includelib kernel32.lib
includelib ole32.lib
GUID STRUCT
Data1 dd ?
Data2 dw ?
Data3 dw ?
Data4 db 8 dup(?)
GUID ENDS
.data
CLSID_SpVoice GUID {096749377h,03391h,011D2h,<09Eh,0E3h,000h,0C0h,04Fh,079h,073h,096h>}
IID_ISpVoice GUID {06C44DF74h,072B9h,04992h,<0A1h,0ECh,0EFh,099h,06Eh,004h,022h,0D4h>}
msg dw 'H', 'e', 'l', 'l', 'o', 0
.code
_WinMainCRTStartup proc C
push ebp
mov ebp, esp
sub esp, 4h
mov dword ptr [ebp-4h], 0h
push 0h
call dword ptr [_imp__CoInitialize@4]
lea eax, [ebp-4h]
push eax
push offset IID_ISpVoice
push 17h
push 0h
push offset CLSID_SpVoice
call dword ptr [_imp__CoCreateInstance@20]
test eax, eax
jl L_57
push 0h
push 0h
push offset msg
push dword ptr [ebp-4h]
mov eax, dword ptr [ebp-4h]
mov eax, dword ptr [eax]
call dword ptr [eax+50h]
push dword ptr [ebp-4h]
mov eax, dword ptr [ebp-4h]
mov eax, dword ptr [eax]
call dword ptr [eax+8h]
mov dword ptr [ebp-4h], 0h
L_57:
call dword ptr [_imp__CoUninitialize@0]
push 0h
call dword ptr [_imp__ExitProcess@4]
mov esp, ebp
pop ebp
ret
_WinMainCRTStartup endp
end
Exceptions:Error code: (Win32) 0x6ba (1722) - The RPC server is unavailable.
Error code: (Win32) 0x71a (1818) - The remote procedure call was cancelled.