The MASM Forum

General => The Workshop => Topic started by: jj2007 on December 17, 2018, 09:48:09 PM

Title: Text to Speech access violation
Post by: jj2007 on December 17, 2018, 09:48:09 PM
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.
Title: Re: Text to Speech access violation
Post by: LiaoMi on December 22, 2018, 08:53:24 AM
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
Title: Re: Text to Speech access violation
Post by: jj2007 on December 22, 2018, 02:52:02 PM
Thanks, I've tried (Olly 2.0) to add the InterlockedDecrement range, to ignore all access violations, nothing works :(
Title: Re: Text to Speech access violation
Post by: Siekmanski on December 22, 2018, 03:32:06 PM
Interesting phenomenon, maybe we can use it as an anti debug feature?
Title: Re: Text to Speech access violation
Post by: jj2007 on December 22, 2018, 03:55:47 PM
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?
Title: Re: Text to Speech access violation
Post by: LiaoMi on December 22, 2018, 09:00:00 PM
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?
Title: Re: Text to Speech access violation
Post by: TimoVJL on December 22, 2018, 11:10:29 PM
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.