| /* | |
| * 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_category | |
| { | |
| ISpObjectTokenCategory ISpObjectTokenCategory_iface; | |
| LONG ref; | |
| ISpRegDataKey *data_key; | |
| }; | |
| struct token_category *impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory *iface ) | |
| { | |
| return CONTAINING_RECORD( iface, struct token_category, ISpObjectTokenCategory_iface ); | |
| } | |
| static HRESULT WINAPI token_category_QueryInterface( ISpObjectTokenCategory *iface, | |
| REFIID iid, void **obj ) | |
| { | |
| struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); | |
| TRACE( "(%p)->(%s %p)\n", This, debugstr_guid( iid ), obj ); | |
| if (IsEqualIID( iid, &IID_IUnknown ) || | |
| IsEqualIID( iid, &IID_ISpDataKey ) || | |
| IsEqualIID( iid, &IID_ISpObjectTokenCategory )) | |
| { | |
| ISpObjectTokenCategory_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_category_AddRef( ISpObjectTokenCategory *iface ) | |
| { | |
| struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); | |
| ULONG ref = InterlockedIncrement( &This->ref ); | |
| TRACE( "(%p) ref = %u\n", This, ref ); | |
| return ref; | |
| } | |
| static ULONG WINAPI token_category_Release( ISpObjectTokenCategory *iface ) | |
| { | |
| struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); | |
| ULONG ref = InterlockedDecrement(&This->ref); | |
| TRACE( "(%p) ref = %u\n", This, ref ); | |
| if (!ref) | |
| { | |
| if (This->data_key) ISpRegDataKey_Release( This->data_key ); | |
| heap_free( This ); | |
| } | |
| return ref; | |
| } | |
| static HRESULT WINAPI token_category_SetData( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, ULONG size, | |
| const BYTE *data ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_GetData( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, ULONG *size, | |
| BYTE *data ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_SetStringValue( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, LPCWSTR value ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_GetStringValue( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, LPWSTR *value ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_SetDWORD( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, DWORD value ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_GetDWORD( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, DWORD *pdwValue ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_OpenKey( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, ISpDataKey **sub_key ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_CreateKey( ISpObjectTokenCategory *iface, | |
| LPCWSTR name, ISpDataKey **sub_key ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_DeleteKey( ISpObjectTokenCategory *iface, | |
| LPCWSTR name ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_DeleteValue( ISpObjectTokenCategory *iface, | |
| LPCWSTR name ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_EnumKeys( ISpObjectTokenCategory *iface, | |
| ULONG index, LPWSTR *sub_key ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_EnumValues( ISpObjectTokenCategory *iface, | |
| ULONG index, LPWSTR *value ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT parse_cat_id( const WCHAR *str, HKEY *root, const WCHAR **sub_key ) | |
| { | |
| static const WCHAR HKLM[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E','\\'}; | |
| static const WCHAR HKCU[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\'}; | |
| struct table | |
| { | |
| const WCHAR *name; | |
| int size; | |
| HKEY key; | |
| } table[] = | |
| { | |
| { HKLM, sizeof(HKLM), HKEY_LOCAL_MACHINE }, | |
| { HKCU, sizeof(HKCU), HKEY_CURRENT_USER }, | |
| { NULL } | |
| }; | |
| struct table *ptr; | |
| int len = strlenW( str ); | |
| for (ptr = table; ptr->name; ptr++) | |
| { | |
| if (len >= ptr->size / sizeof(ptr->name[0]) && !memcmp( str, ptr->name, ptr->size )) | |
| { | |
| *root = ptr->key; | |
| *sub_key = str + ptr->size / sizeof(ptr->name[0]); | |
| return S_OK; | |
| } | |
| } | |
| return S_FALSE; | |
| } | |
| static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface, | |
| LPCWSTR id, BOOL create ) | |
| { | |
| struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); | |
| HKEY root, key; | |
| const WCHAR *subkey; | |
| LONG res; | |
| HRESULT hr; | |
| TRACE( "(%p)->(%s %d)\n", This, debugstr_w( id ), create ); | |
| if (This->data_key) return SPERR_ALREADY_INITIALIZED; | |
| hr = parse_cat_id( id, &root, &subkey ); | |
| if (hr != S_OK) return SPERR_INVALID_REGISTRY_KEY; | |
| if (create) FIXME( "Ignoring create\n" ); | |
| res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); | |
| if (res) return SPERR_INVALID_REGISTRY_KEY; | |
| hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_ALL, | |
| &IID_ISpRegDataKey, (void **)&This->data_key ); | |
| if (FAILED(hr)) goto fail; | |
| hr = ISpRegDataKey_SetKey( This->data_key, key, FALSE ); | |
| if (FAILED(hr)) goto fail; | |
| return hr; | |
| fail: | |
| RegCloseKey( key ); | |
| return hr; | |
| } | |
| static HRESULT WINAPI token_category_GetId( ISpObjectTokenCategory *iface, | |
| LPWSTR *id ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_GetDataKey( ISpObjectTokenCategory *iface, | |
| SPDATAKEYLOCATION location, | |
| ISpDataKey **data_key ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface, | |
| LPCWSTR req, LPCWSTR opt, | |
| IEnumSpObjectTokens **enum_tokens ) | |
| { | |
| struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); | |
| ISpObjectTokenEnumBuilder *builder; | |
| HRESULT hr; | |
| FIXME( "(%p)->(%s %s %p): semi-stub\n", This, debugstr_w( req ), debugstr_w( opt ), enum_tokens ); | |
| if (!This->data_key) return SPERR_UNINITIALIZED; | |
| hr = CoCreateInstance( &CLSID_SpObjectTokenEnum, NULL, CLSCTX_ALL, | |
| &IID_ISpObjectTokenEnumBuilder, (void **)&builder ); | |
| if (FAILED(hr)) return hr; | |
| hr = ISpObjectTokenEnumBuilder_SetAttribs( builder, req, opt ); | |
| if (FAILED(hr)) goto fail; | |
| /* FIXME: Build the enumerator */ | |
| hr = ISpObjectTokenEnumBuilder_QueryInterface( builder, &IID_IEnumSpObjectTokens, | |
| (void **)enum_tokens ); | |
| fail: | |
| ISpObjectTokenEnumBuilder_Release( builder ); | |
| return hr; | |
| } | |
| static HRESULT WINAPI token_category_SetDefaultTokenId( ISpObjectTokenCategory *iface, | |
| LPCWSTR id ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| static HRESULT WINAPI token_category_GetDefaultTokenId( ISpObjectTokenCategory *iface, | |
| LPWSTR *id ) | |
| { | |
| FIXME( "stub\n" ); | |
| return E_NOTIMPL; | |
| } | |
| const struct ISpObjectTokenCategoryVtbl token_category_vtbl = | |
| { | |
| token_category_QueryInterface, | |
| token_category_AddRef, | |
| token_category_Release, | |
| token_category_SetData, | |
| token_category_GetData, | |
| token_category_SetStringValue, | |
| token_category_GetStringValue, | |
| token_category_SetDWORD, | |
| token_category_GetDWORD, | |
| token_category_OpenKey, | |
| token_category_CreateKey, | |
| token_category_DeleteKey, | |
| token_category_DeleteValue, | |
| token_category_EnumKeys, | |
| token_category_EnumValues, | |
| token_category_SetId, | |
| token_category_GetId, | |
| token_category_GetDataKey, | |
| token_category_EnumTokens, | |
| token_category_SetDefaultTokenId, | |
| token_category_GetDefaultTokenId, | |
| }; | |
| HRESULT token_category_create( IUnknown *outer, REFIID iid, void **obj ) | |
| { | |
| struct token_category *This = heap_alloc( sizeof(*This) ); | |
| HRESULT hr; | |
| if (!This) return E_OUTOFMEMORY; | |
| This->ISpObjectTokenCategory_iface.lpVtbl = &token_category_vtbl; | |
| This->ref = 1; | |
| This->data_key = NULL; | |
| hr = ISpObjectTokenCategory_QueryInterface( &This->ISpObjectTokenCategory_iface, iid, obj ); | |
| ISpObjectTokenCategory_Release( &This->ISpObjectTokenCategory_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 ) | |
| { | |
| struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface ); | |
| TRACE( "(%p)->(%u %p %p)\n", This, num, tokens, fetched ); | |
| if (!This->init) return SPERR_UNINITIALIZED; | |
| FIXME( "semi-stub: Returning an empty enumerator\n" ); | |
| if (fetched) *fetched = 0; | |
| return S_FALSE; | |
| } | |
| 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; | |
| } |