2 * Speech API (SAPI) token implementation.
4 * Copyright (C) 2017 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/debug.h"
33 #include "sapi_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(sapi
);
39 ISpRegDataKey ISpRegDataKey_iface
;
46 static struct data_key
*impl_from_ISpRegDataKey( ISpRegDataKey
*iface
)
48 return CONTAINING_RECORD( iface
, struct data_key
, ISpRegDataKey_iface
);
51 static HRESULT WINAPI
data_key_QueryInterface( ISpRegDataKey
*iface
, REFIID iid
, void **obj
)
53 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
55 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
57 if (IsEqualIID( iid
, &IID_IUnknown
) ||
58 IsEqualIID( iid
, &IID_ISpDataKey
) ||
59 IsEqualIID( iid
, &IID_ISpRegDataKey
))
61 ISpRegDataKey_AddRef( iface
);
66 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
71 static ULONG WINAPI
data_key_AddRef( ISpRegDataKey
*iface
)
73 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
74 ULONG ref
= InterlockedIncrement( &This
->ref
);
76 TRACE( "(%p) ref = %u\n", This
, ref
);
80 static ULONG WINAPI
data_key_Release( ISpRegDataKey
*iface
)
82 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
83 ULONG ref
= InterlockedDecrement(&This
->ref
);
85 TRACE( "(%p) ref = %u\n", This
, ref
);
89 if (This
->key
) RegCloseKey( This
->key
);
96 static HRESULT WINAPI
data_key_SetData( ISpRegDataKey
*iface
, LPCWSTR name
,
97 ULONG size
, const BYTE
*data
)
103 static HRESULT WINAPI
data_key_GetData( ISpRegDataKey
*iface
, LPCWSTR name
,
104 ULONG
*size
, BYTE
*data
)
110 static HRESULT WINAPI
data_key_SetStringValue( ISpRegDataKey
*iface
,
111 LPCWSTR name
, LPCWSTR value
)
117 static HRESULT WINAPI
data_key_GetStringValue( ISpRegDataKey
*iface
,
118 LPCWSTR name
, LPWSTR
*value
)
124 static HRESULT WINAPI
data_key_SetDWORD( ISpRegDataKey
*iface
,
125 LPCWSTR name
, DWORD value
)
131 static HRESULT WINAPI
data_key_GetDWORD( ISpRegDataKey
*iface
,
132 LPCWSTR name
, DWORD
*pdwValue
)
138 static HRESULT WINAPI
data_key_OpenKey( ISpRegDataKey
*iface
,
139 LPCWSTR name
, ISpDataKey
**sub_key
)
145 static HRESULT WINAPI
data_key_CreateKey( ISpRegDataKey
*iface
,
146 LPCWSTR name
, ISpDataKey
**sub_key
)
152 static HRESULT WINAPI
data_key_DeleteKey( ISpRegDataKey
*iface
, LPCWSTR name
)
158 static HRESULT WINAPI
data_key_DeleteValue( ISpRegDataKey
*iface
, LPCWSTR name
)
164 static HRESULT WINAPI
data_key_EnumKeys( ISpRegDataKey
*iface
,
165 ULONG index
, LPWSTR
*sub_key
)
171 static HRESULT WINAPI
data_key_EnumValues( ISpRegDataKey
*iface
,
172 ULONG index
, LPWSTR
*value
)
178 static HRESULT WINAPI
data_key_SetKey( ISpRegDataKey
*iface
,
179 HKEY key
, BOOL read_only
)
181 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
183 TRACE( "(%p)->(%p %d)\n", This
, key
, read_only
);
185 if (This
->key
) return SPERR_ALREADY_INITIALIZED
;
188 This
->read_only
= read_only
;
192 const struct ISpRegDataKeyVtbl data_key_vtbl
=
194 data_key_QueryInterface
,
199 data_key_SetStringValue
,
200 data_key_GetStringValue
,
206 data_key_DeleteValue
,
212 HRESULT
data_key_create( IUnknown
*outer
, REFIID iid
, void **obj
)
214 struct data_key
*This
= heap_alloc( sizeof(*This
) );
217 if (!This
) return E_OUTOFMEMORY
;
218 This
->ISpRegDataKey_iface
.lpVtbl
= &data_key_vtbl
;
221 This
->read_only
= FALSE
;
223 hr
= ISpRegDataKey_QueryInterface( &This
->ISpRegDataKey_iface
, iid
, obj
);
225 ISpRegDataKey_Release( &This
->ISpRegDataKey_iface
);
229 struct token_category
231 ISpObjectTokenCategory ISpObjectTokenCategory_iface
;
234 ISpRegDataKey
*data_key
;
237 static struct token_category
*impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory
*iface
)
239 return CONTAINING_RECORD( iface
, struct token_category
, ISpObjectTokenCategory_iface
);
242 static HRESULT WINAPI
token_category_QueryInterface( ISpObjectTokenCategory
*iface
,
243 REFIID iid
, void **obj
)
245 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
247 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
249 if (IsEqualIID( iid
, &IID_IUnknown
) ||
250 IsEqualIID( iid
, &IID_ISpDataKey
) ||
251 IsEqualIID( iid
, &IID_ISpObjectTokenCategory
))
253 ISpObjectTokenCategory_AddRef( iface
);
258 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
260 return E_NOINTERFACE
;
263 static ULONG WINAPI
token_category_AddRef( ISpObjectTokenCategory
*iface
)
265 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
266 ULONG ref
= InterlockedIncrement( &This
->ref
);
268 TRACE( "(%p) ref = %u\n", This
, ref
);
272 static ULONG WINAPI
token_category_Release( ISpObjectTokenCategory
*iface
)
274 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
275 ULONG ref
= InterlockedDecrement(&This
->ref
);
277 TRACE( "(%p) ref = %u\n", This
, ref
);
281 if (This
->data_key
) ISpRegDataKey_Release( This
->data_key
);
287 static HRESULT WINAPI
token_category_SetData( ISpObjectTokenCategory
*iface
,
288 LPCWSTR name
, ULONG size
,
295 static HRESULT WINAPI
token_category_GetData( ISpObjectTokenCategory
*iface
,
296 LPCWSTR name
, ULONG
*size
,
303 static HRESULT WINAPI
token_category_SetStringValue( ISpObjectTokenCategory
*iface
,
304 LPCWSTR name
, LPCWSTR value
)
310 static HRESULT WINAPI
token_category_GetStringValue( ISpObjectTokenCategory
*iface
,
311 LPCWSTR name
, LPWSTR
*value
)
317 static HRESULT WINAPI
token_category_SetDWORD( ISpObjectTokenCategory
*iface
,
318 LPCWSTR name
, DWORD value
)
324 static HRESULT WINAPI
token_category_GetDWORD( ISpObjectTokenCategory
*iface
,
325 LPCWSTR name
, DWORD
*pdwValue
)
331 static HRESULT WINAPI
token_category_OpenKey( ISpObjectTokenCategory
*iface
,
332 LPCWSTR name
, ISpDataKey
**sub_key
)
338 static HRESULT WINAPI
token_category_CreateKey( ISpObjectTokenCategory
*iface
,
339 LPCWSTR name
, ISpDataKey
**sub_key
)
345 static HRESULT WINAPI
token_category_DeleteKey( ISpObjectTokenCategory
*iface
,
352 static HRESULT WINAPI
token_category_DeleteValue( ISpObjectTokenCategory
*iface
,
359 static HRESULT WINAPI
token_category_EnumKeys( ISpObjectTokenCategory
*iface
,
360 ULONG index
, LPWSTR
*sub_key
)
366 static HRESULT WINAPI
token_category_EnumValues( ISpObjectTokenCategory
*iface
,
367 ULONG index
, LPWSTR
*value
)
373 static HRESULT
parse_cat_id( const WCHAR
*str
, HKEY
*root
, const WCHAR
**sub_key
)
375 static const WCHAR HKLM
[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E','\\'};
376 static const WCHAR HKCU
[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\'};
384 { HKLM
, sizeof(HKLM
), HKEY_LOCAL_MACHINE
},
385 { HKCU
, sizeof(HKCU
), HKEY_CURRENT_USER
},
389 int len
= lstrlenW( str
);
391 for (ptr
= table
; ptr
->name
; ptr
++)
393 if (len
>= ptr
->size
/ sizeof(ptr
->name
[0]) && !memcmp( str
, ptr
->name
, ptr
->size
))
396 *sub_key
= str
+ ptr
->size
/ sizeof(ptr
->name
[0]);
403 static HRESULT WINAPI
token_category_SetId( ISpObjectTokenCategory
*iface
,
404 LPCWSTR id
, BOOL create
)
406 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
412 TRACE( "(%p)->(%s %d)\n", This
, debugstr_w( id
), create
);
414 if (This
->data_key
) return SPERR_ALREADY_INITIALIZED
;
416 hr
= parse_cat_id( id
, &root
, &subkey
);
417 if (hr
!= S_OK
) return SPERR_INVALID_REGISTRY_KEY
;
419 if (create
) FIXME( "Ignoring create\n" );
421 res
= RegOpenKeyExW( root
, subkey
, 0, KEY_ALL_ACCESS
, &key
);
422 if (res
) return SPERR_INVALID_REGISTRY_KEY
;
424 hr
= CoCreateInstance( &CLSID_SpDataKey
, NULL
, CLSCTX_ALL
,
425 &IID_ISpRegDataKey
, (void **)&This
->data_key
);
426 if (FAILED(hr
)) goto fail
;
428 hr
= ISpRegDataKey_SetKey( This
->data_key
, key
, FALSE
);
429 if (FAILED(hr
)) goto fail
;
438 static HRESULT WINAPI
token_category_GetId( ISpObjectTokenCategory
*iface
,
445 static HRESULT WINAPI
token_category_GetDataKey( ISpObjectTokenCategory
*iface
,
446 SPDATAKEYLOCATION location
,
447 ISpDataKey
**data_key
)
453 static HRESULT WINAPI
token_category_EnumTokens( ISpObjectTokenCategory
*iface
,
454 LPCWSTR req
, LPCWSTR opt
,
455 IEnumSpObjectTokens
**enum_tokens
)
457 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
458 ISpObjectTokenEnumBuilder
*builder
;
461 FIXME( "(%p)->(%s %s %p): semi-stub\n", This
, debugstr_w( req
), debugstr_w( opt
), enum_tokens
);
463 if (!This
->data_key
) return SPERR_UNINITIALIZED
;
465 hr
= CoCreateInstance( &CLSID_SpObjectTokenEnum
, NULL
, CLSCTX_ALL
,
466 &IID_ISpObjectTokenEnumBuilder
, (void **)&builder
);
467 if (FAILED(hr
)) return hr
;
469 hr
= ISpObjectTokenEnumBuilder_SetAttribs( builder
, req
, opt
);
470 if (FAILED(hr
)) goto fail
;
472 /* FIXME: Build the enumerator */
474 hr
= ISpObjectTokenEnumBuilder_QueryInterface( builder
, &IID_IEnumSpObjectTokens
,
475 (void **)enum_tokens
);
478 ISpObjectTokenEnumBuilder_Release( builder
);
482 static HRESULT WINAPI
token_category_SetDefaultTokenId( ISpObjectTokenCategory
*iface
,
489 static HRESULT WINAPI
token_category_GetDefaultTokenId( ISpObjectTokenCategory
*iface
,
496 const struct ISpObjectTokenCategoryVtbl token_category_vtbl
=
498 token_category_QueryInterface
,
499 token_category_AddRef
,
500 token_category_Release
,
501 token_category_SetData
,
502 token_category_GetData
,
503 token_category_SetStringValue
,
504 token_category_GetStringValue
,
505 token_category_SetDWORD
,
506 token_category_GetDWORD
,
507 token_category_OpenKey
,
508 token_category_CreateKey
,
509 token_category_DeleteKey
,
510 token_category_DeleteValue
,
511 token_category_EnumKeys
,
512 token_category_EnumValues
,
513 token_category_SetId
,
514 token_category_GetId
,
515 token_category_GetDataKey
,
516 token_category_EnumTokens
,
517 token_category_SetDefaultTokenId
,
518 token_category_GetDefaultTokenId
,
521 HRESULT
token_category_create( IUnknown
*outer
, REFIID iid
, void **obj
)
523 struct token_category
*This
= heap_alloc( sizeof(*This
) );
526 if (!This
) return E_OUTOFMEMORY
;
527 This
->ISpObjectTokenCategory_iface
.lpVtbl
= &token_category_vtbl
;
529 This
->data_key
= NULL
;
531 hr
= ISpObjectTokenCategory_QueryInterface( &This
->ISpObjectTokenCategory_iface
, iid
, obj
);
533 ISpObjectTokenCategory_Release( &This
->ISpObjectTokenCategory_iface
);
539 ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface
;
547 static struct token_enum
*impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder
*iface
)
549 return CONTAINING_RECORD( iface
, struct token_enum
, ISpObjectTokenEnumBuilder_iface
);
552 static HRESULT WINAPI
token_enum_QueryInterface( ISpObjectTokenEnumBuilder
*iface
,
553 REFIID iid
, void **obj
)
555 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
557 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
559 if (IsEqualIID( iid
, &IID_IUnknown
) ||
560 IsEqualIID( iid
, &IID_IEnumSpObjectTokens
) ||
561 IsEqualIID( iid
, &IID_ISpObjectTokenEnumBuilder
))
563 ISpObjectTokenEnumBuilder_AddRef( iface
);
568 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
570 return E_NOINTERFACE
;
573 static ULONG WINAPI
token_enum_AddRef( ISpObjectTokenEnumBuilder
*iface
)
575 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
576 ULONG ref
= InterlockedIncrement( &This
->ref
);
578 TRACE( "(%p) ref = %u\n", This
, ref
);
582 static ULONG WINAPI
token_enum_Release( ISpObjectTokenEnumBuilder
*iface
)
584 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
585 ULONG ref
= InterlockedDecrement(&This
->ref
);
587 TRACE( "(%p) ref = %u\n", This
, ref
);
591 heap_free( This
->req
);
592 heap_free( This
->opt
);
599 static HRESULT WINAPI
token_enum_Next( ISpObjectTokenEnumBuilder
*iface
,
600 ULONG num
, ISpObjectToken
**tokens
,
603 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
605 TRACE( "(%p)->(%u %p %p)\n", This
, num
, tokens
, fetched
);
607 if (!This
->init
) return SPERR_UNINITIALIZED
;
609 FIXME( "semi-stub: Returning an empty enumerator\n" );
611 if (fetched
) *fetched
= 0;
615 static HRESULT WINAPI
token_enum_Skip( ISpObjectTokenEnumBuilder
*iface
,
622 static HRESULT WINAPI
token_enum_Reset( ISpObjectTokenEnumBuilder
*iface
)
628 static HRESULT WINAPI
token_enum_Clone( ISpObjectTokenEnumBuilder
*iface
,
629 IEnumSpObjectTokens
**clone
)
635 static HRESULT WINAPI
token_enum_Item( ISpObjectTokenEnumBuilder
*iface
,
636 ULONG index
, ISpObjectToken
**token
)
642 static HRESULT WINAPI
token_enum_GetCount( ISpObjectTokenEnumBuilder
*iface
,
645 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
647 TRACE( "(%p)->(%p)\n", This
, count
);
649 if (!This
->init
) return SPERR_UNINITIALIZED
;
651 *count
= This
->count
;
655 static HRESULT WINAPI
token_enum_SetAttribs( ISpObjectTokenEnumBuilder
*iface
,
656 LPCWSTR req
, LPCWSTR opt
)
658 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
660 TRACE( "(%p)->(%s %s)\n", This
, debugstr_w( req
), debugstr_w( opt
) );
662 if (This
->init
) return SPERR_ALREADY_INITIALIZED
;
666 This
->req
= heap_strdupW( req
);
667 if (!This
->req
) goto out_of_mem
;
672 This
->opt
= heap_strdupW( opt
);
673 if (!This
->opt
) goto out_of_mem
;
680 heap_free( This
->req
);
681 return E_OUTOFMEMORY
;
684 static HRESULT WINAPI
token_enum_AddTokens( ISpObjectTokenEnumBuilder
*iface
,
685 ULONG num
, ISpObjectToken
**tokens
)
691 static HRESULT WINAPI
token_enum_AddTokensFromDataKey( ISpObjectTokenEnumBuilder
*iface
,
692 ISpDataKey
*data_key
,
693 LPCWSTR sub_key
, LPCWSTR cat_id
)
699 static HRESULT WINAPI
token_enum_AddTokensFromTokenEnum( ISpObjectTokenEnumBuilder
*iface
,
700 IEnumSpObjectTokens
*token_enum
)
706 static HRESULT WINAPI
token_enum_Sort( ISpObjectTokenEnumBuilder
*iface
,
713 const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl
=
715 token_enum_QueryInterface
,
724 token_enum_SetAttribs
,
725 token_enum_AddTokens
,
726 token_enum_AddTokensFromDataKey
,
727 token_enum_AddTokensFromTokenEnum
,
731 HRESULT
token_enum_create( IUnknown
*outer
, REFIID iid
, void **obj
)
733 struct token_enum
*This
= heap_alloc( sizeof(*This
) );
736 if (!This
) return E_OUTOFMEMORY
;
737 This
->ISpObjectTokenEnumBuilder_iface
.lpVtbl
= &token_enum_vtbl
;
744 hr
= ISpObjectTokenEnumBuilder_QueryInterface( &This
->ISpObjectTokenEnumBuilder_iface
, iid
, obj
);
746 ISpObjectTokenEnumBuilder_Release( &This
->ISpObjectTokenEnumBuilder_iface
);