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
32 #include "wine/debug.h"
34 #include "sapi_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(sapi
);
40 ISpRegDataKey ISpRegDataKey_iface
;
47 static struct data_key
*impl_from_ISpRegDataKey( ISpRegDataKey
*iface
)
49 return CONTAINING_RECORD( iface
, struct data_key
, ISpRegDataKey_iface
);
52 static HRESULT WINAPI
data_key_QueryInterface( ISpRegDataKey
*iface
, REFIID iid
, void **obj
)
54 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
56 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
58 if (IsEqualIID( iid
, &IID_IUnknown
) ||
59 IsEqualIID( iid
, &IID_ISpDataKey
) ||
60 IsEqualIID( iid
, &IID_ISpRegDataKey
))
62 ISpRegDataKey_AddRef( iface
);
67 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
72 static ULONG WINAPI
data_key_AddRef( ISpRegDataKey
*iface
)
74 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
75 ULONG ref
= InterlockedIncrement( &This
->ref
);
77 TRACE( "(%p) ref = %u\n", This
, ref
);
81 static ULONG WINAPI
data_key_Release( ISpRegDataKey
*iface
)
83 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
84 ULONG ref
= InterlockedDecrement(&This
->ref
);
86 TRACE( "(%p) ref = %u\n", This
, ref
);
90 if (This
->key
) RegCloseKey( This
->key
);
97 static HRESULT WINAPI
data_key_SetData( ISpRegDataKey
*iface
, LPCWSTR name
,
98 ULONG size
, const BYTE
*data
)
104 static HRESULT WINAPI
data_key_GetData( ISpRegDataKey
*iface
, LPCWSTR name
,
105 ULONG
*size
, BYTE
*data
)
111 static HRESULT WINAPI
data_key_SetStringValue( ISpRegDataKey
*iface
,
112 LPCWSTR name
, LPCWSTR value
)
118 static HRESULT WINAPI
data_key_GetStringValue( ISpRegDataKey
*iface
,
119 LPCWSTR name
, LPWSTR
*value
)
125 static HRESULT WINAPI
data_key_SetDWORD( ISpRegDataKey
*iface
,
126 LPCWSTR name
, DWORD value
)
132 static HRESULT WINAPI
data_key_GetDWORD( ISpRegDataKey
*iface
,
133 LPCWSTR name
, DWORD
*pdwValue
)
139 static HRESULT WINAPI
data_key_OpenKey( ISpRegDataKey
*iface
,
140 LPCWSTR name
, ISpDataKey
**sub_key
)
146 static HRESULT WINAPI
data_key_CreateKey( ISpRegDataKey
*iface
,
147 LPCWSTR name
, ISpDataKey
**sub_key
)
153 static HRESULT WINAPI
data_key_DeleteKey( ISpRegDataKey
*iface
, LPCWSTR name
)
159 static HRESULT WINAPI
data_key_DeleteValue( ISpRegDataKey
*iface
, LPCWSTR name
)
165 static HRESULT WINAPI
data_key_EnumKeys( ISpRegDataKey
*iface
,
166 ULONG index
, LPWSTR
*sub_key
)
172 static HRESULT WINAPI
data_key_EnumValues( ISpRegDataKey
*iface
,
173 ULONG index
, LPWSTR
*value
)
179 static HRESULT WINAPI
data_key_SetKey( ISpRegDataKey
*iface
,
180 HKEY key
, BOOL read_only
)
182 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
184 TRACE( "(%p)->(%p %d)\n", This
, key
, read_only
);
186 if (This
->key
) return SPERR_ALREADY_INITIALIZED
;
189 This
->read_only
= read_only
;
193 const struct ISpRegDataKeyVtbl data_key_vtbl
=
195 data_key_QueryInterface
,
200 data_key_SetStringValue
,
201 data_key_GetStringValue
,
207 data_key_DeleteValue
,
213 HRESULT
data_key_create( IUnknown
*outer
, REFIID iid
, void **obj
)
215 struct data_key
*This
= heap_alloc( sizeof(*This
) );
218 if (!This
) return E_OUTOFMEMORY
;
219 This
->ISpRegDataKey_iface
.lpVtbl
= &data_key_vtbl
;
222 This
->read_only
= FALSE
;
224 hr
= ISpRegDataKey_QueryInterface( &This
->ISpRegDataKey_iface
, iid
, obj
);
226 ISpRegDataKey_Release( &This
->ISpRegDataKey_iface
);
230 struct token_category
232 ISpObjectTokenCategory ISpObjectTokenCategory_iface
;
235 ISpRegDataKey
*data_key
;
238 static struct token_category
*impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory
*iface
)
240 return CONTAINING_RECORD( iface
, struct token_category
, ISpObjectTokenCategory_iface
);
243 static HRESULT WINAPI
token_category_QueryInterface( ISpObjectTokenCategory
*iface
,
244 REFIID iid
, void **obj
)
246 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
248 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
250 if (IsEqualIID( iid
, &IID_IUnknown
) ||
251 IsEqualIID( iid
, &IID_ISpDataKey
) ||
252 IsEqualIID( iid
, &IID_ISpObjectTokenCategory
))
254 ISpObjectTokenCategory_AddRef( iface
);
259 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
261 return E_NOINTERFACE
;
264 static ULONG WINAPI
token_category_AddRef( ISpObjectTokenCategory
*iface
)
266 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
267 ULONG ref
= InterlockedIncrement( &This
->ref
);
269 TRACE( "(%p) ref = %u\n", This
, ref
);
273 static ULONG WINAPI
token_category_Release( ISpObjectTokenCategory
*iface
)
275 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
276 ULONG ref
= InterlockedDecrement(&This
->ref
);
278 TRACE( "(%p) ref = %u\n", This
, ref
);
282 if (This
->data_key
) ISpRegDataKey_Release( This
->data_key
);
288 static HRESULT WINAPI
token_category_SetData( ISpObjectTokenCategory
*iface
,
289 LPCWSTR name
, ULONG size
,
296 static HRESULT WINAPI
token_category_GetData( ISpObjectTokenCategory
*iface
,
297 LPCWSTR name
, ULONG
*size
,
304 static HRESULT WINAPI
token_category_SetStringValue( ISpObjectTokenCategory
*iface
,
305 LPCWSTR name
, LPCWSTR value
)
311 static HRESULT WINAPI
token_category_GetStringValue( ISpObjectTokenCategory
*iface
,
312 LPCWSTR name
, LPWSTR
*value
)
318 static HRESULT WINAPI
token_category_SetDWORD( ISpObjectTokenCategory
*iface
,
319 LPCWSTR name
, DWORD value
)
325 static HRESULT WINAPI
token_category_GetDWORD( ISpObjectTokenCategory
*iface
,
326 LPCWSTR name
, DWORD
*pdwValue
)
332 static HRESULT WINAPI
token_category_OpenKey( ISpObjectTokenCategory
*iface
,
333 LPCWSTR name
, ISpDataKey
**sub_key
)
339 static HRESULT WINAPI
token_category_CreateKey( ISpObjectTokenCategory
*iface
,
340 LPCWSTR name
, ISpDataKey
**sub_key
)
346 static HRESULT WINAPI
token_category_DeleteKey( ISpObjectTokenCategory
*iface
,
353 static HRESULT WINAPI
token_category_DeleteValue( ISpObjectTokenCategory
*iface
,
360 static HRESULT WINAPI
token_category_EnumKeys( ISpObjectTokenCategory
*iface
,
361 ULONG index
, LPWSTR
*sub_key
)
367 static HRESULT WINAPI
token_category_EnumValues( ISpObjectTokenCategory
*iface
,
368 ULONG index
, LPWSTR
*value
)
374 static HRESULT
parse_cat_id( const WCHAR
*str
, HKEY
*root
, const WCHAR
**sub_key
)
376 static const WCHAR HKLM
[] = {'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E','\\'};
377 static const WCHAR HKCU
[] = {'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\'};
385 { HKLM
, sizeof(HKLM
), HKEY_LOCAL_MACHINE
},
386 { HKCU
, sizeof(HKCU
), HKEY_CURRENT_USER
},
390 int len
= strlenW( str
);
392 for (ptr
= table
; ptr
->name
; ptr
++)
394 if (len
>= ptr
->size
/ sizeof(ptr
->name
[0]) && !memcmp( str
, ptr
->name
, ptr
->size
))
397 *sub_key
= str
+ ptr
->size
/ sizeof(ptr
->name
[0]);
404 static HRESULT WINAPI
token_category_SetId( ISpObjectTokenCategory
*iface
,
405 LPCWSTR id
, BOOL create
)
407 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
413 TRACE( "(%p)->(%s %d)\n", This
, debugstr_w( id
), create
);
415 if (This
->data_key
) return SPERR_ALREADY_INITIALIZED
;
417 hr
= parse_cat_id( id
, &root
, &subkey
);
418 if (hr
!= S_OK
) return SPERR_INVALID_REGISTRY_KEY
;
420 if (create
) FIXME( "Ignoring create\n" );
422 res
= RegOpenKeyExW( root
, subkey
, 0, KEY_ALL_ACCESS
, &key
);
423 if (res
) return SPERR_INVALID_REGISTRY_KEY
;
425 hr
= CoCreateInstance( &CLSID_SpDataKey
, NULL
, CLSCTX_ALL
,
426 &IID_ISpRegDataKey
, (void **)&This
->data_key
);
427 if (FAILED(hr
)) goto fail
;
429 hr
= ISpRegDataKey_SetKey( This
->data_key
, key
, FALSE
);
430 if (FAILED(hr
)) goto fail
;
439 static HRESULT WINAPI
token_category_GetId( ISpObjectTokenCategory
*iface
,
446 static HRESULT WINAPI
token_category_GetDataKey( ISpObjectTokenCategory
*iface
,
447 SPDATAKEYLOCATION location
,
448 ISpDataKey
**data_key
)
454 static HRESULT WINAPI
token_category_EnumTokens( ISpObjectTokenCategory
*iface
,
455 LPCWSTR req
, LPCWSTR opt
,
456 IEnumSpObjectTokens
**enum_tokens
)
458 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
459 ISpObjectTokenEnumBuilder
*builder
;
462 FIXME( "(%p)->(%s %s %p): semi-stub\n", This
, debugstr_w( req
), debugstr_w( opt
), enum_tokens
);
464 if (!This
->data_key
) return SPERR_UNINITIALIZED
;
466 hr
= CoCreateInstance( &CLSID_SpObjectTokenEnum
, NULL
, CLSCTX_ALL
,
467 &IID_ISpObjectTokenEnumBuilder
, (void **)&builder
);
468 if (FAILED(hr
)) return hr
;
470 hr
= ISpObjectTokenEnumBuilder_SetAttribs( builder
, req
, opt
);
471 if (FAILED(hr
)) goto fail
;
473 /* FIXME: Build the enumerator */
475 hr
= ISpObjectTokenEnumBuilder_QueryInterface( builder
, &IID_IEnumSpObjectTokens
,
476 (void **)enum_tokens
);
479 ISpObjectTokenEnumBuilder_Release( builder
);
483 static HRESULT WINAPI
token_category_SetDefaultTokenId( ISpObjectTokenCategory
*iface
,
490 static HRESULT WINAPI
token_category_GetDefaultTokenId( ISpObjectTokenCategory
*iface
,
497 const struct ISpObjectTokenCategoryVtbl token_category_vtbl
=
499 token_category_QueryInterface
,
500 token_category_AddRef
,
501 token_category_Release
,
502 token_category_SetData
,
503 token_category_GetData
,
504 token_category_SetStringValue
,
505 token_category_GetStringValue
,
506 token_category_SetDWORD
,
507 token_category_GetDWORD
,
508 token_category_OpenKey
,
509 token_category_CreateKey
,
510 token_category_DeleteKey
,
511 token_category_DeleteValue
,
512 token_category_EnumKeys
,
513 token_category_EnumValues
,
514 token_category_SetId
,
515 token_category_GetId
,
516 token_category_GetDataKey
,
517 token_category_EnumTokens
,
518 token_category_SetDefaultTokenId
,
519 token_category_GetDefaultTokenId
,
522 HRESULT
token_category_create( IUnknown
*outer
, REFIID iid
, void **obj
)
524 struct token_category
*This
= heap_alloc( sizeof(*This
) );
527 if (!This
) return E_OUTOFMEMORY
;
528 This
->ISpObjectTokenCategory_iface
.lpVtbl
= &token_category_vtbl
;
530 This
->data_key
= NULL
;
532 hr
= ISpObjectTokenCategory_QueryInterface( &This
->ISpObjectTokenCategory_iface
, iid
, obj
);
534 ISpObjectTokenCategory_Release( &This
->ISpObjectTokenCategory_iface
);
540 ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface
;
548 static struct token_enum
*impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder
*iface
)
550 return CONTAINING_RECORD( iface
, struct token_enum
, ISpObjectTokenEnumBuilder_iface
);
553 static HRESULT WINAPI
token_enum_QueryInterface( ISpObjectTokenEnumBuilder
*iface
,
554 REFIID iid
, void **obj
)
556 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
558 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
560 if (IsEqualIID( iid
, &IID_IUnknown
) ||
561 IsEqualIID( iid
, &IID_IEnumSpObjectTokens
) ||
562 IsEqualIID( iid
, &IID_ISpObjectTokenEnumBuilder
))
564 ISpObjectTokenEnumBuilder_AddRef( iface
);
569 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
571 return E_NOINTERFACE
;
574 static ULONG WINAPI
token_enum_AddRef( ISpObjectTokenEnumBuilder
*iface
)
576 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
577 ULONG ref
= InterlockedIncrement( &This
->ref
);
579 TRACE( "(%p) ref = %u\n", This
, ref
);
583 static ULONG WINAPI
token_enum_Release( ISpObjectTokenEnumBuilder
*iface
)
585 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
586 ULONG ref
= InterlockedDecrement(&This
->ref
);
588 TRACE( "(%p) ref = %u\n", This
, ref
);
592 heap_free( This
->req
);
593 heap_free( This
->opt
);
600 static HRESULT WINAPI
token_enum_Next( ISpObjectTokenEnumBuilder
*iface
,
601 ULONG num
, ISpObjectToken
**tokens
,
604 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
606 TRACE( "(%p)->(%u %p %p)\n", This
, num
, tokens
, fetched
);
608 if (!This
->init
) return SPERR_UNINITIALIZED
;
610 FIXME( "semi-stub: Returning an empty enumerator\n" );
612 if (fetched
) *fetched
= 0;
616 static HRESULT WINAPI
token_enum_Skip( ISpObjectTokenEnumBuilder
*iface
,
623 static HRESULT WINAPI
token_enum_Reset( ISpObjectTokenEnumBuilder
*iface
)
629 static HRESULT WINAPI
token_enum_Clone( ISpObjectTokenEnumBuilder
*iface
,
630 IEnumSpObjectTokens
**clone
)
636 static HRESULT WINAPI
token_enum_Item( ISpObjectTokenEnumBuilder
*iface
,
637 ULONG index
, ISpObjectToken
**token
)
643 static HRESULT WINAPI
token_enum_GetCount( ISpObjectTokenEnumBuilder
*iface
,
646 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
648 TRACE( "(%p)->(%p)\n", This
, count
);
650 if (!This
->init
) return SPERR_UNINITIALIZED
;
652 *count
= This
->count
;
656 static HRESULT WINAPI
token_enum_SetAttribs( ISpObjectTokenEnumBuilder
*iface
,
657 LPCWSTR req
, LPCWSTR opt
)
659 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
661 TRACE( "(%p)->(%s %s)\n", This
, debugstr_w( req
), debugstr_w( opt
) );
663 if (This
->init
) return SPERR_ALREADY_INITIALIZED
;
667 This
->req
= heap_strdupW( req
);
668 if (!This
->req
) goto out_of_mem
;
673 This
->opt
= heap_strdupW( opt
);
674 if (!This
->opt
) goto out_of_mem
;
681 heap_free( This
->req
);
682 return E_OUTOFMEMORY
;
685 static HRESULT WINAPI
token_enum_AddTokens( ISpObjectTokenEnumBuilder
*iface
,
686 ULONG num
, ISpObjectToken
**tokens
)
692 static HRESULT WINAPI
token_enum_AddTokensFromDataKey( ISpObjectTokenEnumBuilder
*iface
,
693 ISpDataKey
*data_key
,
694 LPCWSTR sub_key
, LPCWSTR cat_id
)
700 static HRESULT WINAPI
token_enum_AddTokensFromTokenEnum( ISpObjectTokenEnumBuilder
*iface
,
701 IEnumSpObjectTokens
*token_enum
)
707 static HRESULT WINAPI
token_enum_Sort( ISpObjectTokenEnumBuilder
*iface
,
714 const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl
=
716 token_enum_QueryInterface
,
725 token_enum_SetAttribs
,
726 token_enum_AddTokens
,
727 token_enum_AddTokensFromDataKey
,
728 token_enum_AddTokensFromTokenEnum
,
732 HRESULT
token_enum_create( IUnknown
*outer
, REFIID iid
, void **obj
)
734 struct token_enum
*This
= heap_alloc( sizeof(*This
) );
737 if (!This
) return E_OUTOFMEMORY
;
738 This
->ISpObjectTokenEnumBuilder_iface
.lpVtbl
= &token_enum_vtbl
;
745 hr
= ISpObjectTokenEnumBuilder_QueryInterface( &This
->ISpObjectTokenEnumBuilder_iface
, iid
, obj
);
747 ISpObjectTokenEnumBuilder_Release( &This
->ISpObjectTokenEnumBuilder_iface
);