| /* |
| * Speech API (SAPI) token implementation. |
| * |
| * Copyright (C) 2017 Huw Davies |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| #include <stdarg.h> |
| |
| #define COBJMACROS |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "objbase.h" |
| #include "sapiddk.h" |
| #include "sperror.h" |
| |
| #include "wine/debug.h" |
| |
| #include "sapi_private.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(sapi); |
| |
| struct data_key |
| { |
| ISpRegDataKey ISpRegDataKey_iface; |
| LONG ref; |
| |
| HKEY key; |
| BOOL read_only; |
| }; |
| |
| struct data_key *impl_from_ISpRegDataKey( ISpRegDataKey *iface ) |
| { |
| return CONTAINING_RECORD( iface, struct data_key, ISpRegDataKey_iface ); |
| } |
| |
| static HRESULT WINAPI data_key_QueryInterface( ISpRegDataKey *iface, REFIID iid, void **obj ) |
| { |
| struct data_key *This = impl_from_ISpRegDataKey( iface ); |
| |
| TRACE( "(%p)->(%s %p)\n", This, debugstr_guid( iid ), obj ); |
| |
| if (IsEqualIID( iid, &IID_IUnknown ) || |
| IsEqualIID( iid, &IID_ISpDataKey ) || |
| IsEqualIID( iid, &IID_ISpRegDataKey )) |
| { |
| ISpRegDataKey_AddRef( iface ); |
| *obj = iface; |
| return S_OK; |
| } |
| |
| FIXME( "interface %s not implemented\n", debugstr_guid( iid ) ); |
| *obj = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI data_key_AddRef( ISpRegDataKey *iface ) |
| { |
| struct data_key *This = impl_from_ISpRegDataKey( iface ); |
| ULONG ref = InterlockedIncrement( &This->ref ); |
| |
| TRACE( "(%p) ref = %u\n", This, ref ); |
| return ref; |
| } |
| |
| static ULONG WINAPI data_key_Release( ISpRegDataKey *iface ) |
| { |
| struct data_key *This = impl_from_ISpRegDataKey( iface ); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE( "(%p) ref = %u\n", This, ref ); |
| |
| if (!ref) |
| { |
| if (This->key) RegCloseKey( This->key ); |
| heap_free( This ); |
| } |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI data_key_SetData( ISpRegDataKey *iface, LPCWSTR name, |
| ULONG size, const BYTE *data ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_GetData( ISpRegDataKey *iface, LPCWSTR name, |
| ULONG *size, BYTE *data ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_SetStringValue( ISpRegDataKey *iface, |
| LPCWSTR name, LPCWSTR value ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_GetStringValue( ISpRegDataKey *iface, |
| LPCWSTR name, LPWSTR *value ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_SetDWORD( ISpRegDataKey *iface, |
| LPCWSTR name, DWORD value ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_GetDWORD( ISpRegDataKey *iface, |
| LPCWSTR name, DWORD *pdwValue ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_OpenKey( ISpRegDataKey *iface, |
| LPCWSTR name, ISpDataKey **sub_key ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_CreateKey( ISpRegDataKey *iface, |
| LPCWSTR name, ISpDataKey **sub_key ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_DeleteKey( ISpRegDataKey *iface, LPCWSTR name ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_DeleteValue( ISpRegDataKey *iface, LPCWSTR name ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_EnumKeys( ISpRegDataKey *iface, |
| ULONG index, LPWSTR *sub_key ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_EnumValues( ISpRegDataKey *iface, |
| ULONG index, LPWSTR *value ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI data_key_SetKey( ISpRegDataKey *iface, |
| HKEY key, BOOL read_only ) |
| { |
| struct data_key *This = impl_from_ISpRegDataKey( iface ); |
| |
| TRACE( "(%p)->(%p %d)\n", This, key, read_only ); |
| |
| if (This->key) return SPERR_ALREADY_INITIALIZED; |
| |
| This->key = key; |
| This->read_only = read_only; |
| return S_OK; |
| } |
| |
| const struct ISpRegDataKeyVtbl data_key_vtbl = |
| { |
| data_key_QueryInterface, |
| data_key_AddRef, |
| data_key_Release, |
| data_key_SetData, |
| data_key_GetData, |
| data_key_SetStringValue, |
| data_key_GetStringValue, |
| data_key_SetDWORD, |
| data_key_GetDWORD, |
| data_key_OpenKey, |
| data_key_CreateKey, |
| data_key_DeleteKey, |
| data_key_DeleteValue, |
| data_key_EnumKeys, |
| data_key_EnumValues, |
| data_key_SetKey |
| }; |
| |
| HRESULT data_key_create( IUnknown *outer, REFIID iid, void **obj ) |
| { |
| struct data_key *This = heap_alloc( sizeof(*This) ); |
| HRESULT hr; |
| |
| if (!This) return E_OUTOFMEMORY; |
| This->ISpRegDataKey_iface.lpVtbl = &data_key_vtbl; |
| This->ref = 1; |
| This->key = NULL; |
| This->read_only = FALSE; |
| |
| hr = ISpRegDataKey_QueryInterface( &This->ISpRegDataKey_iface, iid, obj ); |
| |
| ISpRegDataKey_Release( &This->ISpRegDataKey_iface ); |
| return hr; |
| } |
| |
| struct token_enum |
| { |
| ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface; |
| LONG ref; |
| |
| BOOL init; |
| WCHAR *req, *opt; |
| ULONG count; |
| }; |
| |
| struct token_enum *impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder *iface ) |
| { |
| return CONTAINING_RECORD( iface, struct token_enum, ISpObjectTokenEnumBuilder_iface ); |
| } |
| |
| static HRESULT WINAPI token_enum_QueryInterface( ISpObjectTokenEnumBuilder *iface, |
| REFIID iid, void **obj ) |
| { |
| struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface ); |
| |
| TRACE( "(%p)->(%s %p)\n", This, debugstr_guid( iid ), obj ); |
| |
| if (IsEqualIID( iid, &IID_IUnknown ) || |
| IsEqualIID( iid, &IID_IEnumSpObjectTokens ) || |
| IsEqualIID( iid, &IID_ISpObjectTokenEnumBuilder )) |
| { |
| ISpObjectTokenEnumBuilder_AddRef( iface ); |
| *obj = iface; |
| return S_OK; |
| } |
| |
| FIXME( "interface %s not implemented\n", debugstr_guid( iid ) ); |
| *obj = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI token_enum_AddRef( ISpObjectTokenEnumBuilder *iface ) |
| { |
| struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface ); |
| ULONG ref = InterlockedIncrement( &This->ref ); |
| |
| TRACE( "(%p) ref = %u\n", This, ref ); |
| return ref; |
| } |
| |
| static ULONG WINAPI token_enum_Release( ISpObjectTokenEnumBuilder *iface ) |
| { |
| struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface ); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE( "(%p) ref = %u\n", This, ref ); |
| |
| if (!ref) |
| { |
| heap_free( This->req ); |
| heap_free( This->opt ); |
| heap_free( This ); |
| } |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI token_enum_Next( ISpObjectTokenEnumBuilder *iface, |
| ULONG num, ISpObjectToken **tokens, |
| ULONG *fetched ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_Skip( ISpObjectTokenEnumBuilder *iface, |
| ULONG num ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_Reset( ISpObjectTokenEnumBuilder *iface) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_Clone( ISpObjectTokenEnumBuilder *iface, |
| IEnumSpObjectTokens **clone ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_Item( ISpObjectTokenEnumBuilder *iface, |
| ULONG index, ISpObjectToken **token ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_GetCount( ISpObjectTokenEnumBuilder *iface, |
| ULONG *count ) |
| { |
| struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface ); |
| |
| TRACE( "(%p)->(%p)\n", This, count ); |
| |
| if (!This->init) return SPERR_UNINITIALIZED; |
| |
| *count = This->count; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI token_enum_SetAttribs( ISpObjectTokenEnumBuilder *iface, |
| LPCWSTR req, LPCWSTR opt) |
| { |
| struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface ); |
| |
| TRACE( "(%p)->(%s %s)\n", This, debugstr_w( req ), debugstr_w( opt ) ); |
| |
| if (This->init) return SPERR_ALREADY_INITIALIZED; |
| |
| if (req) |
| { |
| This->req = heap_strdupW( req ); |
| if (!This->req) goto out_of_mem; |
| } |
| |
| if (opt) |
| { |
| This->opt = heap_strdupW( opt ); |
| if (!This->opt) goto out_of_mem; |
| } |
| |
| This->init = TRUE; |
| return S_OK; |
| |
| out_of_mem: |
| heap_free( This->req ); |
| return E_OUTOFMEMORY; |
| } |
| |
| static HRESULT WINAPI token_enum_AddTokens( ISpObjectTokenEnumBuilder *iface, |
| ULONG num, ISpObjectToken **tokens ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_AddTokensFromDataKey( ISpObjectTokenEnumBuilder *iface, |
| ISpDataKey *data_key, |
| LPCWSTR sub_key, LPCWSTR cat_id ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_AddTokensFromTokenEnum( ISpObjectTokenEnumBuilder *iface, |
| IEnumSpObjectTokens *token_enum ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI token_enum_Sort( ISpObjectTokenEnumBuilder *iface, |
| LPCWSTR first ) |
| { |
| FIXME( "stub\n" ); |
| return E_NOTIMPL; |
| } |
| |
| const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl = |
| { |
| token_enum_QueryInterface, |
| token_enum_AddRef, |
| token_enum_Release, |
| token_enum_Next, |
| token_enum_Skip, |
| token_enum_Reset, |
| token_enum_Clone, |
| token_enum_Item, |
| token_enum_GetCount, |
| token_enum_SetAttribs, |
| token_enum_AddTokens, |
| token_enum_AddTokensFromDataKey, |
| token_enum_AddTokensFromTokenEnum, |
| token_enum_Sort |
| }; |
| |
| HRESULT token_enum_create( IUnknown *outer, REFIID iid, void **obj ) |
| { |
| struct token_enum *This = heap_alloc( sizeof(*This) ); |
| HRESULT hr; |
| |
| if (!This) return E_OUTOFMEMORY; |
| This->ISpObjectTokenEnumBuilder_iface.lpVtbl = &token_enum_vtbl; |
| This->ref = 1; |
| This->req = NULL; |
| This->opt = NULL; |
| This->init = FALSE; |
| This->count = 0; |
| |
| hr = ISpObjectTokenEnumBuilder_QueryInterface( &This->ISpObjectTokenEnumBuilder_iface, iid, obj ); |
| |
| ISpObjectTokenEnumBuilder_Release( &This->ISpObjectTokenEnumBuilder_iface ); |
| return hr; |
| } |