mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-15 03:39:47 +00:00
sapi: Partially reimplement ISpObjectTokenEnumBuilder storing a token array.
This is needed in order to implement filtering and sorting in ISpObjectTokenCategory::EnumTokens.
This commit is contained in:
parent
e071a70ba8
commit
f286ee9bfa
|
@ -109,6 +109,63 @@ static void test_data_key(void)
|
|||
ISpRegDataKey_Release( data_key );
|
||||
}
|
||||
|
||||
static void setup_test_voice_tokens(void)
|
||||
{
|
||||
HKEY key;
|
||||
ISpRegDataKey *data_key;
|
||||
ISpDataKey *attrs_key;
|
||||
LSTATUS ret;
|
||||
HRESULT hr;
|
||||
|
||||
ret = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Winetest\\sapi\\TestVoices\\Tokens", 0, NULL, 0,
|
||||
KEY_ALL_ACCESS, NULL, &key, NULL );
|
||||
ok( ret == ERROR_SUCCESS, "got %ld\n", ret );
|
||||
|
||||
hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_ISpRegDataKey, (void **)&data_key );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
hr = ISpRegDataKey_SetKey( data_key, key, FALSE );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
|
||||
ISpRegDataKey_CreateKey( data_key, L"Voice1\\Attributes", &attrs_key );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Language", L"409" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Gender", L"Female" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Age", L"Child" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Vendor", L"Vendor2" );
|
||||
ISpDataKey_Release( attrs_key );
|
||||
|
||||
ISpRegDataKey_CreateKey( data_key, L"Voice2\\Attributes", &attrs_key );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Language", L"406;407;408;409;40a" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Gender", L"Female" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Age", L"Adult" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Vendor", L"Vendor1" );
|
||||
ISpDataKey_Release( attrs_key );
|
||||
|
||||
ISpRegDataKey_CreateKey( data_key, L"Voice3\\Attributes", &attrs_key );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Language", L"409;411" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Gender", L"Female" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Age", L"Child" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Vendor", L"Vendor1" );
|
||||
ISpDataKey_Release( attrs_key );
|
||||
|
||||
ISpRegDataKey_CreateKey( data_key, L"Voice4\\Attributes", &attrs_key );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Language", L"411" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Gender", L"Male" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Age", L"Adult" );
|
||||
ISpDataKey_Release( attrs_key );
|
||||
|
||||
ISpRegDataKey_CreateKey( data_key, L"Voice5\\Attributes", &attrs_key );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Language", L"411" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Gender", L"Female" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Age", L"Adult" );
|
||||
ISpDataKey_SetStringValue( attrs_key, L"Vendor", L"Vendor2" );
|
||||
ISpDataKey_Release( attrs_key );
|
||||
|
||||
ISpRegDataKey_Release( data_key );
|
||||
}
|
||||
|
||||
static const WCHAR test_cat[] = L"HKEY_CURRENT_USER\\Software\\Winetest\\sapi\\TestVoices";
|
||||
|
||||
static void test_token_category(void)
|
||||
{
|
||||
ISpObjectTokenCategory *cat;
|
||||
|
@ -126,17 +183,19 @@ static void test_token_category(void)
|
|||
hr = ISpObjectTokenCategory_SetId( cat, L"bogus", FALSE );
|
||||
ok( hr == SPERR_INVALID_REGISTRY_KEY, "got %08lx\n", hr );
|
||||
|
||||
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_VOICES, FALSE );
|
||||
hr = ISpObjectTokenCategory_SetId( cat, test_cat, FALSE );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
|
||||
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_VOICES, FALSE );
|
||||
hr = ISpObjectTokenCategory_SetId( cat, test_cat, FALSE );
|
||||
ok( hr == SPERR_ALREADY_INITIALIZED, "got %08lx\n", hr );
|
||||
|
||||
hr = ISpObjectTokenCategory_EnumTokens( cat, NULL, NULL, &enum_tokens );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
|
||||
count = 0xdeadbeef;
|
||||
hr = IEnumSpObjectTokens_GetCount( enum_tokens, &count );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
ok( count == 5, "got %lu\n", count );
|
||||
|
||||
IEnumSpObjectTokens_Release( enum_tokens );
|
||||
ISpObjectTokenCategory_Release( cat );
|
||||
|
@ -146,8 +205,11 @@ static void test_token_enum(void)
|
|||
{
|
||||
ISpObjectTokenEnumBuilder *token_enum;
|
||||
HRESULT hr;
|
||||
ISpObjectToken *token;
|
||||
ISpObjectToken *tokens[3];
|
||||
ISpObjectToken *out_tokens[3];
|
||||
WCHAR token_id[MAX_PATH];
|
||||
ULONG count;
|
||||
int i;
|
||||
|
||||
hr = CoCreateInstance( &CLSID_SpObjectTokenEnum, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_ISpObjectTokenEnumBuilder, (void **)&token_enum );
|
||||
|
@ -156,7 +218,7 @@ static void test_token_enum(void)
|
|||
hr = ISpObjectTokenEnumBuilder_GetCount( token_enum, &count );
|
||||
ok( hr == SPERR_UNINITIALIZED, "got %08lx\n", hr );
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 1, &token, &count );
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 1, tokens, &count );
|
||||
ok( hr == SPERR_UNINITIALIZED, "got %08lx\n", hr );
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_SetAttribs( token_enum, NULL, NULL );
|
||||
|
@ -168,11 +230,50 @@ static void test_token_enum(void)
|
|||
ok( count == 0, "got %lu\n", count );
|
||||
|
||||
count = 0xdeadbeef;
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 1, &token, &count );
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 1, &out_tokens[0], &count );
|
||||
ok( hr == S_FALSE, "got %08lx\n", hr );
|
||||
ok( count == 0, "got %lu\n", count );
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
hr = CoCreateInstance( &CLSID_SpObjectToken, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_ISpObjectToken, (void **)&tokens[i] );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
|
||||
swprintf( token_id, MAX_PATH, L"%ls\\Tokens\\Voice%d", test_cat, i + 1 );
|
||||
hr = ISpObjectToken_SetId( tokens[i], NULL, token_id, FALSE );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
}
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_AddTokens( token_enum, 3, tokens );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
|
||||
out_tokens[0] = (ISpObjectToken *)0xdeadbeef;
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 1, &out_tokens[0], NULL );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
ok( out_tokens[0] == tokens[0], "got %p\n", out_tokens[0] );
|
||||
|
||||
out_tokens[0] = (ISpObjectToken *)0xdeadbeef;
|
||||
hr = ISpObjectTokenEnumBuilder_Item( token_enum, 0, &out_tokens[0] );
|
||||
ok( hr == S_OK, "got %08lx\n", hr );
|
||||
ok( out_tokens[0] == tokens[0], "got %p\n", out_tokens[0] );
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_Item( token_enum, 3, &out_tokens[0] );
|
||||
ok( hr == SPERR_NO_MORE_ITEMS, "got %08lx\n", hr );
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 3, &out_tokens[1], NULL );
|
||||
ok( hr == E_POINTER, "got %08lx\n", hr );
|
||||
|
||||
count = 0xdeadbeef;
|
||||
out_tokens[1] = out_tokens[2] = (ISpObjectToken *)0xdeadbeef;
|
||||
hr = ISpObjectTokenEnumBuilder_Next( token_enum, 3, &out_tokens[1], &count );
|
||||
ok( hr == S_FALSE, "got %08lx\n", hr );
|
||||
ok( count == 2, "got %lu\n", count );
|
||||
ok( out_tokens[1] == tokens[1], "got %p\n", out_tokens[1] );
|
||||
ok( out_tokens[2] == tokens[2], "got %p\n", out_tokens[2] );
|
||||
|
||||
ISpObjectTokenEnumBuilder_Release( token_enum );
|
||||
|
||||
for ( i = 0; i < 3; i++ ) ISpObjectToken_Release( tokens[i] );
|
||||
}
|
||||
|
||||
static void test_default_token_id(void)
|
||||
|
@ -558,6 +659,7 @@ START_TEST(token)
|
|||
CoInitialize( NULL );
|
||||
RegDeleteTreeA( HKEY_CURRENT_USER, "Software\\Winetest\\sapi" );
|
||||
test_data_key();
|
||||
setup_test_voice_tokens();
|
||||
test_token_category();
|
||||
test_token_enum();
|
||||
test_default_token_id();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define COBJMACROS
|
||||
|
||||
|
@ -328,6 +329,7 @@ struct token_category
|
|||
LONG ref;
|
||||
|
||||
ISpRegDataKey *data_key;
|
||||
WCHAR *id;
|
||||
};
|
||||
|
||||
static struct token_category *impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory *iface )
|
||||
|
@ -375,6 +377,7 @@ static ULONG WINAPI token_category_Release( ISpObjectTokenCategory *iface )
|
|||
if (!ref)
|
||||
{
|
||||
if (This->data_key) ISpRegDataKey_Release( This->data_key );
|
||||
free( This->id );
|
||||
free( This );
|
||||
}
|
||||
return ref;
|
||||
|
@ -541,6 +544,8 @@ static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface,
|
|||
return hr;
|
||||
}
|
||||
|
||||
This->id = wcsdup( id );
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -559,6 +564,12 @@ static HRESULT WINAPI token_category_GetDataKey( ISpObjectTokenCategory *iface,
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
struct token_with_score
|
||||
{
|
||||
ISpObjectToken *token;
|
||||
uint64_t score;
|
||||
};
|
||||
|
||||
struct token_enum
|
||||
{
|
||||
ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface;
|
||||
|
@ -566,8 +577,8 @@ struct token_enum
|
|||
|
||||
BOOL init;
|
||||
WCHAR *req, *opt;
|
||||
ULONG count;
|
||||
HKEY key;
|
||||
struct token_with_score *tokens;
|
||||
ULONG capacity, count;
|
||||
DWORD index;
|
||||
};
|
||||
|
||||
|
@ -582,8 +593,12 @@ static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface,
|
|||
{
|
||||
struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
|
||||
ISpObjectTokenEnumBuilder *builder;
|
||||
struct token_enum *tokenenum;
|
||||
struct data_key *this_data_key;
|
||||
HKEY tokens_key;
|
||||
DWORD count, max_subkey_size, root_len, token_id_size;
|
||||
DWORD size, i;
|
||||
WCHAR *token_id = NULL;
|
||||
ISpObjectToken *token = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE( "(%p)->(%s %s %p)\n", This, debugstr_w( req ), debugstr_w( opt ), enum_tokens );
|
||||
|
@ -599,12 +614,43 @@ static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface,
|
|||
|
||||
this_data_key = impl_from_ISpRegDataKey( This->data_key );
|
||||
|
||||
tokenenum = impl_from_ISpObjectTokenEnumBuilder( builder );
|
||||
|
||||
if (!RegOpenKeyExW( this_data_key->key, L"Tokens", 0, KEY_ALL_ACCESS, &tokenenum->key ))
|
||||
if (!RegOpenKeyExW( this_data_key->key, L"Tokens", 0, KEY_ALL_ACCESS, &tokens_key ))
|
||||
{
|
||||
RegQueryInfoKeyW(tokenenum->key, NULL, NULL, NULL, &tokenenum->count, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
RegQueryInfoKeyW( tokens_key, NULL, NULL, NULL, &count, &max_subkey_size, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL );
|
||||
max_subkey_size++;
|
||||
|
||||
root_len = wcslen( This->id );
|
||||
token_id_size = root_len + sizeof("\\Tokens\\") + max_subkey_size;
|
||||
token_id = malloc( token_id_size * sizeof(WCHAR) );
|
||||
if (!token_id)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto fail;
|
||||
}
|
||||
root_len = swprintf( token_id, token_id_size, L"%ls%lsTokens\\",
|
||||
This->id, This->id[root_len - 1] == L'\\' ? L"" : L"\\" );
|
||||
|
||||
for ( i = 0; i < count; i++ )
|
||||
{
|
||||
size = max_subkey_size;
|
||||
hr = HRESULT_FROM_WIN32(RegEnumKeyExW( tokens_key, i, token_id + root_len, &size, NULL, NULL, NULL, NULL ));
|
||||
if (FAILED(hr)) goto fail;
|
||||
|
||||
hr = token_create( NULL, &IID_ISpObjectToken, (void **)&token );
|
||||
if (FAILED(hr)) goto fail;
|
||||
|
||||
hr = ISpObjectToken_SetId( token, NULL, token_id, FALSE );
|
||||
if (FAILED(hr)) goto fail;
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_AddTokens( builder, 1, &token );
|
||||
if (FAILED(hr)) goto fail;
|
||||
ISpObjectToken_Release( token );
|
||||
token = NULL;
|
||||
}
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_Sort( builder, NULL );
|
||||
if (FAILED(hr)) goto fail;
|
||||
}
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_QueryInterface( builder, &IID_IEnumSpObjectTokens,
|
||||
|
@ -612,6 +658,8 @@ static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface,
|
|||
|
||||
fail:
|
||||
ISpObjectTokenEnumBuilder_Release( builder );
|
||||
if ( token ) ISpObjectToken_Release( token );
|
||||
free( token_id );
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -693,6 +741,7 @@ HRESULT token_category_create( IUnknown *outer, REFIID iid, void **obj )
|
|||
This->ISpObjectTokenCategory_iface.lpVtbl = &token_category_vtbl;
|
||||
This->ref = 1;
|
||||
This->data_key = NULL;
|
||||
This->id = NULL;
|
||||
|
||||
hr = ISpObjectTokenCategory_QueryInterface( &This->ISpObjectTokenCategory_iface, iid, obj );
|
||||
|
||||
|
@ -739,10 +788,16 @@ static ULONG WINAPI token_enum_Release( ISpObjectTokenEnumBuilder *iface )
|
|||
|
||||
if (!ref)
|
||||
{
|
||||
if (This->key)
|
||||
RegCloseKey(This->key);
|
||||
free( This->req );
|
||||
free( This->opt );
|
||||
if (This->tokens)
|
||||
{
|
||||
ULONG i;
|
||||
for ( i = 0; i < This->count; i++ )
|
||||
if ( This->tokens[i].token )
|
||||
ISpObjectToken_Release( This->tokens[i].token );
|
||||
free( This->tokens );
|
||||
}
|
||||
free( This );
|
||||
}
|
||||
|
||||
|
@ -754,64 +809,23 @@ static HRESULT WINAPI token_enum_Next( ISpObjectTokenEnumBuilder *iface,
|
|||
ULONG *fetched )
|
||||
{
|
||||
struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
|
||||
struct object_token *object;
|
||||
HRESULT hr;
|
||||
DWORD retCode;
|
||||
WCHAR *subkey_name;
|
||||
HKEY sub_key;
|
||||
DWORD size;
|
||||
ISpRegDataKey *data_key;
|
||||
ULONG i;
|
||||
|
||||
TRACE( "(%p)->(%lu %p %p)\n", This, num, tokens, fetched );
|
||||
|
||||
if (!This->init) return SPERR_UNINITIALIZED;
|
||||
if (fetched) *fetched = 0;
|
||||
if (!fetched && num != 1) return E_POINTER;
|
||||
if (!tokens) return E_POINTER;
|
||||
|
||||
*tokens = NULL;
|
||||
|
||||
RegQueryInfoKeyW( This->key, NULL, NULL, NULL, NULL, &size, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
size = (size+1) * sizeof(WCHAR);
|
||||
subkey_name = malloc( size );
|
||||
if (!subkey_name)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
retCode = RegEnumKeyExW( This->key, This->index, subkey_name, &size, NULL, NULL, NULL, NULL );
|
||||
if (retCode != ERROR_SUCCESS)
|
||||
for ( i = 0; i < num && This->index < This->count; i++, This->index++ )
|
||||
{
|
||||
free( subkey_name );
|
||||
return S_FALSE;
|
||||
ISpObjectToken_AddRef( This->tokens[This->index].token );
|
||||
tokens[i] = This->tokens[This->index].token;
|
||||
}
|
||||
|
||||
This->index++;
|
||||
if (fetched) *fetched = i;
|
||||
|
||||
if (RegOpenKeyExW( This->key, subkey_name, 0, KEY_READ, &sub_key ) != ERROR_SUCCESS)
|
||||
{
|
||||
free( subkey_name );
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
hr = create_data_key_with_hkey( sub_key, &data_key );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
free( subkey_name );
|
||||
RegCloseKey( sub_key );
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = token_create( NULL, &IID_ISpObjectToken, (void**)tokens );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
free( subkey_name );
|
||||
ISpRegDataKey_Release( data_key );
|
||||
return hr;
|
||||
}
|
||||
|
||||
object = impl_from_ISpObjectToken( *tokens );
|
||||
object->data_key = data_key;
|
||||
object->token_id = subkey_name;
|
||||
|
||||
if (fetched) *fetched = 1;
|
||||
return hr;
|
||||
return i == num ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI token_enum_Skip( ISpObjectTokenEnumBuilder *iface,
|
||||
|
@ -838,63 +852,18 @@ static HRESULT WINAPI token_enum_Item( ISpObjectTokenEnumBuilder *iface,
|
|||
ULONG index, ISpObjectToken **token )
|
||||
{
|
||||
struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
|
||||
struct object_token *object;
|
||||
ISpObjectToken *subtoken;
|
||||
HRESULT hr;
|
||||
WCHAR *subkey;
|
||||
DWORD size;
|
||||
LONG ret;
|
||||
HKEY key;
|
||||
ISpRegDataKey *data_key;
|
||||
|
||||
TRACE( "%p, %lu, %p\n", This, index, token );
|
||||
TRACE( "(%p)->(%lu %p)\n", This, index, token );
|
||||
|
||||
if (!This->init)
|
||||
return SPERR_UNINITIALIZED;
|
||||
if (!This->init) return SPERR_UNINITIALIZED;
|
||||
|
||||
RegQueryInfoKeyW(This->key, NULL, NULL, NULL, NULL, &size, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
size = (size+1) * sizeof(WCHAR);
|
||||
subkey = malloc( size );
|
||||
if (!subkey)
|
||||
return E_OUTOFMEMORY;
|
||||
if (!token) return E_POINTER;
|
||||
if (index >= This->count) return SPERR_NO_MORE_ITEMS;
|
||||
|
||||
ret = RegEnumKeyExW(This->key, index, subkey, &size, NULL, NULL, NULL, NULL);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
{
|
||||
free( subkey );
|
||||
return HRESULT_FROM_WIN32(ret);
|
||||
}
|
||||
ISpObjectToken_AddRef( This->tokens[index].token );
|
||||
*token = This->tokens[index].token;
|
||||
|
||||
ret = RegOpenKeyExW (This->key, subkey, 0, KEY_READ, &key);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
{
|
||||
free( subkey );
|
||||
return HRESULT_FROM_WIN32(ret);
|
||||
}
|
||||
|
||||
hr = create_data_key_with_hkey( key, &data_key );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
free( subkey );
|
||||
RegCloseKey( key );
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = token_create( NULL, &IID_ISpObjectToken, (void**)&subtoken );
|
||||
if (FAILED(hr))
|
||||
{
|
||||
free( subkey );
|
||||
ISpRegDataKey_Release( data_key );
|
||||
return hr;
|
||||
}
|
||||
|
||||
object = impl_from_ISpObjectToken( subtoken );
|
||||
object->data_key = data_key;
|
||||
object->token_id = subkey;
|
||||
|
||||
*token = subtoken;
|
||||
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI token_enum_GetCount( ISpObjectTokenEnumBuilder *iface,
|
||||
|
@ -939,11 +908,60 @@ out_of_mem:
|
|||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static BOOL grow_tokens_array( struct token_enum *This )
|
||||
{
|
||||
struct token_with_score *new_tokens;
|
||||
ULONG new_cap;
|
||||
|
||||
if (This->count < This->capacity) return TRUE;
|
||||
|
||||
if (This->capacity > 0)
|
||||
{
|
||||
new_cap = This->capacity * 2;
|
||||
new_tokens = realloc( This->tokens, new_cap * sizeof(*new_tokens) );
|
||||
}
|
||||
else
|
||||
{
|
||||
new_cap = 1;
|
||||
new_tokens = malloc( sizeof(*new_tokens) );
|
||||
}
|
||||
|
||||
if (!new_tokens) return FALSE;
|
||||
|
||||
This->tokens = new_tokens;
|
||||
This->capacity = new_cap;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI token_enum_AddTokens( ISpObjectTokenEnumBuilder *iface,
|
||||
ULONG num, ISpObjectToken **tokens )
|
||||
{
|
||||
FIXME( "stub\n" );
|
||||
return E_NOTIMPL;
|
||||
struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
|
||||
ULONG i;
|
||||
|
||||
TRACE( "(%p)->(%lu %p)\n", iface, num, tokens );
|
||||
|
||||
if (!This->init) return SPERR_UNINITIALIZED;
|
||||
if (!tokens) return E_POINTER;
|
||||
|
||||
if (This->req || This->opt)
|
||||
{
|
||||
FIXME( "filtering and sorting of tokens is not implemented\n" );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
for ( i = 0; i < num; i++ )
|
||||
{
|
||||
if (!tokens[i]) return E_POINTER;
|
||||
|
||||
if (!grow_tokens_array( This )) return E_OUTOFMEMORY;
|
||||
ISpObjectToken_AddRef( tokens[i] );
|
||||
This->tokens[This->count].token = tokens[i];
|
||||
This->tokens[This->count].score = 0;
|
||||
This->count++;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI token_enum_AddTokensFromDataKey( ISpObjectTokenEnumBuilder *iface,
|
||||
|
@ -964,8 +982,26 @@ static HRESULT WINAPI token_enum_AddTokensFromTokenEnum( ISpObjectTokenEnumBuild
|
|||
static HRESULT WINAPI token_enum_Sort( ISpObjectTokenEnumBuilder *iface,
|
||||
LPCWSTR first )
|
||||
{
|
||||
FIXME( "stub\n" );
|
||||
return E_NOTIMPL;
|
||||
struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
|
||||
|
||||
FIXME( "(%p)->(%s): semi-stub\n", iface, debugstr_w(first) );
|
||||
|
||||
if (!This->init) return SPERR_UNINITIALIZED;
|
||||
if (!This->tokens) return S_OK;
|
||||
|
||||
if (first)
|
||||
{
|
||||
FIXME( "first != NULL is not implemented.\n" );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (This->opt)
|
||||
{
|
||||
FIXME( "sorting with optional attributes is not implemented.\n" );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const struct ISpObjectTokenEnumBuilderVtbl token_enum_vtbl =
|
||||
|
@ -997,8 +1033,8 @@ HRESULT token_enum_create( IUnknown *outer, REFIID iid, void **obj )
|
|||
This->req = NULL;
|
||||
This->opt = NULL;
|
||||
This->init = FALSE;
|
||||
This->count = 0;
|
||||
This->key = NULL;
|
||||
This->tokens = NULL;
|
||||
This->capacity = This->count = 0;
|
||||
This->index = 0;
|
||||
|
||||
hr = ISpObjectTokenEnumBuilder_QueryInterface( &This->ISpObjectTokenEnumBuilder_iface, iid, obj );
|
||||
|
|
Loading…
Reference in a new issue