sapi: Implement ISpObjectToken::CreateKey.
[wine.git] / dlls / sapi / token.c
blobdbbc14b6e56aba10e91f13785f76cf10c5c10db0
1 /*
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
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "sapiddk.h"
29 #include "sperror.h"
31 #include "wine/debug.h"
33 #include "sapi_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(sapi);
37 struct data_key
39 ISpRegDataKey ISpRegDataKey_iface;
40 LONG ref;
42 HKEY key;
45 static struct data_key *impl_from_ISpRegDataKey( ISpRegDataKey *iface )
47 return CONTAINING_RECORD( iface, struct data_key, ISpRegDataKey_iface );
50 struct object_token
52 ISpObjectToken ISpObjectToken_iface;
53 LONG ref;
55 ISpRegDataKey *data_key;
56 WCHAR *token_id;
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 );
75 *obj = iface;
76 return S_OK;
79 FIXME( "interface %s not implemented\n", debugstr_guid( iid ) );
80 *obj = NULL;
81 return E_NOINTERFACE;
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 );
90 return 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 );
100 if (!ref)
102 if (This->key) RegCloseKey( This->key );
103 free( This );
106 return ref;
109 static HRESULT WINAPI data_key_SetData( ISpRegDataKey *iface, LPCWSTR name,
110 ULONG size, const BYTE *data )
112 FIXME( "stub\n" );
113 return E_NOTIMPL;
116 static HRESULT WINAPI data_key_GetData( ISpRegDataKey *iface, LPCWSTR name,
117 ULONG *size, BYTE *data )
119 FIXME( "stub\n" );
120 return E_NOTIMPL;
123 static HRESULT WINAPI data_key_SetStringValue( ISpRegDataKey *iface,
124 LPCWSTR name, LPCWSTR value )
126 struct data_key *This = impl_from_ISpRegDataKey( iface );
127 DWORD ret, size;
129 TRACE( "%p, %s, %s\n", This, debugstr_w(name), debugstr_w(value) );
131 if (!This->key)
132 return E_HANDLE;
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 );
144 DWORD ret, size;
145 WCHAR *content;
147 TRACE( "%p, %s, %p\n", This, debugstr_w(name), value);
149 if (!This->key)
150 return E_HANDLE;
152 size = 0;
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);
158 if (!content)
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);
168 *value = content;
169 return S_OK;
172 static HRESULT WINAPI data_key_SetDWORD( ISpRegDataKey *iface,
173 LPCWSTR name, DWORD value )
175 FIXME( "stub\n" );
176 return E_NOTIMPL;
179 static HRESULT WINAPI data_key_GetDWORD( ISpRegDataKey *iface,
180 LPCWSTR name, DWORD *pdwValue )
182 FIXME( "stub\n" );
183 return E_NOTIMPL;
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;
191 HRESULT hr;
192 HKEY key;
193 LONG ret;
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 );
202 if (FAILED(hr))
204 RegCloseKey( key );
205 return hr;
208 hr = ISpRegDataKey_SetKey( spregkey, key, FALSE );
209 if (FAILED(hr))
211 RegCloseKey( key );
212 ISpRegDataKey_Release( spregkey );
213 return hr;
216 hr = ISpRegDataKey_QueryInterface( spregkey, &IID_ISpDataKey, (void**)sub_key );
217 ISpRegDataKey_Release( spregkey );
219 return hr;
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;
227 HRESULT hr;
228 HKEY key;
229 LONG res;
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);
238 if (SUCCEEDED(hr))
240 hr = ISpRegDataKey_SetKey(spregkey, key, FALSE);
241 if (SUCCEEDED(hr))
242 hr = ISpRegDataKey_QueryInterface(spregkey, &IID_ISpDataKey, (void**)sub_key);
243 ISpRegDataKey_Release(spregkey);
246 return hr;
249 static HRESULT WINAPI data_key_DeleteKey( ISpRegDataKey *iface, LPCWSTR name )
251 FIXME( "stub\n" );
252 return E_NOTIMPL;
255 static HRESULT WINAPI data_key_DeleteValue( ISpRegDataKey *iface, LPCWSTR name )
257 FIXME( "stub\n" );
258 return E_NOTIMPL;
261 static HRESULT WINAPI data_key_EnumKeys( ISpRegDataKey *iface,
262 ULONG index, LPWSTR *sub_key )
264 FIXME( "stub\n" );
265 return E_NOTIMPL;
268 static HRESULT WINAPI data_key_EnumValues( ISpRegDataKey *iface,
269 ULONG index, LPWSTR *value )
271 FIXME( "stub\n" );
272 return E_NOTIMPL;
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. */
285 This->key = key;
286 return S_OK;
289 const struct ISpRegDataKeyVtbl data_key_vtbl =
291 data_key_QueryInterface,
292 data_key_AddRef,
293 data_key_Release,
294 data_key_SetData,
295 data_key_GetData,
296 data_key_SetStringValue,
297 data_key_GetStringValue,
298 data_key_SetDWORD,
299 data_key_GetDWORD,
300 data_key_OpenKey,
301 data_key_CreateKey,
302 data_key_DeleteKey,
303 data_key_DeleteValue,
304 data_key_EnumKeys,
305 data_key_EnumValues,
306 data_key_SetKey
309 HRESULT data_key_create( IUnknown *outer, REFIID iid, void **obj )
311 struct data_key *This = malloc( sizeof(*This) );
312 HRESULT hr;
314 if (!This) return E_OUTOFMEMORY;
315 This->ISpRegDataKey_iface.lpVtbl = &data_key_vtbl;
316 This->ref = 1;
317 This->key = NULL;
319 hr = ISpRegDataKey_QueryInterface( &This->ISpRegDataKey_iface, iid, obj );
321 ISpRegDataKey_Release( &This->ISpRegDataKey_iface );
322 return hr;
325 struct token_category
327 ISpObjectTokenCategory ISpObjectTokenCategory_iface;
328 LONG ref;
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 );
350 *obj = iface;
351 return S_OK;
354 FIXME( "interface %s not implemented\n", debugstr_guid( iid ) );
355 *obj = NULL;
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 );
365 return 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 );
375 if (!ref)
377 if (This->data_key) ISpRegDataKey_Release( This->data_key );
378 free( This );
380 return ref;
383 static HRESULT WINAPI token_category_SetData( ISpObjectTokenCategory *iface,
384 LPCWSTR name, ULONG size,
385 const BYTE *data )
387 FIXME( "stub\n" );
388 return E_NOTIMPL;
391 static HRESULT WINAPI token_category_GetData( ISpObjectTokenCategory *iface,
392 LPCWSTR name, ULONG *size,
393 BYTE *data )
395 FIXME( "stub\n" );
396 return E_NOTIMPL;
399 static HRESULT WINAPI token_category_SetStringValue( ISpObjectTokenCategory *iface,
400 LPCWSTR name, LPCWSTR value )
402 FIXME( "stub\n" );
403 return E_NOTIMPL;
406 static HRESULT WINAPI token_category_GetStringValue( ISpObjectTokenCategory *iface,
407 LPCWSTR name, LPWSTR *value )
409 FIXME( "stub\n" );
410 return E_NOTIMPL;
413 static HRESULT WINAPI token_category_SetDWORD( ISpObjectTokenCategory *iface,
414 LPCWSTR name, DWORD value )
416 FIXME( "stub\n" );
417 return E_NOTIMPL;
420 static HRESULT WINAPI token_category_GetDWORD( ISpObjectTokenCategory *iface,
421 LPCWSTR name, DWORD *pdwValue )
423 FIXME( "stub\n" );
424 return E_NOTIMPL;
427 static HRESULT WINAPI token_category_OpenKey( ISpObjectTokenCategory *iface,
428 LPCWSTR name, ISpDataKey **sub_key )
430 FIXME( "stub\n" );
431 return E_NOTIMPL;
434 static HRESULT WINAPI token_category_CreateKey( ISpObjectTokenCategory *iface,
435 LPCWSTR name, ISpDataKey **sub_key )
437 FIXME( "stub\n" );
438 return E_NOTIMPL;
441 static HRESULT WINAPI token_category_DeleteKey( ISpObjectTokenCategory *iface,
442 LPCWSTR name )
444 FIXME( "stub\n" );
445 return E_NOTIMPL;
448 static HRESULT WINAPI token_category_DeleteValue( ISpObjectTokenCategory *iface,
449 LPCWSTR name )
451 FIXME( "stub\n" );
452 return E_NOTIMPL;
455 static HRESULT WINAPI token_category_EnumKeys( ISpObjectTokenCategory *iface,
456 ULONG index, LPWSTR *sub_key )
458 FIXME( "stub\n" );
459 return E_NOTIMPL;
462 static HRESULT WINAPI token_category_EnumValues( ISpObjectTokenCategory *iface,
463 ULONG index, LPWSTR *value )
465 FIXME( "stub\n" );
466 return E_NOTIMPL;
469 static HRESULT parse_cat_id( const WCHAR *str, HKEY *root, const WCHAR **sub_key )
471 struct table
473 const WCHAR *name;
474 unsigned int len;
475 HKEY key;
476 } table[] =
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 },
481 { NULL }
482 #undef X
484 struct table *ptr;
485 int len = lstrlenW( str );
487 for (ptr = table; ptr->name; ptr++)
489 if (len >= ptr->len && !wcsncmp( str, ptr->name, ptr->len ))
491 *root = ptr->key;
492 *sub_key = str + ptr->len;
493 return S_OK;
496 return S_FALSE;
499 static HRESULT WINAPI create_data_key_with_hkey( HKEY key, ISpRegDataKey **data_key )
501 HRESULT hr;
503 if (FAILED(hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_INPROC_SERVER,
504 &IID_ISpRegDataKey, (void **)data_key ) ))
505 return hr;
507 if (FAILED(hr = ISpRegDataKey_SetKey( *data_key, key, TRUE )))
509 ISpRegDataKey_Release( *data_key );
510 *data_key = NULL;
513 return hr;
516 static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface,
517 LPCWSTR id, BOOL create )
519 struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
520 HKEY root, key;
521 const WCHAR *subkey;
522 LONG res;
523 HRESULT hr;
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;
532 if (create)
533 res = RegCreateKeyExW( root, subkey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL );
534 else
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 )))
540 RegCloseKey( key );
541 return hr;
544 return hr;
547 static HRESULT WINAPI token_category_GetId( ISpObjectTokenCategory *iface,
548 LPWSTR *id )
550 FIXME( "stub\n" );
551 return E_NOTIMPL;
554 static HRESULT WINAPI token_category_GetDataKey( ISpObjectTokenCategory *iface,
555 SPDATAKEYLOCATION location,
556 ISpDataKey **data_key )
558 FIXME( "stub\n" );
559 return E_NOTIMPL;
562 struct token_enum
564 ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface;
565 LONG ref;
567 BOOL init;
568 WCHAR *req, *opt;
569 ULONG count;
570 HKEY key;
571 DWORD index;
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;
587 HRESULT hr;
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 );
613 fail:
614 ISpObjectTokenEnumBuilder_Release( builder );
615 return hr;
618 static HRESULT WINAPI token_category_SetDefaultTokenId( ISpObjectTokenCategory *iface,
619 LPCWSTR id )
621 FIXME( "stub\n" );
622 return E_NOTIMPL;
625 static HRESULT WINAPI token_category_GetDefaultTokenId( ISpObjectTokenCategory *iface,
626 LPWSTR *id )
628 struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
629 struct data_key *this_data_key;
630 LONG res;
631 WCHAR regvalue[512];
632 DWORD regvalue_size = sizeof( regvalue );
634 FIXME( "(%p)->(%p): semi-stub\n", iface, id );
636 if (!This->data_key)
637 return SPERR_UNINITIALIZED;
639 if (!id)
640 return E_POINTER;
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, &regvalue, &regvalue_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 );
653 return res;
656 *id = CoTaskMemAlloc( regvalue_size );
657 wcscpy( *id, regvalue );
659 return S_OK;
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) );
690 HRESULT hr;
692 if (!This) return E_OUTOFMEMORY;
693 This->ISpObjectTokenCategory_iface.lpVtbl = &token_category_vtbl;
694 This->ref = 1;
695 This->data_key = NULL;
697 hr = ISpObjectTokenCategory_QueryInterface( &This->ISpObjectTokenCategory_iface, iid, obj );
699 ISpObjectTokenCategory_Release( &This->ISpObjectTokenCategory_iface );
700 return hr;
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 );
715 *obj = iface;
716 return S_OK;
719 FIXME( "interface %s not implemented\n", debugstr_guid( iid ) );
720 *obj = NULL;
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 );
730 return 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 );
740 if (!ref)
742 if (This->key)
743 RegCloseKey(This->key);
744 free( This->req );
745 free( This->opt );
746 free( This );
749 return ref;
752 static HRESULT WINAPI token_enum_Next( ISpObjectTokenEnumBuilder *iface,
753 ULONG num, ISpObjectToken **tokens,
754 ULONG *fetched )
756 struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
757 struct object_token *object;
758 HRESULT hr;
759 DWORD retCode;
760 WCHAR *subkey_name;
761 HKEY sub_key;
762 DWORD size;
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;
770 *tokens = NULL;
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 );
775 if (!subkey_name)
776 return E_OUTOFMEMORY;
778 retCode = RegEnumKeyExW( This->key, This->index, subkey_name, &size, NULL, NULL, NULL, NULL );
779 if (retCode != ERROR_SUCCESS)
781 free( subkey_name );
782 return S_FALSE;
785 This->index++;
787 if (RegOpenKeyExW( This->key, subkey_name, 0, KEY_READ, &sub_key ) != ERROR_SUCCESS)
789 free( subkey_name );
790 return E_FAIL;
793 hr = create_data_key_with_hkey( sub_key, &data_key );
794 if (FAILED(hr))
796 free( subkey_name );
797 RegCloseKey( sub_key );
798 return hr;
801 hr = token_create( NULL, &IID_ISpObjectToken, (void**)tokens );
802 if (FAILED(hr))
804 free( subkey_name );
805 ISpRegDataKey_Release( data_key );
806 return hr;
809 object = impl_from_ISpObjectToken( *tokens );
810 object->data_key = data_key;
811 object->token_id = subkey_name;
813 if (fetched) *fetched = 1;
814 return hr;
817 static HRESULT WINAPI token_enum_Skip( ISpObjectTokenEnumBuilder *iface,
818 ULONG num )
820 FIXME( "stub\n" );
821 return E_NOTIMPL;
824 static HRESULT WINAPI token_enum_Reset( ISpObjectTokenEnumBuilder *iface)
826 FIXME( "stub\n" );
827 return E_NOTIMPL;
830 static HRESULT WINAPI token_enum_Clone( ISpObjectTokenEnumBuilder *iface,
831 IEnumSpObjectTokens **clone )
833 FIXME( "stub\n" );
834 return E_NOTIMPL;
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;
843 HRESULT hr;
844 WCHAR *subkey;
845 DWORD size;
846 LONG ret;
847 HKEY key;
848 ISpRegDataKey *data_key;
850 TRACE( "%p, %lu, %p\n", This, index, token );
852 if (!This->init)
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 );
858 if (!subkey)
859 return E_OUTOFMEMORY;
861 ret = RegEnumKeyExW(This->key, index, subkey, &size, NULL, NULL, NULL, NULL);
862 if (ret != ERROR_SUCCESS)
864 free( subkey );
865 return HRESULT_FROM_WIN32(ret);
868 ret = RegOpenKeyExW (This->key, subkey, 0, KEY_READ, &key);
869 if (ret != ERROR_SUCCESS)
871 free( subkey );
872 return HRESULT_FROM_WIN32(ret);
875 hr = create_data_key_with_hkey( key, &data_key );
876 if (FAILED(hr))
878 free( subkey );
879 RegCloseKey( key );
880 return hr;
883 hr = token_create( NULL, &IID_ISpObjectToken, (void**)&subtoken );
884 if (FAILED(hr))
886 free( subkey );
887 ISpRegDataKey_Release( data_key );
888 return hr;
891 object = impl_from_ISpObjectToken( subtoken );
892 object->data_key = data_key;
893 object->token_id = subkey;
895 *token = subtoken;
897 return hr;
900 static HRESULT WINAPI token_enum_GetCount( ISpObjectTokenEnumBuilder *iface,
901 ULONG *count )
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;
910 return S_OK;
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;
922 if (req)
924 This->req = wcsdup( req );
925 if (!This->req) goto out_of_mem;
928 if (opt)
930 This->opt = wcsdup( opt );
931 if (!This->opt) goto out_of_mem;
934 This->init = TRUE;
935 return S_OK;
937 out_of_mem:
938 free( This->req );
939 return E_OUTOFMEMORY;
942 static HRESULT WINAPI token_enum_AddTokens( ISpObjectTokenEnumBuilder *iface,
943 ULONG num, ISpObjectToken **tokens )
945 FIXME( "stub\n" );
946 return E_NOTIMPL;
949 static HRESULT WINAPI token_enum_AddTokensFromDataKey( ISpObjectTokenEnumBuilder *iface,
950 ISpDataKey *data_key,
951 LPCWSTR sub_key, LPCWSTR cat_id )
953 FIXME( "stub\n" );
954 return E_NOTIMPL;
957 static HRESULT WINAPI token_enum_AddTokensFromTokenEnum( ISpObjectTokenEnumBuilder *iface,
958 IEnumSpObjectTokens *token_enum )
960 FIXME( "stub\n" );
961 return E_NOTIMPL;
964 static HRESULT WINAPI token_enum_Sort( ISpObjectTokenEnumBuilder *iface,
965 LPCWSTR first )
967 FIXME( "stub\n" );
968 return E_NOTIMPL;
971 const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl =
973 token_enum_QueryInterface,
974 token_enum_AddRef,
975 token_enum_Release,
976 token_enum_Next,
977 token_enum_Skip,
978 token_enum_Reset,
979 token_enum_Clone,
980 token_enum_Item,
981 token_enum_GetCount,
982 token_enum_SetAttribs,
983 token_enum_AddTokens,
984 token_enum_AddTokensFromDataKey,
985 token_enum_AddTokensFromTokenEnum,
986 token_enum_Sort
989 HRESULT token_enum_create( IUnknown *outer, REFIID iid, void **obj )
991 struct token_enum *This = malloc( sizeof(*This) );
992 HRESULT hr;
994 if (!This) return E_OUTOFMEMORY;
995 This->ISpObjectTokenEnumBuilder_iface.lpVtbl = &token_enum_vtbl;
996 This->ref = 1;
997 This->req = NULL;
998 This->opt = NULL;
999 This->init = FALSE;
1000 This->count = 0;
1001 This->key = NULL;
1002 This->index = 0;
1004 hr = ISpObjectTokenEnumBuilder_QueryInterface( &This->ISpObjectTokenEnumBuilder_iface, iid, obj );
1006 ISpObjectTokenEnumBuilder_Release( &This->ISpObjectTokenEnumBuilder_iface );
1007 return hr;
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 );
1022 *obj = iface;
1023 return S_OK;
1026 FIXME( "interface %s not implemented\n", debugstr_guid( iid ) );
1027 *obj = NULL;
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 );
1037 return 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 );
1047 if (!ref)
1049 if (This->data_key) ISpRegDataKey_Release( This->data_key );
1050 free( This->token_id );
1051 free( This );
1054 return ref;
1057 static HRESULT WINAPI token_SetData( ISpObjectToken *iface,
1058 LPCWSTR name, ULONG size,
1059 const BYTE *data )
1061 FIXME( "stub\n" );
1062 return E_NOTIMPL;
1065 static HRESULT WINAPI token_GetData( ISpObjectToken *iface,
1066 LPCWSTR name, ULONG *size,
1067 BYTE *data )
1069 FIXME( "stub\n" );
1070 return E_NOTIMPL;
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 )
1096 FIXME( "stub\n" );
1097 return E_NOTIMPL;
1100 static HRESULT WINAPI token_GetDWORD( ISpObjectToken *iface,
1101 LPCWSTR name, DWORD *pdwValue )
1103 FIXME( "stub\n" );
1104 return E_NOTIMPL;
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,
1128 LPCWSTR name )
1130 FIXME( "stub\n" );
1131 return E_NOTIMPL;
1134 static HRESULT WINAPI token_DeleteValue( ISpObjectToken *iface,
1135 LPCWSTR name )
1137 FIXME( "stub\n" );
1138 return E_NOTIMPL;
1141 static HRESULT WINAPI token_EnumKeys( ISpObjectToken *iface,
1142 ULONG index, LPWSTR *sub_key )
1144 FIXME( "stub\n" );
1145 return E_NOTIMPL;
1148 static HRESULT WINAPI token_EnumValues( ISpObjectToken *iface,
1149 ULONG index, LPWSTR *value )
1151 FIXME( "stub\n" );
1152 return E_NOTIMPL;
1155 static HRESULT WINAPI token_SetId( ISpObjectToken *iface,
1156 LPCWSTR category_id, LPCWSTR token_id,
1157 BOOL create )
1159 struct object_token *This = impl_from_ISpObjectToken( iface );
1160 BOOL res;
1161 HRESULT hr;
1162 HKEY root, key;
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;
1175 if (create)
1176 res = RegCreateKeyExW( root, subkey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL);
1177 else
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 );
1182 if (FAILED(hr))
1184 RegCloseKey( key );
1185 return hr;
1188 This->token_id = wcsdup(token_id);
1190 return S_OK;
1193 static HRESULT WINAPI token_GetId( ISpObjectToken *iface,
1194 LPWSTR *token_id )
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;
1203 if (!token_id)
1204 return E_POINTER;
1206 if (!This->token_id)
1208 FIXME("Loading default category not supported.\n");
1209 return E_POINTER;
1212 *token_id = CoTaskMemAlloc( (wcslen(This->token_id) + 1) * sizeof(WCHAR));
1213 if (!*token_id)
1214 return E_OUTOFMEMORY;
1216 wcscpy(*token_id, This->token_id);
1217 return S_OK;
1220 static HRESULT WINAPI token_GetCategory( ISpObjectToken *iface,
1221 ISpObjectTokenCategory **category )
1223 FIXME( "stub\n" );
1224 return E_NOTIMPL;
1227 static HRESULT WINAPI token_CreateInstance( ISpObjectToken *iface,
1228 IUnknown *outer,
1229 DWORD class_context,
1230 REFIID riid,
1231 void **object )
1233 WCHAR *clsid_str;
1234 CLSID clsid;
1235 IUnknown *unk;
1236 ISpObjectWithToken *obj_token_iface;
1237 HRESULT hr;
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 )))
1242 return hr;
1244 hr = CLSIDFromString( clsid_str, &clsid );
1245 CoTaskMemFree( clsid_str );
1246 if (FAILED(hr))
1247 return hr;
1249 if (FAILED(hr = CoCreateInstance( &clsid, outer, class_context, &IID_IUnknown, (void **)&unk )))
1250 return hr;
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 );
1257 if (FAILED(hr))
1258 goto done;
1261 hr = IUnknown_QueryInterface( unk, riid, object );
1263 done:
1264 IUnknown_Release( unk );
1265 return hr;
1268 static HRESULT WINAPI token_GetStorageFileName( ISpObjectToken *iface,
1269 REFCLSID caller,
1270 LPCWSTR key_name,
1271 LPCWSTR filename,
1272 ULONG folder,
1273 LPWSTR *filepath )
1275 FIXME( "stub\n" );
1276 return E_NOTIMPL;
1279 static HRESULT WINAPI token_RemoveStorageFileName( ISpObjectToken *iface,
1280 REFCLSID caller,
1281 LPCWSTR key_name,
1282 BOOL delete_file )
1284 FIXME( "stub\n" );
1285 return E_NOTIMPL;
1288 static HRESULT WINAPI token_Remove( ISpObjectToken *iface,
1289 REFCLSID caller )
1291 FIXME( "stub\n" );
1292 return E_NOTIMPL;
1295 static HRESULT WINAPI token_IsUISupported( ISpObjectToken *iface,
1296 LPCWSTR ui_type,
1297 void *extra_data,
1298 ULONG extra_data_size,
1299 IUnknown *object,
1300 BOOL *supported )
1302 FIXME( "stub\n" );
1303 return E_NOTIMPL;
1306 static HRESULT WINAPI token_DisplayUI( ISpObjectToken *iface,
1307 HWND parent,
1308 LPCWSTR title,
1309 LPCWSTR ui_type,
1310 void *extra_data,
1311 ULONG extra_data_size,
1312 IUnknown *object )
1314 FIXME( "stub\n" );
1315 return E_NOTIMPL;
1318 static HRESULT WINAPI token_MatchesAttributes( ISpObjectToken *iface,
1319 LPCWSTR attributes,
1320 BOOL *matches )
1322 FIXME( "stub\n" );
1323 return E_NOTIMPL;
1326 const struct ISpObjectTokenVtbl token_vtbl =
1328 token_QueryInterface,
1329 token_AddRef,
1330 token_Release,
1331 token_SetData,
1332 token_GetData,
1333 token_SetStringValue,
1334 token_GetStringValue,
1335 token_SetDWORD,
1336 token_GetDWORD,
1337 token_OpenKey,
1338 token_CreateKey,
1339 token_DeleteKey,
1340 token_DeleteValue,
1341 token_EnumKeys,
1342 token_EnumValues,
1343 token_SetId,
1344 token_GetId,
1345 token_GetCategory,
1346 token_CreateInstance,
1347 token_GetStorageFileName,
1348 token_RemoveStorageFileName,
1349 token_Remove,
1350 token_IsUISupported,
1351 token_DisplayUI,
1352 token_MatchesAttributes
1355 HRESULT token_create( IUnknown *outer, REFIID iid, void **obj )
1357 struct object_token *This = malloc( sizeof(*This) );
1358 HRESULT hr;
1360 if (!This) return E_OUTOFMEMORY;
1361 This->ISpObjectToken_iface.lpVtbl = &token_vtbl;
1362 This->ref = 1;
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 );
1370 return hr;