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
;
45 static struct data_key
*impl_from_ISpRegDataKey( ISpRegDataKey
*iface
)
47 return CONTAINING_RECORD( iface
, struct data_key
, ISpRegDataKey_iface
);
52 ISpObjectToken ISpObjectToken_iface
;
55 ISpRegDataKey
*data_key
;
59 static struct object_token
*impl_from_ISpObjectToken( ISpObjectToken
*iface
)
61 return CONTAINING_RECORD( iface
, struct object_token
, ISpObjectToken_iface
);
64 static HRESULT WINAPI
data_key_QueryInterface( ISpRegDataKey
*iface
, REFIID iid
, void **obj
)
66 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
68 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
70 if (IsEqualIID( iid
, &IID_IUnknown
) ||
71 IsEqualIID( iid
, &IID_ISpDataKey
) ||
72 IsEqualIID( iid
, &IID_ISpRegDataKey
))
74 ISpRegDataKey_AddRef( iface
);
79 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
84 static ULONG WINAPI
data_key_AddRef( ISpRegDataKey
*iface
)
86 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
87 ULONG ref
= InterlockedIncrement( &This
->ref
);
89 TRACE( "(%p) ref = %lu\n", This
, ref
);
93 static ULONG WINAPI
data_key_Release( ISpRegDataKey
*iface
)
95 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
96 ULONG ref
= InterlockedDecrement(&This
->ref
);
98 TRACE( "(%p) ref = %lu\n", This
, ref
);
102 if (This
->key
) RegCloseKey( This
->key
);
109 static HRESULT WINAPI
data_key_SetData( ISpRegDataKey
*iface
, LPCWSTR name
,
110 ULONG size
, const BYTE
*data
)
116 static HRESULT WINAPI
data_key_GetData( ISpRegDataKey
*iface
, LPCWSTR name
,
117 ULONG
*size
, BYTE
*data
)
123 static HRESULT WINAPI
data_key_SetStringValue( ISpRegDataKey
*iface
,
124 LPCWSTR name
, LPCWSTR value
)
126 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
129 TRACE( "%p, %s, %s\n", This
, debugstr_w(name
), debugstr_w(value
) );
134 size
= (wcslen(value
) + 1) * sizeof(WCHAR
);
135 ret
= RegSetValueExW( This
->key
, name
, 0, REG_SZ
, (BYTE
*)value
, size
);
137 return HRESULT_FROM_WIN32(ret
);
140 static HRESULT WINAPI
data_key_GetStringValue( ISpRegDataKey
*iface
,
141 LPCWSTR name
, LPWSTR
*value
)
143 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
147 TRACE( "%p, %s, %p\n", This
, debugstr_w(name
), value
);
153 ret
= RegGetValueW( This
->key
, NULL
, name
, RRF_RT_REG_SZ
, NULL
, NULL
, &size
);
154 if (ret
!= ERROR_SUCCESS
)
155 return SPERR_NOT_FOUND
;
157 content
= CoTaskMemAlloc(size
);
159 return E_OUTOFMEMORY
;
161 ret
= RegGetValueW( This
->key
, NULL
, name
, RRF_RT_REG_SZ
, NULL
, content
, &size
);
162 if (ret
!= ERROR_SUCCESS
)
164 CoTaskMemFree(content
);
165 return HRESULT_FROM_WIN32(ret
);
172 static HRESULT WINAPI
data_key_SetDWORD( ISpRegDataKey
*iface
,
173 LPCWSTR name
, DWORD value
)
179 static HRESULT WINAPI
data_key_GetDWORD( ISpRegDataKey
*iface
,
180 LPCWSTR name
, DWORD
*pdwValue
)
186 static HRESULT WINAPI
data_key_OpenKey( ISpRegDataKey
*iface
,
187 LPCWSTR name
, ISpDataKey
**sub_key
)
189 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
190 ISpRegDataKey
*spregkey
;
195 TRACE( "%p, %s, %p\n", This
, debugstr_w(name
), sub_key
);
197 ret
= RegOpenKeyExW( This
->key
, name
, 0, KEY_ALL_ACCESS
, &key
);
198 if (ret
!= ERROR_SUCCESS
)
199 return SPERR_NOT_FOUND
;
201 hr
= data_key_create( NULL
, &IID_ISpRegDataKey
, (void**)&spregkey
);
208 hr
= ISpRegDataKey_SetKey( spregkey
, key
, FALSE
);
212 ISpRegDataKey_Release( spregkey
);
216 hr
= ISpRegDataKey_QueryInterface( spregkey
, &IID_ISpDataKey
, (void**)sub_key
);
217 ISpRegDataKey_Release( spregkey
);
222 static HRESULT WINAPI
data_key_CreateKey( ISpRegDataKey
*iface
,
223 LPCWSTR name
, ISpDataKey
**sub_key
)
225 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
226 ISpRegDataKey
*spregkey
;
231 TRACE( "%p, %s, %p\n", This
, debugstr_w(name
), sub_key
);
233 res
= RegCreateKeyExW( This
->key
, name
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
234 if (res
!= ERROR_SUCCESS
)
235 return HRESULT_FROM_WIN32(res
);
237 hr
= data_key_create(NULL
, &IID_ISpRegDataKey
, (void**)&spregkey
);
240 hr
= ISpRegDataKey_SetKey(spregkey
, key
, FALSE
);
242 hr
= ISpRegDataKey_QueryInterface(spregkey
, &IID_ISpDataKey
, (void**)sub_key
);
243 ISpRegDataKey_Release(spregkey
);
249 static HRESULT WINAPI
data_key_DeleteKey( ISpRegDataKey
*iface
, LPCWSTR name
)
255 static HRESULT WINAPI
data_key_DeleteValue( ISpRegDataKey
*iface
, LPCWSTR name
)
261 static HRESULT WINAPI
data_key_EnumKeys( ISpRegDataKey
*iface
,
262 ULONG index
, LPWSTR
*sub_key
)
268 static HRESULT WINAPI
data_key_EnumValues( ISpRegDataKey
*iface
,
269 ULONG index
, LPWSTR
*value
)
275 static HRESULT WINAPI
data_key_SetKey( ISpRegDataKey
*iface
,
276 HKEY key
, BOOL read_only
)
278 struct data_key
*This
= impl_from_ISpRegDataKey( iface
);
280 TRACE( "(%p)->(%p %d)\n", This
, key
, read_only
);
282 if (This
->key
) return SPERR_ALREADY_INITIALIZED
;
284 /* read_only is ignored in Windows implementations. */
289 const struct ISpRegDataKeyVtbl data_key_vtbl
=
291 data_key_QueryInterface
,
296 data_key_SetStringValue
,
297 data_key_GetStringValue
,
303 data_key_DeleteValue
,
309 HRESULT
data_key_create( IUnknown
*outer
, REFIID iid
, void **obj
)
311 struct data_key
*This
= malloc( sizeof(*This
) );
314 if (!This
) return E_OUTOFMEMORY
;
315 This
->ISpRegDataKey_iface
.lpVtbl
= &data_key_vtbl
;
319 hr
= ISpRegDataKey_QueryInterface( &This
->ISpRegDataKey_iface
, iid
, obj
);
321 ISpRegDataKey_Release( &This
->ISpRegDataKey_iface
);
325 struct token_category
327 ISpObjectTokenCategory ISpObjectTokenCategory_iface
;
330 ISpRegDataKey
*data_key
;
333 static struct token_category
*impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory
*iface
)
335 return CONTAINING_RECORD( iface
, struct token_category
, ISpObjectTokenCategory_iface
);
338 static HRESULT WINAPI
token_category_QueryInterface( ISpObjectTokenCategory
*iface
,
339 REFIID iid
, void **obj
)
341 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
343 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
345 if (IsEqualIID( iid
, &IID_IUnknown
) ||
346 IsEqualIID( iid
, &IID_ISpDataKey
) ||
347 IsEqualIID( iid
, &IID_ISpObjectTokenCategory
))
349 ISpObjectTokenCategory_AddRef( iface
);
354 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
356 return E_NOINTERFACE
;
359 static ULONG WINAPI
token_category_AddRef( ISpObjectTokenCategory
*iface
)
361 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
362 ULONG ref
= InterlockedIncrement( &This
->ref
);
364 TRACE( "(%p) ref = %lu\n", This
, ref
);
368 static ULONG WINAPI
token_category_Release( ISpObjectTokenCategory
*iface
)
370 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
371 ULONG ref
= InterlockedDecrement(&This
->ref
);
373 TRACE( "(%p) ref = %lu\n", This
, ref
);
377 if (This
->data_key
) ISpRegDataKey_Release( This
->data_key
);
383 static HRESULT WINAPI
token_category_SetData( ISpObjectTokenCategory
*iface
,
384 LPCWSTR name
, ULONG size
,
391 static HRESULT WINAPI
token_category_GetData( ISpObjectTokenCategory
*iface
,
392 LPCWSTR name
, ULONG
*size
,
399 static HRESULT WINAPI
token_category_SetStringValue( ISpObjectTokenCategory
*iface
,
400 LPCWSTR name
, LPCWSTR value
)
406 static HRESULT WINAPI
token_category_GetStringValue( ISpObjectTokenCategory
*iface
,
407 LPCWSTR name
, LPWSTR
*value
)
413 static HRESULT WINAPI
token_category_SetDWORD( ISpObjectTokenCategory
*iface
,
414 LPCWSTR name
, DWORD value
)
420 static HRESULT WINAPI
token_category_GetDWORD( ISpObjectTokenCategory
*iface
,
421 LPCWSTR name
, DWORD
*pdwValue
)
427 static HRESULT WINAPI
token_category_OpenKey( ISpObjectTokenCategory
*iface
,
428 LPCWSTR name
, ISpDataKey
**sub_key
)
434 static HRESULT WINAPI
token_category_CreateKey( ISpObjectTokenCategory
*iface
,
435 LPCWSTR name
, ISpDataKey
**sub_key
)
441 static HRESULT WINAPI
token_category_DeleteKey( ISpObjectTokenCategory
*iface
,
448 static HRESULT WINAPI
token_category_DeleteValue( ISpObjectTokenCategory
*iface
,
455 static HRESULT WINAPI
token_category_EnumKeys( ISpObjectTokenCategory
*iface
,
456 ULONG index
, LPWSTR
*sub_key
)
462 static HRESULT WINAPI
token_category_EnumValues( ISpObjectTokenCategory
*iface
,
463 ULONG index
, LPWSTR
*value
)
469 static HRESULT
parse_cat_id( const WCHAR
*str
, HKEY
*root
, const WCHAR
**sub_key
)
478 #define X(s) s, ARRAY_SIZE(s) - 1
479 { X(L
"HKEY_LOCAL_MACHINE\\"), HKEY_LOCAL_MACHINE
},
480 { X(L
"HKEY_CURRENT_USER\\"), HKEY_CURRENT_USER
},
485 int len
= lstrlenW( str
);
487 for (ptr
= table
; ptr
->name
; ptr
++)
489 if (len
>= ptr
->len
&& !wcsncmp( str
, ptr
->name
, ptr
->len
))
492 *sub_key
= str
+ ptr
->len
;
499 static HRESULT WINAPI
create_data_key_with_hkey( HKEY key
, ISpRegDataKey
**data_key
)
503 if (FAILED(hr
= CoCreateInstance( &CLSID_SpDataKey
, NULL
, CLSCTX_INPROC_SERVER
,
504 &IID_ISpRegDataKey
, (void **)data_key
) ))
507 if (FAILED(hr
= ISpRegDataKey_SetKey( *data_key
, key
, TRUE
)))
509 ISpRegDataKey_Release( *data_key
);
516 static HRESULT WINAPI
token_category_SetId( ISpObjectTokenCategory
*iface
,
517 LPCWSTR id
, BOOL create
)
519 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
525 TRACE( "(%p)->(%s %d)\n", This
, debugstr_w( id
), create
);
527 if (This
->data_key
) return SPERR_ALREADY_INITIALIZED
;
529 hr
= parse_cat_id( id
, &root
, &subkey
);
530 if (hr
!= S_OK
) return SPERR_INVALID_REGISTRY_KEY
;
533 res
= RegCreateKeyExW( root
, subkey
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
535 res
= RegOpenKeyExW( root
, subkey
, 0, KEY_ALL_ACCESS
, &key
);
536 if (res
) return SPERR_INVALID_REGISTRY_KEY
;
538 if (FAILED(hr
= create_data_key_with_hkey( key
, &This
->data_key
)))
547 static HRESULT WINAPI
token_category_GetId( ISpObjectTokenCategory
*iface
,
554 static HRESULT WINAPI
token_category_GetDataKey( ISpObjectTokenCategory
*iface
,
555 SPDATAKEYLOCATION location
,
556 ISpDataKey
**data_key
)
564 ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface
;
574 static struct token_enum
*impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder
*iface
)
576 return CONTAINING_RECORD( iface
, struct token_enum
, ISpObjectTokenEnumBuilder_iface
);
579 static HRESULT WINAPI
token_category_EnumTokens( ISpObjectTokenCategory
*iface
,
580 LPCWSTR req
, LPCWSTR opt
,
581 IEnumSpObjectTokens
**enum_tokens
)
583 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
584 ISpObjectTokenEnumBuilder
*builder
;
585 struct token_enum
*tokenenum
;
586 struct data_key
*this_data_key
;
589 TRACE( "(%p)->(%s %s %p)\n", This
, debugstr_w( req
), debugstr_w( opt
), enum_tokens
);
591 if (!This
->data_key
) return SPERR_UNINITIALIZED
;
593 hr
= CoCreateInstance( &CLSID_SpObjectTokenEnum
, NULL
, CLSCTX_ALL
,
594 &IID_ISpObjectTokenEnumBuilder
, (void **)&builder
);
595 if (FAILED(hr
)) return hr
;
597 hr
= ISpObjectTokenEnumBuilder_SetAttribs( builder
, req
, opt
);
598 if (FAILED(hr
)) goto fail
;
600 this_data_key
= impl_from_ISpRegDataKey( This
->data_key
);
602 tokenenum
= impl_from_ISpObjectTokenEnumBuilder( builder
);
604 if (!RegOpenKeyExW( this_data_key
->key
, L
"Tokens", 0, KEY_ALL_ACCESS
, &tokenenum
->key
))
606 RegQueryInfoKeyW(tokenenum
->key
, NULL
, NULL
, NULL
, &tokenenum
->count
, NULL
, NULL
,
607 NULL
, NULL
, NULL
, NULL
, NULL
);
610 hr
= ISpObjectTokenEnumBuilder_QueryInterface( builder
, &IID_IEnumSpObjectTokens
,
611 (void **)enum_tokens
);
614 ISpObjectTokenEnumBuilder_Release( builder
);
618 static HRESULT WINAPI
token_category_SetDefaultTokenId( ISpObjectTokenCategory
*iface
,
625 static HRESULT WINAPI
token_category_GetDefaultTokenId( ISpObjectTokenCategory
*iface
,
628 struct token_category
*This
= impl_from_ISpObjectTokenCategory( iface
);
629 struct data_key
*this_data_key
;
632 DWORD regvalue_size
= sizeof( regvalue
);
634 FIXME( "(%p)->(%p): semi-stub\n", iface
, id
);
637 return SPERR_UNINITIALIZED
;
642 /* todo: check HKCU's DefaultTokenId before */
644 this_data_key
= impl_from_ISpRegDataKey( This
->data_key
);
646 res
= RegGetValueW( this_data_key
->key
, NULL
, L
"DefaultDefaultTokenId", RRF_RT_REG_SZ
,
647 NULL
, ®value
, ®value_size
);
648 if (res
== ERROR_FILE_NOT_FOUND
) {
649 return SPERR_NOT_FOUND
;
650 } else if (res
!= ERROR_SUCCESS
) {
651 /* probably not the correct return value */
652 FIXME( "returning %08lx\n", res
);
656 *id
= CoTaskMemAlloc( regvalue_size
);
657 wcscpy( *id
, regvalue
);
662 const struct ISpObjectTokenCategoryVtbl token_category_vtbl
=
664 token_category_QueryInterface
,
665 token_category_AddRef
,
666 token_category_Release
,
667 token_category_SetData
,
668 token_category_GetData
,
669 token_category_SetStringValue
,
670 token_category_GetStringValue
,
671 token_category_SetDWORD
,
672 token_category_GetDWORD
,
673 token_category_OpenKey
,
674 token_category_CreateKey
,
675 token_category_DeleteKey
,
676 token_category_DeleteValue
,
677 token_category_EnumKeys
,
678 token_category_EnumValues
,
679 token_category_SetId
,
680 token_category_GetId
,
681 token_category_GetDataKey
,
682 token_category_EnumTokens
,
683 token_category_SetDefaultTokenId
,
684 token_category_GetDefaultTokenId
,
687 HRESULT
token_category_create( IUnknown
*outer
, REFIID iid
, void **obj
)
689 struct token_category
*This
= malloc( sizeof(*This
) );
692 if (!This
) return E_OUTOFMEMORY
;
693 This
->ISpObjectTokenCategory_iface
.lpVtbl
= &token_category_vtbl
;
695 This
->data_key
= NULL
;
697 hr
= ISpObjectTokenCategory_QueryInterface( &This
->ISpObjectTokenCategory_iface
, iid
, obj
);
699 ISpObjectTokenCategory_Release( &This
->ISpObjectTokenCategory_iface
);
703 static HRESULT WINAPI
token_enum_QueryInterface( ISpObjectTokenEnumBuilder
*iface
,
704 REFIID iid
, void **obj
)
706 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
708 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
710 if (IsEqualIID( iid
, &IID_IUnknown
) ||
711 IsEqualIID( iid
, &IID_IEnumSpObjectTokens
) ||
712 IsEqualIID( iid
, &IID_ISpObjectTokenEnumBuilder
))
714 ISpObjectTokenEnumBuilder_AddRef( iface
);
719 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
721 return E_NOINTERFACE
;
724 static ULONG WINAPI
token_enum_AddRef( ISpObjectTokenEnumBuilder
*iface
)
726 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
727 ULONG ref
= InterlockedIncrement( &This
->ref
);
729 TRACE( "(%p) ref = %lu\n", This
, ref
);
733 static ULONG WINAPI
token_enum_Release( ISpObjectTokenEnumBuilder
*iface
)
735 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
736 ULONG ref
= InterlockedDecrement(&This
->ref
);
738 TRACE( "(%p) ref = %lu\n", This
, ref
);
743 RegCloseKey(This
->key
);
752 static HRESULT WINAPI
token_enum_Next( ISpObjectTokenEnumBuilder
*iface
,
753 ULONG num
, ISpObjectToken
**tokens
,
756 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
757 struct object_token
*object
;
763 ISpRegDataKey
*data_key
;
765 TRACE( "(%p)->(%lu %p %p)\n", This
, num
, tokens
, fetched
);
767 if (!This
->init
) return SPERR_UNINITIALIZED
;
768 if (fetched
) *fetched
= 0;
772 RegQueryInfoKeyW( This
->key
, NULL
, NULL
, NULL
, NULL
, &size
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
773 size
= (size
+1) * sizeof(WCHAR
);
774 subkey_name
= malloc( size
);
776 return E_OUTOFMEMORY
;
778 retCode
= RegEnumKeyExW( This
->key
, This
->index
, subkey_name
, &size
, NULL
, NULL
, NULL
, NULL
);
779 if (retCode
!= ERROR_SUCCESS
)
787 if (RegOpenKeyExW( This
->key
, subkey_name
, 0, KEY_READ
, &sub_key
) != ERROR_SUCCESS
)
793 hr
= create_data_key_with_hkey( sub_key
, &data_key
);
797 RegCloseKey( sub_key
);
801 hr
= token_create( NULL
, &IID_ISpObjectToken
, (void**)tokens
);
805 ISpRegDataKey_Release( data_key
);
809 object
= impl_from_ISpObjectToken( *tokens
);
810 object
->data_key
= data_key
;
811 object
->token_id
= subkey_name
;
813 if (fetched
) *fetched
= 1;
817 static HRESULT WINAPI
token_enum_Skip( ISpObjectTokenEnumBuilder
*iface
,
824 static HRESULT WINAPI
token_enum_Reset( ISpObjectTokenEnumBuilder
*iface
)
830 static HRESULT WINAPI
token_enum_Clone( ISpObjectTokenEnumBuilder
*iface
,
831 IEnumSpObjectTokens
**clone
)
837 static HRESULT WINAPI
token_enum_Item( ISpObjectTokenEnumBuilder
*iface
,
838 ULONG index
, ISpObjectToken
**token
)
840 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
841 struct object_token
*object
;
842 ISpObjectToken
*subtoken
;
848 ISpRegDataKey
*data_key
;
850 TRACE( "%p, %lu, %p\n", This
, index
, token
);
853 return SPERR_UNINITIALIZED
;
855 RegQueryInfoKeyW(This
->key
, NULL
, NULL
, NULL
, NULL
, &size
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
856 size
= (size
+1) * sizeof(WCHAR
);
857 subkey
= malloc( size
);
859 return E_OUTOFMEMORY
;
861 ret
= RegEnumKeyExW(This
->key
, index
, subkey
, &size
, NULL
, NULL
, NULL
, NULL
);
862 if (ret
!= ERROR_SUCCESS
)
865 return HRESULT_FROM_WIN32(ret
);
868 ret
= RegOpenKeyExW (This
->key
, subkey
, 0, KEY_READ
, &key
);
869 if (ret
!= ERROR_SUCCESS
)
872 return HRESULT_FROM_WIN32(ret
);
875 hr
= create_data_key_with_hkey( key
, &data_key
);
883 hr
= token_create( NULL
, &IID_ISpObjectToken
, (void**)&subtoken
);
887 ISpRegDataKey_Release( data_key
);
891 object
= impl_from_ISpObjectToken( subtoken
);
892 object
->data_key
= data_key
;
893 object
->token_id
= subkey
;
900 static HRESULT WINAPI
token_enum_GetCount( ISpObjectTokenEnumBuilder
*iface
,
903 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
905 TRACE( "(%p)->(%p)\n", This
, count
);
907 if (!This
->init
) return SPERR_UNINITIALIZED
;
909 *count
= This
->count
;
913 static HRESULT WINAPI
token_enum_SetAttribs( ISpObjectTokenEnumBuilder
*iface
,
914 LPCWSTR req
, LPCWSTR opt
)
916 struct token_enum
*This
= impl_from_ISpObjectTokenEnumBuilder( iface
);
918 TRACE( "(%p)->(%s %s)\n", This
, debugstr_w( req
), debugstr_w( opt
) );
920 if (This
->init
) return SPERR_ALREADY_INITIALIZED
;
924 This
->req
= wcsdup( req
);
925 if (!This
->req
) goto out_of_mem
;
930 This
->opt
= wcsdup( opt
);
931 if (!This
->opt
) goto out_of_mem
;
939 return E_OUTOFMEMORY
;
942 static HRESULT WINAPI
token_enum_AddTokens( ISpObjectTokenEnumBuilder
*iface
,
943 ULONG num
, ISpObjectToken
**tokens
)
949 static HRESULT WINAPI
token_enum_AddTokensFromDataKey( ISpObjectTokenEnumBuilder
*iface
,
950 ISpDataKey
*data_key
,
951 LPCWSTR sub_key
, LPCWSTR cat_id
)
957 static HRESULT WINAPI
token_enum_AddTokensFromTokenEnum( ISpObjectTokenEnumBuilder
*iface
,
958 IEnumSpObjectTokens
*token_enum
)
964 static HRESULT WINAPI
token_enum_Sort( ISpObjectTokenEnumBuilder
*iface
,
971 const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl
=
973 token_enum_QueryInterface
,
982 token_enum_SetAttribs
,
983 token_enum_AddTokens
,
984 token_enum_AddTokensFromDataKey
,
985 token_enum_AddTokensFromTokenEnum
,
989 HRESULT
token_enum_create( IUnknown
*outer
, REFIID iid
, void **obj
)
991 struct token_enum
*This
= malloc( sizeof(*This
) );
994 if (!This
) return E_OUTOFMEMORY
;
995 This
->ISpObjectTokenEnumBuilder_iface
.lpVtbl
= &token_enum_vtbl
;
1004 hr
= ISpObjectTokenEnumBuilder_QueryInterface( &This
->ISpObjectTokenEnumBuilder_iface
, iid
, obj
);
1006 ISpObjectTokenEnumBuilder_Release( &This
->ISpObjectTokenEnumBuilder_iface
);
1010 static HRESULT WINAPI
token_QueryInterface( ISpObjectToken
*iface
,
1011 REFIID iid
, void **obj
)
1013 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1015 TRACE( "(%p)->(%s %p)\n", This
, debugstr_guid( iid
), obj
);
1017 if (IsEqualIID( iid
, &IID_IUnknown
) ||
1018 IsEqualIID( iid
, &IID_ISpDataKey
) ||
1019 IsEqualIID( iid
, &IID_ISpObjectToken
))
1021 ISpObjectToken_AddRef( iface
);
1026 FIXME( "interface %s not implemented\n", debugstr_guid( iid
) );
1028 return E_NOINTERFACE
;
1031 static ULONG WINAPI
token_AddRef( ISpObjectToken
*iface
)
1033 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1034 ULONG ref
= InterlockedIncrement( &This
->ref
);
1036 TRACE( "(%p) ref = %lu\n", This
, ref
);
1040 static ULONG WINAPI
token_Release( ISpObjectToken
*iface
)
1042 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1043 ULONG ref
= InterlockedDecrement(&This
->ref
);
1045 TRACE( "(%p) ref = %lu\n", This
, ref
);
1049 if (This
->data_key
) ISpRegDataKey_Release( This
->data_key
);
1050 free( This
->token_id
);
1057 static HRESULT WINAPI
token_SetData( ISpObjectToken
*iface
,
1058 LPCWSTR name
, ULONG size
,
1065 static HRESULT WINAPI
token_GetData( ISpObjectToken
*iface
,
1066 LPCWSTR name
, ULONG
*size
,
1073 static HRESULT WINAPI
token_SetStringValue( ISpObjectToken
*iface
,
1074 LPCWSTR name
, LPCWSTR value
)
1076 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1078 TRACE( "%p, %s, %s\n", This
, debugstr_w(name
), debugstr_w(value
) );
1080 return ISpRegDataKey_SetStringValue( This
->data_key
, name
, value
);
1083 static HRESULT WINAPI
token_GetStringValue( ISpObjectToken
*iface
,
1084 LPCWSTR name
, LPWSTR
*value
)
1086 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1088 TRACE( "%p, %s, %p\n", This
, debugstr_w(name
), value
);
1090 return ISpRegDataKey_GetStringValue( This
->data_key
, name
, value
);
1093 static HRESULT WINAPI
token_SetDWORD( ISpObjectToken
*iface
,
1094 LPCWSTR name
, DWORD value
)
1100 static HRESULT WINAPI
token_GetDWORD( ISpObjectToken
*iface
,
1101 LPCWSTR name
, DWORD
*pdwValue
)
1107 static HRESULT WINAPI
token_OpenKey( ISpObjectToken
*iface
,
1108 LPCWSTR name
, ISpDataKey
**sub_key
)
1110 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1112 TRACE( "%p, %s, %p\n", This
, debugstr_w(name
), sub_key
);
1114 return ISpRegDataKey_OpenKey( This
->data_key
, name
, sub_key
);
1117 static HRESULT WINAPI
token_CreateKey( ISpObjectToken
*iface
,
1118 LPCWSTR name
, ISpDataKey
**sub_key
)
1120 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1122 TRACE( "%p, %s, %p\n", iface
, debugstr_w(name
), sub_key
);
1124 return ISpRegDataKey_CreateKey( This
->data_key
, name
, sub_key
);
1127 static HRESULT WINAPI
token_DeleteKey( ISpObjectToken
*iface
,
1134 static HRESULT WINAPI
token_DeleteValue( ISpObjectToken
*iface
,
1141 static HRESULT WINAPI
token_EnumKeys( ISpObjectToken
*iface
,
1142 ULONG index
, LPWSTR
*sub_key
)
1148 static HRESULT WINAPI
token_EnumValues( ISpObjectToken
*iface
,
1149 ULONG index
, LPWSTR
*value
)
1155 static HRESULT WINAPI
token_SetId( ISpObjectToken
*iface
,
1156 LPCWSTR category_id
, LPCWSTR token_id
,
1159 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1163 const WCHAR
*subkey
;
1165 FIXME( "(%p)->(%s %s %d): semi-stub\n", This
, debugstr_w( category_id
),
1166 debugstr_w(token_id
), create
);
1168 if (This
->data_key
) return SPERR_ALREADY_INITIALIZED
;
1170 if (!token_id
) return E_POINTER
;
1172 hr
= parse_cat_id( token_id
, &root
, &subkey
);
1173 if (hr
!= S_OK
) return SPERR_NOT_FOUND
;
1176 res
= RegCreateKeyExW( root
, subkey
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &key
, NULL
);
1178 res
= RegOpenKeyExW( root
, subkey
, 0, KEY_ALL_ACCESS
, &key
);
1179 if (res
) return SPERR_NOT_FOUND
;
1181 hr
= create_data_key_with_hkey( key
, &This
->data_key
);
1188 This
->token_id
= wcsdup(token_id
);
1193 static HRESULT WINAPI
token_GetId( ISpObjectToken
*iface
,
1196 struct object_token
*This
= impl_from_ISpObjectToken( iface
);
1198 TRACE( "%p, %p\n", This
, token_id
);
1200 if (!This
->data_key
)
1201 return SPERR_UNINITIALIZED
;
1206 if (!This
->token_id
)
1208 FIXME("Loading default category not supported.\n");
1212 *token_id
= CoTaskMemAlloc( (wcslen(This
->token_id
) + 1) * sizeof(WCHAR
));
1214 return E_OUTOFMEMORY
;
1216 wcscpy(*token_id
, This
->token_id
);
1220 static HRESULT WINAPI
token_GetCategory( ISpObjectToken
*iface
,
1221 ISpObjectTokenCategory
**category
)
1227 static HRESULT WINAPI
token_CreateInstance( ISpObjectToken
*iface
,
1229 DWORD class_context
,
1236 ISpObjectWithToken
*obj_token_iface
;
1239 TRACE( "%p, %p, %#lx, %s, %p\n", iface
, outer
, class_context
, debugstr_guid( riid
), object
);
1241 if (FAILED(hr
= ISpObjectToken_GetStringValue( iface
, L
"CLSID", &clsid_str
)))
1244 hr
= CLSIDFromString( clsid_str
, &clsid
);
1245 CoTaskMemFree( clsid_str
);
1249 if (FAILED(hr
= CoCreateInstance( &clsid
, outer
, class_context
, &IID_IUnknown
, (void **)&unk
)))
1252 /* Call ISpObjectWithToken::SetObjectToken if the interface is available. */
1253 if (SUCCEEDED(IUnknown_QueryInterface( unk
, &IID_ISpObjectWithToken
, (void **)&obj_token_iface
)))
1255 hr
= ISpObjectWithToken_SetObjectToken( obj_token_iface
, iface
);
1256 ISpObjectWithToken_Release( obj_token_iface
);
1261 hr
= IUnknown_QueryInterface( unk
, riid
, object
);
1264 IUnknown_Release( unk
);
1268 static HRESULT WINAPI
token_GetStorageFileName( ISpObjectToken
*iface
,
1279 static HRESULT WINAPI
token_RemoveStorageFileName( ISpObjectToken
*iface
,
1288 static HRESULT WINAPI
token_Remove( ISpObjectToken
*iface
,
1295 static HRESULT WINAPI
token_IsUISupported( ISpObjectToken
*iface
,
1298 ULONG extra_data_size
,
1306 static HRESULT WINAPI
token_DisplayUI( ISpObjectToken
*iface
,
1311 ULONG extra_data_size
,
1318 static HRESULT WINAPI
token_MatchesAttributes( ISpObjectToken
*iface
,
1326 const struct ISpObjectTokenVtbl token_vtbl
=
1328 token_QueryInterface
,
1333 token_SetStringValue
,
1334 token_GetStringValue
,
1346 token_CreateInstance
,
1347 token_GetStorageFileName
,
1348 token_RemoveStorageFileName
,
1350 token_IsUISupported
,
1352 token_MatchesAttributes
1355 HRESULT
token_create( IUnknown
*outer
, REFIID iid
, void **obj
)
1357 struct object_token
*This
= malloc( sizeof(*This
) );
1360 if (!This
) return E_OUTOFMEMORY
;
1361 This
->ISpObjectToken_iface
.lpVtbl
= &token_vtbl
;
1364 This
->data_key
= NULL
;
1365 This
->token_id
= NULL
;
1367 hr
= ISpObjectToken_QueryInterface( &This
->ISpObjectToken_iface
, iid
, obj
);
1369 ISpObjectToken_Release( &This
->ISpObjectToken_iface
);