[PATCH] sapi: Improve Get/SetDefaultTokenId stubs.
Myah Caron
qsniyg at protonmail.com
Sat Aug 1 14:52:20 CDT 2020
Signed-off-by: Myah Caron <qsniyg at 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
More information about the wine-devel
mailing list