From: Shaun Ren sren@codeweavers.com
--- dlls/sapi/tests/token.c | 24 +++++++++ dlls/sapi/token.c | 117 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/dlls/sapi/tests/token.c b/dlls/sapi/tests/token.c index 9350c304e41..a725dfa78ac 100644 --- a/dlls/sapi/tests/token.c +++ b/dlls/sapi/tests/token.c @@ -248,6 +248,8 @@ static void test_token_enum(void) HRESULT hr; IDispatch *disp; ISpeechObjectTokens *speech_tokens; + IUnknown *unk; + IEnumVARIANT *enumvar; ISpObjectToken *tokens[5]; ISpObjectToken *out_tokens[5]; WCHAR token_id[MAX_PATH]; @@ -348,6 +350,28 @@ static void test_token_enum(void) &IID_ISpObjectTokenEnumBuilder, (void **)&token_enum ); ok( hr == S_OK, "got %08lx\n", hr );
+ hr = ISpObjectTokenEnumBuilder_QueryInterface( token_enum, + &IID_ISpeechObjectTokens, + (void **)&speech_tokens ); + ok( hr == S_OK, "got %08lx\n", hr ); + + hr = ISpObjectTokenEnumBuilder_AddTokens( token_enum, 3, tokens ); + ok( hr == S_OK, "got %08lx\n", hr ); + + hr = ISpeechObjectTokens_get__NewEnum( speech_tokens, &unk ); + ok( hr == S_OK, "got %08lx\n", hr ); + hr = IUnknown_QueryInterface( unk, &IID_IEnumVARIANT, (void **)&enumvar ); + ok( hr == S_OK, "got %08lx\n", hr ); + IUnknown_Release( unk ); + IEnumVARIANT_Release( enumvar ); + + ISpeechObjectTokens_Release( speech_tokens ); + ISpObjectTokenEnumBuilder_Release( token_enum ); + + hr = CoCreateInstance( &CLSID_SpObjectTokenEnum, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpObjectTokenEnumBuilder, (void **)&token_enum ); + ok( hr == S_OK, "got %08lx\n", hr ); + /* Vendor attribute must exist */ hr = ISpObjectTokenEnumBuilder_SetAttribs( token_enum, L"Vendor", NULL ); ok( hr == S_OK, "got %08lx\n", hr ); diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c index 4688e6a07b9..28c433b0f27 100644 --- a/dlls/sapi/token.c +++ b/dlls/sapi/token.c @@ -599,6 +599,20 @@ static struct token_enum *impl_from_ISpeechObjectTokens( ISpeechObjectTokens *if return CONTAINING_RECORD( iface, struct token_enum, ISpeechObjectTokens_iface ); }
+struct enum_var +{ + IEnumVARIANT IEnumVARIANT_iface; + LONG ref; + + ISpObjectTokenEnumBuilder *token_enum; + ULONG index; +}; + +static struct enum_var *impl_from_IEnumVARIANT( IEnumVARIANT *iface ) +{ + return CONTAINING_RECORD( iface, struct enum_var, IEnumVARIANT_iface ); +} + static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface, LPCWSTR req, LPCWSTR opt, IEnumSpObjectTokens **enum_tokens ) @@ -1145,6 +1159,86 @@ const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl = token_enum_Sort };
+static HRESULT WINAPI enum_var_QueryInterface( IEnumVARIANT *iface, + REFIID iid, void **obj ) +{ + struct enum_var *This = impl_from_IEnumVARIANT( iface ); + + TRACE( "(%p)->(%s %p)\n", This, debugstr_guid( iid ), obj ); + + if (IsEqualIID( iid, &IID_IUnknown ) || + IsEqualIID( iid, &IID_IEnumVARIANT )) + { + IEnumVARIANT_AddRef( iface ); + *obj = iface; + return S_OK; + } + + *obj = NULL; + FIXME( "interface %s not implemented\n", debugstr_guid( iid ) ); + return E_NOINTERFACE; +} + +static ULONG WINAPI enum_var_AddRef( IEnumVARIANT *iface ) +{ + struct enum_var *This = impl_from_IEnumVARIANT( iface ); + ULONG ref = InterlockedIncrement( &This->ref ); + + TRACE( "(%p) ref = %lu\n", This, ref ); + return ref; +} + +static ULONG WINAPI enum_var_Release( IEnumVARIANT *iface ) +{ + struct enum_var *This = impl_from_IEnumVARIANT( iface ); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE( "(%p) ref = %lu\n", This, ref ); + + if (!ref) + { + ISpObjectTokenEnumBuilder_Release( This->token_enum ); + free( This ); + } + return ref; +} + +static HRESULT WINAPI enum_var_Next( IEnumVARIANT *iface, ULONG count, + VARIANT *vars, ULONG *fetched ) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI enum_var_Skip( IEnumVARIANT *iface, ULONG count ) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI enum_var_Reset( IEnumVARIANT *iface ) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI enum_var_Clone( IEnumVARIANT *iface, IEnumVARIANT **new_enum ) +{ + FIXME("stub\n"); + return E_NOTIMPL; +} + +static const IEnumVARIANTVtbl enum_var_vtbl = +{ + enum_var_QueryInterface, + enum_var_AddRef, + enum_var_Release, + enum_var_Next, + enum_var_Skip, + enum_var_Reset, + enum_var_Clone +}; + static HRESULT WINAPI speech_tokens_QueryInterface( ISpeechObjectTokens *iface, REFIID iid, void **obj ) { @@ -1233,8 +1327,27 @@ static HRESULT WINAPI speech_tokens_Item( ISpeechObjectTokens *iface, static HRESULT WINAPI speech_tokens_get__NewEnum( ISpeechObjectTokens *iface, IUnknown **new_enum ) { - FIXME( "stub\n" ); - return E_NOTIMPL; + struct enum_var *enum_var; + HRESULT hr; + + TRACE( "(%p)->(%p)\n", iface, new_enum ); + + if (!new_enum) return E_POINTER; + if (!(enum_var = malloc( sizeof(*enum_var) ))) return E_OUTOFMEMORY; + + enum_var->IEnumVARIANT_iface.lpVtbl = &enum_var_vtbl; + enum_var->ref = 1; + enum_var->index = 0; + if (FAILED(hr = ISpeechObjectTokens_QueryInterface( iface, &IID_ISpObjectTokenEnumBuilder, + (void **)&enum_var->token_enum ))) + { + free( enum_var ); + return hr; + } + + *new_enum = (IUnknown *)&enum_var->IEnumVARIANT_iface; + + return S_OK; }
static const ISpeechObjectTokensVtbl speech_tokens_vtbl =