Signed-off-by: Myah Caron qsniyg@protonmail.com --- Progressing towards fixing #49641. This patch alone doesn't fix the issue, but I'm not sure when I'll get to the next patch, so I'm sending this one in by itself for the moment.
dlls/sapi/tests/token.c | 253 ++++++++++++++++++++++++++++++++++++++++ dlls/sapi/token.c | 96 ++++++++++++++- 2 files changed, 345 insertions(+), 4 deletions(-)
diff --git a/dlls/sapi/tests/token.c b/dlls/sapi/tests/token.c index 9f6689b83f..4d12ddb1c9 100644 --- a/dlls/sapi/tests/token.c +++ b/dlls/sapi/tests/token.c @@ -83,6 +83,254 @@ static void test_token_category(void) ISpObjectTokenCategory_Release( cat ); }
+static void backup_speech(HKEY root) +{ + LONG res; + HKEY key; + + res = RegDeleteTreeW( root, L"SOFTWARE\Microsoft\Speech_winetest" ); + ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + res = RegCreateKeyW( root, L"SOFTWARE\Microsoft\Speech_winetest", &key ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + RegCopyTreeW( root, L"SOFTWARE\Microsoft\Speech", key ); + ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + RegCloseKey(key); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); +} + +static void restore_speech(HKEY root, BOOL delete_backup) +{ + LONG res; + HKEY key; + + res = RegDeleteTreeW( root, L"SOFTWARE\Microsoft\Speech" ); + ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + res = RegCreateKeyW( root, L"SOFTWARE\Microsoft\Speech", &key ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + RegCopyTreeW( root, L"SOFTWARE\Microsoft\Speech_winetest", key ); + ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + RegCloseKey(key); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + if (delete_backup) { + res = RegDeleteTreeW( root, L"SOFTWARE\Microsoft\Speech_winetest" ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + } +} + +static void test_token_default_id(void) +{ + ISpObjectTokenCategory *cat; + HRESULT hr; + LONG res; + HKEY key; + LPWSTR token_id = NULL; + WCHAR regvalue[512]; + WCHAR regvalue2[512]; + DWORD regvalue_size = sizeof( regvalue ); + + hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpObjectTokenCategory, (void **)&cat ); + ok( hr == S_OK, "got %08x\n", hr ); + + token_id = (LPWSTR)0xdeadbeef; + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id ); + ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr ); + ok( token_id == (LPWSTR)0xdeadbeef, "got %p\n", token_id ); + + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, NULL ); + ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr ); + + /* if missing, Get/SetDefaultTokenId should initialize HKEY_LOCAL_USER's + SOFTWARE\Microsoft\Speech\AudioOutput */ + res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" ); + ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE ); + ok( hr == S_OK, "got %08x\n", hr ); + + res = RegOpenKeyExW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key ); + ok( res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, NULL ); + ok( hr == E_POINTER, "got %08x\n", hr ); + + res = RegOpenKeyExW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key ); + ok( res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + + token_id = (LPWSTR)0xdeadbeef; + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id ); + + regvalue_size = sizeof( regvalue ); + res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", + L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + ok( !wcscmp(regvalue, token_id), + "GetDefaultTokenId (%s) should be equal to the DefaultTokenId key (%s)\n", + wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) ); + CoTaskMemFree(token_id); + + regvalue_size = sizeof( regvalue ); + res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", + L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + regvalue_size = sizeof( regvalue2 ); + res = RegGetValueW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput", + L"DefaultdefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value2, ®value_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + ok( !wcscmp(regvalue, regvalue2), + "DefaultTokenId (%s) should be equal to the DefaultdefaultTokenId key (%s)\n", + wine_dbgstr_w(regvalue), wine_dbgstr_w(regvalue2) ); + + /* todo: test subkeys */ + + res = RegOpenKeyExW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + wcscpy(regvalue, L"bogus"); + regvalue_size = (wcslen(regvalue) + 1) * sizeof( WCHAR ); + res = RegSetValueExW( key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + RegCloseKey(key); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + token_id = (LPWSTR)0xdeadbeef; + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id ); + todo_wine ok( wcscmp(regvalue, token_id), + "GetDefaultTokenId (%s) should not be equal to the bogus DefaultTokenId key (%s)\n", + wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) ); + CoTaskMemFree(token_id); + + /* todo: add more tests for the resulting token_id */ + + restore_speech( HKEY_LOCAL_MACHINE, FALSE ); + token_id = (LPWSTR)0xdeadbeef; + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id ); + todo_wine ok( hr == 0x800703fa, "got %08x\n", hr ); + todo_wine ok( token_id == (LPWSTR)0xdeadbeef, "got %p\n", token_id ); + + ISpObjectTokenCategory_Release( cat ); + + hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpObjectTokenCategory, (void **)&cat ); + ok( hr == S_OK, "got %08x\n", hr ); + + res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + res = RegDeleteTreeW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput" ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE ); + todo_wine ok( hr == SPERR_NOT_FOUND, "got %08x\n", hr ); + + restore_speech( HKEY_CURRENT_USER, FALSE ); + + hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE ); + todo_wine ok( hr == SPERR_NOT_FOUND, "got %08x\n", hr ); + + restore_speech( HKEY_LOCAL_MACHINE, FALSE ); + + hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE ); + ok( hr == S_OK, "got %08x\n", hr ); + + res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" ); + ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res ); + res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + wcscpy(regvalue, L"bogus"); + regvalue_size = (wcslen(regvalue) + 1) * sizeof( WCHAR ); + res = RegSetValueExW( key, L"DefaultdefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + RegCloseKey(key); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + token_id = (LPWSTR)0xdeadbeef; + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id ); + todo_wine ok( wcscmp(regvalue, token_id), + "GetDefaultTokenId (%s) should not be equal to the bogus DefaultdefaultTokenId key (%s)\n", + wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) ); + CoTaskMemFree(token_id); + + /* todo: test valid DefaultdefaultTokenId values */ + + ISpObjectTokenCategory_Release( cat ); + + res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + res = RegDeleteValueW( key, L"DefaultdefaultTokenId" ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + RegCloseKey(key); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + + hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpObjectTokenCategory, (void **)&cat ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE ); + ok( hr == S_OK, "got %08x\n", hr ); + + token_id = (LPWSTR)0xdeadbeef; + hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id ); + todo_wine ok( hr == S_OK, "got %08x\n", hr ); + todo_wine ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id ); + if (token_id != (LPWSTR)0xdeadbeef) + CoTaskMemFree(token_id); + + ISpObjectTokenCategory_Release( cat ); + restore_speech( HKEY_LOCAL_MACHINE, FALSE ); + hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER, + &IID_ISpObjectTokenCategory, (void **)&cat ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, NULL ); + ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr ); + + hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + wcscpy(regvalue, L"deadbeef"); + hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, regvalue ); + ok( hr == S_OK, "got %08x\n", hr ); + + regvalue_size = sizeof( regvalue ); + res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", + L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + ok( !wcscmp(regvalue, L"deadbeef"), + "DefaultTokenId in registry (%s) should be equal to the set default token id (%s)\n", + wine_dbgstr_w(regvalue), wine_dbgstr_w(L"deadbeef") ); + + res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" ); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + wcscpy(regvalue, L"deadbeef"); + hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, regvalue ); + ok( hr == S_OK, "got %08x\n", hr ); + regvalue_size = sizeof( regvalue ); + res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", + L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size); + ok( res == ERROR_SUCCESS, "got %08x\n", res ); + ok( !wcscmp(regvalue, L"deadbeef"), + "GetDefaultTokenId (%s) should be equal to the set DefaultTokenId key (%s)\n", + wine_dbgstr_w(token_id), wine_dbgstr_w(L"deadbeef") ); + + ISpObjectTokenCategory_Release( cat ); +} + static void test_token_enum(void) { ISpObjectTokenEnumBuilder *token_enum; @@ -121,6 +369,11 @@ START_TEST(token) CoInitialize( NULL ); test_data_key(); test_token_category(); + backup_speech( HKEY_LOCAL_MACHINE ); + backup_speech( HKEY_CURRENT_USER ); + test_token_default_id(); + restore_speech( HKEY_CURRENT_USER, TRUE ); + restore_speech( HKEY_LOCAL_MACHINE, TRUE ); test_token_enum(); CoUninitialize(); } diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c index d2b70c95cf..78c5d2cdd5 100644 --- a/dlls/sapi/token.c +++ b/dlls/sapi/token.c @@ -232,6 +232,7 @@ struct token_category LONG ref;
ISpRegDataKey *data_key; + WCHAR *subkey; };
static struct token_category *impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory *iface ) @@ -421,6 +422,8 @@ static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface, res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); if (res) return SPERR_INVALID_REGISTRY_KEY;
+ This->subkey = _wcsdup(subkey); + hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_ALL, &IID_ISpRegDataKey, (void **)&This->data_key ); if (FAILED(hr)) goto fail; @@ -479,18 +482,103 @@ fail: return hr; }
+static HRESULT get_user_speech_key( struct token_category *This, HKEY* key ) +{ + LONG res; + WCHAR regvalue[512]; + DWORD regvalue_size = sizeof( regvalue ); + + res = RegOpenKeyExW( HKEY_CURRENT_USER, This->subkey, 0, KEY_ALL_ACCESS, key ); + if (res == ERROR_SUCCESS) { + return S_OK; + } + + FIXME( "(%p): semi-stub\n", This ); + + res = RegCreateKeyW( HKEY_CURRENT_USER, This->subkey, key ); + if (res != ERROR_SUCCESS) { + /* probably not the correct return value */ + FIXME( "returning %08x\n", res ); + return res; + } + + res = RegGetValueW( HKEY_LOCAL_MACHINE, This->subkey, L"DefaultdefaultTokenId", + RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size); + if (res == ERROR_SUCCESS) { + RegSetValueExW( *key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size); + } + + return S_OK; +} + static HRESULT WINAPI token_category_SetDefaultTokenId( ISpObjectTokenCategory *iface, LPCWSTR id ) { - FIXME( "stub\n" ); - return E_NOTIMPL; + struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); + HRESULT hr; + LONG res; + HKEY key; + + FIXME( "(%p)->(%s): semi-stub\n", iface, debugstr_w(id) ); + + if (!This->data_key) + return SPERR_UNINITIALIZED; + + if (!id) + return E_INVALIDARG; + + hr = get_user_speech_key( This, &key ); + if (FAILED(hr)) return hr; + + res = RegSetValueExW( key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)id, + wcslen( id) * sizeof( WCHAR )); + if (res != ERROR_SUCCESS) { + /* probably not the correct return value */ + FIXME( "unable to set DefaultTokenId, returning S_FALSE\n" ); + RegCloseKey( key ); + return S_FALSE; + } + + RegCloseKey( key ); + + return S_OK; }
static HRESULT WINAPI token_category_GetDefaultTokenId( ISpObjectTokenCategory *iface, LPWSTR *id ) { - FIXME( "stub\n" ); - return E_NOTIMPL; + struct token_category *This = impl_from_ISpObjectTokenCategory( iface ); + HRESULT hr; + LONG res; + HKEY key; + WCHAR regvalue[512]; + DWORD regvalue_size = sizeof( regvalue ); + + FIXME( "(%p)->(%p): semi-stub\n", iface, id ); + + if (!This->data_key) + return SPERR_UNINITIALIZED; + + if (!id) + return E_POINTER; + + hr = get_user_speech_key( This, &key ); + if (FAILED(hr)) return hr; + + res = RegGetValueW( key, NULL, L"DefaultTokenId", RRF_RT_REG_SZ, NULL, + ®value, ®value_size); + if (res != ERROR_SUCCESS) { + FIXME( "DefaultTokenId is missing, returning S_FALSE\n" ); + RegCloseKey( key ); + return S_FALSE; + } + + *id = CoTaskMemAlloc( regvalue_size ); + wcscpy( *id, regvalue ); + + RegCloseKey( key ); + + return S_OK; }
const struct ISpObjectTokenCategoryVtbl token_category_vtbl = -- 2.27.0
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=76408
Your paranoid android.
=== w2008s64 (32 bit report) ===
sapi: token.c:169: Test failed: got 8004503a token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 0390:token: unhandled exception c0000005 at 74CB36C6
=== w8 (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00571208 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w8adm (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00322228 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1507 (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 007EBAE0 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809 (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00A4E2E8 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809_2scr (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 006D2BD0 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809_ar (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 008752A8 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809_he (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 008A1128 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809_ja (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00A338C8 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809_zh_CN (32 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00975570 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w2008s64 (64 bit report) ===
sapi: token.c:169: Test failed: got 8004503a token.c:170: Test failed: got 00000000DEADBEEF token.c:175: Test failed: got 00000002 0390:token: unhandled exception c0000005 at 000007FEFDF3688B
=== w864 (64 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00000000005506D0 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1507 (64 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 00000000005C6070 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== w1064v1809 (64 bit report) ===
sapi: token.c:110: Test failed: got 00000005 token.c:218: Test failed: got 00000000 token.c:219: Test failed: got 000000000078E840 token.c:230: Test failed: got 00000005 token.c:233: Test failed: got 00000000 token.c:238: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:243: Test failed: got 80045002 token.c:110: Test failed: got 00000005 token.c:110: Test failed: got 00000005 token.c:123: Test failed: got 00000005
=== debiant (32 bit report) ===
sapi: token.c:156: Test failed: got 80045040 token.c:162: Test failed: got 80045001 token.c:169: Test failed: got 80045001 token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 Unhandled exception: page fault on read access to 0xdeadbeef in 32-bit code (0x7e9d14ad).
Report validation errors: sapi:token crashed (c0000005)
=== debiant (32 bit French report) ===
sapi: token.c:156: Test failed: got 80045040 token.c:162: Test failed: got 80045001 token.c:169: Test failed: got 80045001 token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 Unhandled exception: page fault on read access to 0xdeadbeef in 32-bit code (0x7e9d14ad).
Report validation errors: sapi:token crashed (c0000005)
=== debiant (32 bit Japanese:Japan report) ===
sapi: token.c:156: Test failed: got 80045040 token.c:162: Test failed: got 80045001 token.c:169: Test failed: got 80045001 token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 Unhandled exception: page fault on read access to 0xdeadbeef in 32-bit code (0x7eace4ad).
Report validation errors: sapi:token crashed (c0000005)
=== debiant (32 bit Chinese:China report) ===
sapi: token.c:156: Test failed: got 80045040 token.c:162: Test failed: got 80045001 token.c:169: Test failed: got 80045001 token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 Unhandled exception: page fault on read access to 0xdeadbeef in 32-bit code (0x7e9484ad).
Report validation errors: sapi:token crashed (c0000005)
=== debiant (32 bit WoW report) ===
sapi: token.c:156: Test failed: got 80045040 token.c:162: Test failed: got 80045001 token.c:169: Test failed: got 80045001 token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 Unhandled exception: page fault on read access to 0xdeadbeef in 32-bit code (0x7e9d14ad).
Report validation errors: sapi:token crashed (c0000005)
=== debiant (64 bit WoW report) ===
sapi: token.c:156: Test failed: got 80045040 token.c:162: Test failed: got 80045001 token.c:169: Test failed: got 80045001 token.c:170: Test failed: got DEADBEEF token.c:175: Test failed: got 00000002 Unhandled exception: page fault on read access to 0xdeadbeef in 32-bit code (0x7e9d14ad).
Report validation errors: sapi:token crashed (c0000005)
Sorry I forgot to test under windows, I had only tested with the native dll from winetricks.
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Saturday, August 1, 2020 12:52 PM, Myah Caron qsniyg@protonmail.com wrote:
Signed-off-by: Myah Caron qsniyg@protonmail.com
Progressing towards fixing #49641. This patch alone doesn't fix the issue, but I'm not sure when I'll get to the next patch, so I'm sending this one in by itself for the moment.
dlls/sapi/tests/token.c | 253 ++++++++++++++++++++++++++++++++++++++++ dlls/sapi/token.c | 96 ++++++++++++++- 2 files changed, 345 insertions(+), 4 deletions(-)
diff --git a/dlls/sapi/tests/token.c b/dlls/sapi/tests/token.c index 9f6689b83f..4d12ddb1c9 100644 --- a/dlls/sapi/tests/token.c +++ b/dlls/sapi/tests/token.c @@ -83,6 +83,254 @@ static void test_token_category(void) ISpObjectTokenCategory_Release( cat ); }
+static void backup_speech(HKEY root) +{
LONG res;
HKEY key;
res = RegDeleteTreeW( root, L"SOFTWARE\Microsoft\Speech_winetest" );
ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
res = RegCreateKeyW( root, L"SOFTWARE\Microsoft\Speech_winetest", &key );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
RegCopyTreeW( root, L"SOFTWARE\Microsoft\Speech", key );
ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
RegCloseKey(key);
ok( res == ERROR_SUCCESS, "got %08x\n", res ); +}
+static void restore_speech(HKEY root, BOOL delete_backup) +{
LONG res;
HKEY key;
res = RegDeleteTreeW( root, L"SOFTWARE\Microsoft\Speech" );
ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
res = RegCreateKeyW( root, L"SOFTWARE\Microsoft\Speech", &key );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
RegCopyTreeW( root, L"SOFTWARE\Microsoft\Speech_winetest", key );
ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
RegCloseKey(key);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
if (delete_backup) {
res = RegDeleteTreeW( root, L"SOFTWARE\\\\Microsoft\\\\Speech_winetest" );
ok( res == ERROR_SUCCESS, "got %08x\\n", res );
} +}
+static void test_token_default_id(void) +{
ISpObjectTokenCategory *cat;
HRESULT hr;
LONG res;
HKEY key;
LPWSTR token_id = NULL;
WCHAR regvalue[512];
WCHAR regvalue2[512];
DWORD regvalue_size = sizeof( regvalue );
hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
&IID_ISpObjectTokenCategory, (void **)&cat );
ok( hr == S_OK, "got %08x\n", hr );
token_id = (LPWSTR)0xdeadbeef;
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr );
ok( token_id == (LPWSTR)0xdeadbeef, "got %p\n", token_id );
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, NULL );
ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr );
/* if missing, Get/SetDefaultTokenId should initialize HKEY_LOCAL_USER's
SOFTWARE\\Microsoft\\Speech\\AudioOutput */
res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" );
ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE );
ok( hr == S_OK, "got %08x\n", hr );
res = RegOpenKeyExW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key );
ok( res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, NULL );
ok( hr == E_POINTER, "got %08x\n", hr );
res = RegOpenKeyExW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key );
ok( res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
token_id = (LPWSTR)0xdeadbeef;
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
ok( hr == S_OK, "got %08x\n", hr );
ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
regvalue_size = sizeof( regvalue );
res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput",
L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
ok( !wcscmp(regvalue, token_id),
"GetDefaultTokenId (%s) should be equal to the DefaultTokenId key (%s)\\n",
wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) );
CoTaskMemFree(token_id);
regvalue_size = sizeof( regvalue );
res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput",
L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
regvalue_size = sizeof( regvalue2 );
res = RegGetValueW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput",
L"DefaultdefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value2, ®value_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
ok( !wcscmp(regvalue, regvalue2),
"DefaultTokenId (%s) should be equal to the DefaultdefaultTokenId key (%s)\\n",
wine_dbgstr_w(regvalue), wine_dbgstr_w(regvalue2) );
/* todo: test subkeys */
res = RegOpenKeyExW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
wcscpy(regvalue, L"bogus");
regvalue_size = (wcslen(regvalue) + 1) * sizeof( WCHAR );
res = RegSetValueExW( key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
RegCloseKey(key);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
token_id = (LPWSTR)0xdeadbeef;
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
ok( hr == S_OK, "got %08x\n", hr );
ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
todo_wine ok( wcscmp(regvalue, token_id),
"GetDefaultTokenId (%s) should not be equal to the bogus DefaultTokenId key (%s)\\n",
wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) );
CoTaskMemFree(token_id);
/* todo: add more tests for the resulting token_id */
restore_speech( HKEY_LOCAL_MACHINE, FALSE );
token_id = (LPWSTR)0xdeadbeef;
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
todo_wine ok( hr == 0x800703fa, "got %08x\n", hr );
todo_wine ok( token_id == (LPWSTR)0xdeadbeef, "got %p\n", token_id );
ISpObjectTokenCategory_Release( cat );
hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
&IID_ISpObjectTokenCategory, (void **)&cat );
ok( hr == S_OK, "got %08x\n", hr );
res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
res = RegDeleteTreeW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput" );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE );
todo_wine ok( hr == SPERR_NOT_FOUND, "got %08x\n", hr );
restore_speech( HKEY_CURRENT_USER, FALSE );
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE );
todo_wine ok( hr == SPERR_NOT_FOUND, "got %08x\n", hr );
restore_speech( HKEY_LOCAL_MACHINE, FALSE );
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE );
ok( hr == S_OK, "got %08x\n", hr );
res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" );
ok( res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND, "got %08x\n", res );
res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
wcscpy(regvalue, L"bogus");
regvalue_size = (wcslen(regvalue) + 1) * sizeof( WCHAR );
res = RegSetValueExW( key, L"DefaultdefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
RegCloseKey(key);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
token_id = (LPWSTR)0xdeadbeef;
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
ok( hr == S_OK, "got %08x\n", hr );
ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
todo_wine ok( wcscmp(regvalue, token_id),
"GetDefaultTokenId (%s) should not be equal to the bogus DefaultdefaultTokenId key (%s)\\n",
wine_dbgstr_w(token_id), wine_dbgstr_w(regvalue) );
CoTaskMemFree(token_id);
/* todo: test valid DefaultdefaultTokenId values */
ISpObjectTokenCategory_Release( cat );
res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
res = RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\Microsoft\Speech\AudioOutput", 0, KEY_ALL_ACCESS, &key );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
res = RegDeleteValueW( key, L"DefaultdefaultTokenId" );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
RegCloseKey(key);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
&IID_ISpObjectTokenCategory, (void **)&cat );
ok( hr == S_OK, "got %08x\n", hr );
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE );
ok( hr == S_OK, "got %08x\n", hr );
token_id = (LPWSTR)0xdeadbeef;
hr = ISpObjectTokenCategory_GetDefaultTokenId( cat, &token_id );
todo_wine ok( hr == S_OK, "got %08x\n", hr );
todo_wine ok( token_id != (LPWSTR)0xdeadbeef && token_id != NULL, "got %p\n", token_id );
if (token_id != (LPWSTR)0xdeadbeef)
CoTaskMemFree(token_id);
ISpObjectTokenCategory_Release( cat );
restore_speech( HKEY_LOCAL_MACHINE, FALSE );
hr = CoCreateInstance( &CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
&IID_ISpObjectTokenCategory, (void **)&cat );
ok( hr == S_OK, "got %08x\n", hr );
hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, NULL );
ok( hr == SPERR_UNINITIALIZED, "got %08x\n", hr );
hr = ISpObjectTokenCategory_SetId( cat, SPCAT_AUDIOOUT, FALSE );
ok( hr == S_OK, "got %08x\n", hr );
hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
wcscpy(regvalue, L"deadbeef");
hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, regvalue );
ok( hr == S_OK, "got %08x\n", hr );
regvalue_size = sizeof( regvalue );
res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput",
L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
ok( !wcscmp(regvalue, L"deadbeef"),
"DefaultTokenId in registry (%s) should be equal to the set default token id (%s)\\n",
wine_dbgstr_w(regvalue), wine_dbgstr_w(L"deadbeef") );
res = RegDeleteTreeW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput" );
ok( res == ERROR_SUCCESS, "got %08x\n", res );
wcscpy(regvalue, L"deadbeef");
hr = ISpObjectTokenCategory_SetDefaultTokenId( cat, regvalue );
ok( hr == S_OK, "got %08x\n", hr );
regvalue_size = sizeof( regvalue );
res = RegGetValueW( HKEY_CURRENT_USER, L"SOFTWARE\Microsoft\Speech\AudioOutput",
L"DefaultTokenId", RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size);
ok( res == ERROR_SUCCESS, "got %08x\n", res );
ok( !wcscmp(regvalue, L"deadbeef"),
"GetDefaultTokenId (%s) should be equal to the set DefaultTokenId key (%s)\\n",
wine_dbgstr_w(token_id), wine_dbgstr_w(L"deadbeef") );
ISpObjectTokenCategory_Release( cat ); +}
static void test_token_enum(void) { ISpObjectTokenEnumBuilder *token_enum; @@ -121,6 +369,11 @@ START_TEST(token) CoInitialize( NULL ); test_data_key(); test_token_category();
backup_speech( HKEY_LOCAL_MACHINE );
backup_speech( HKEY_CURRENT_USER );
test_token_default_id();
restore_speech( HKEY_CURRENT_USER, TRUE );
restore_speech( HKEY_LOCAL_MACHINE, TRUE ); test_token_enum(); CoUninitialize(); } diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c index d2b70c95cf..78c5d2cdd5 100644 --- a/dlls/sapi/token.c +++ b/dlls/sapi/token.c @@ -232,6 +232,7 @@ struct token_category LONG ref;
ISpRegDataKey *data_key;
WCHAR *subkey; };
static struct token_category *impl_from_ISpObjectTokenCategory( ISpObjectTokenCategory *iface ) @@ -421,6 +422,8 @@ static HRESULT WINAPI token_category_SetId( ISpObjectTokenCategory *iface, res = RegOpenKeyExW( root, subkey, 0, KEY_ALL_ACCESS, &key ); if (res) return SPERR_INVALID_REGISTRY_KEY;
This->subkey = _wcsdup(subkey);
hr = CoCreateInstance( &CLSID_SpDataKey, NULL, CLSCTX_ALL, &IID_ISpRegDataKey, (void **)&This->data_key ); if (FAILED(hr)) goto fail; @@ -479,18 +482,103 @@ fail: return hr; }
+static HRESULT get_user_speech_key( struct token_category This, HKEY key ) +{
LONG res;
WCHAR regvalue[512];
DWORD regvalue_size = sizeof( regvalue );
res = RegOpenKeyExW( HKEY_CURRENT_USER, This->subkey, 0, KEY_ALL_ACCESS, key );
if (res == ERROR_SUCCESS) {
return S_OK;
}
FIXME( "(%p): semi-stub\n", This );
res = RegCreateKeyW( HKEY_CURRENT_USER, This->subkey, key );
if (res != ERROR_SUCCESS) {
/* probably not the correct return value */
FIXME( "returning %08x\\n", res );
return res;
}
res = RegGetValueW( HKEY_LOCAL_MACHINE, This->subkey, L"DefaultdefaultTokenId",
RRF_RT_REG_SZ, NULL, (LPVOID)®value, ®value_size);
if (res == ERROR_SUCCESS) {
RegSetValueExW( *key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)regvalue, regvalue_size);
}
return S_OK; +}
static HRESULT WINAPI token_category_SetDefaultTokenId( ISpObjectTokenCategory *iface, LPCWSTR id ) {
FIXME( "stub\n" );
return E_NOTIMPL;
struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
HRESULT hr;
LONG res;
HKEY key;
FIXME( "(%p)->(%s): semi-stub\n", iface, debugstr_w(id) );
if (!This->data_key)
return SPERR_UNINITIALIZED;
if (!id)
return E_INVALIDARG;
hr = get_user_speech_key( This, &key );
if (FAILED(hr)) return hr;
res = RegSetValueExW( key, L"DefaultTokenId", 0, REG_SZ, (const BYTE*)id,
wcslen( id) * sizeof( WCHAR ));
if (res != ERROR_SUCCESS) {
/* probably not the correct return value */
FIXME( "unable to set DefaultTokenId, returning S_FALSE\\n" );
RegCloseKey( key );
return S_FALSE;
}
RegCloseKey( key );
return S_OK; }
static HRESULT WINAPI token_category_GetDefaultTokenId( ISpObjectTokenCategory *iface, LPWSTR *id ) {
FIXME( "stub\n" );
return E_NOTIMPL;
struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
HRESULT hr;
LONG res;
HKEY key;
WCHAR regvalue[512];
DWORD regvalue_size = sizeof( regvalue );
FIXME( "(%p)->(%p): semi-stub\n", iface, id );
if (!This->data_key)
return SPERR_UNINITIALIZED;
if (!id)
return E_POINTER;
hr = get_user_speech_key( This, &key );
if (FAILED(hr)) return hr;
res = RegGetValueW( key, NULL, L"DefaultTokenId", RRF_RT_REG_SZ, NULL,
®value, ®value_size);
if (res != ERROR_SUCCESS) {
FIXME( "DefaultTokenId is missing, returning S_FALSE\\n" );
RegCloseKey( key );
return S_FALSE;
}
*id = CoTaskMemAlloc( regvalue_size );
wcscpy( *id, regvalue );
RegCloseKey( key );
return S_OK; }
const struct ISpObjectTokenCategoryVtbl token_category_vtbl =
2.27.0