Module: wine Branch: master Commit: 2d08038bac1beb29161143385642701190f8a4c1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=2d08038bac1beb291611433856...
Author: Bruno Jesus 00cpxxx@gmail.com Date: Wed Jan 14 21:09:49 2015 -0200
dplayx: Cache GUID values so they persist after enumeration.
---
dlls/dplayx/dplay.c | 39 +++++++++++---- dlls/dplayx/tests/dplayx.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 8 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 36e97a6..bae6a15 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -5785,6 +5785,11 @@ static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, DWORD max_sizeOfDescriptionA = 0; WCHAR *descriptionW = NULL; DWORD max_sizeOfDescriptionW = 0; + DWORD sizeOfSubKeyName; + WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */ + LONG ret_value; + static GUID *guid_cache; + static int cache_count;
if (!lpEnumCallbackA && !lpEnumCallbackW) { @@ -5799,19 +5804,37 @@ static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, ERR(": no service provider key in the registry - check your Wine installation !!!\n"); return DPERR_GENERIC; } - + + dwIndex = 0; + do + { + sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR); + ret_value = RegEnumKeyW(hkResult, dwIndex, subKeyName, sizeOfSubKeyName); + dwIndex++; + } + while (ret_value == ERROR_SUCCESS); + /* The game Swing from bug 37185 expects GUID values to persist after + * the end of the enumeration. */ + if (cache_count < dwIndex) + { + HeapFree(GetProcessHeap(), 0, guid_cache); + guid_cache = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID) * dwIndex); + if (!guid_cache) + { + ERR(": failed to alloc required memory.\n"); + return DPERR_EXCEPTION; + } + cache_count = dwIndex; + } /* Traverse all the service providers we have available */ dwIndex = 0; while (1) { - WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */ - DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR); HKEY hkServiceProvider; - GUID serviceProviderGUID; WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ]; DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent); - LONG ret_value; + sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR); ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime); if (ret_value == ERROR_NO_MORE_ITEMS) @@ -5842,7 +5865,7 @@ static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent)); continue; } - CLSIDFromString(guidKeyContent, &serviceProviderGUID ); + CLSIDFromString(guidKeyContent, &guid_cache[dwIndex]); /* The enumeration will return FALSE if we are not to continue. * @@ -5870,7 +5893,7 @@ static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, RegQueryValueExA(hkServiceProvider, "DescriptionA", NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription); - if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext)) + if (!lpEnumCallbackA(&guid_cache[dwIndex], descriptionA, 6, 0, lpContext)) goto end; } else @@ -5892,7 +5915,7 @@ static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, RegQueryValueExW(hkServiceProvider, descW, NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
- if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext)) + if (!lpEnumCallbackW(&guid_cache[dwIndex], descriptionW, 6, 0, lpContext)) goto end; }
diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index fb6646d..236e1a8 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -72,6 +72,13 @@ typedef struct tagCallbackData UINT dpidSize; } CallbackData, *lpCallbackData;
+struct provider_data +{ + int call_count; + GUID *guid_ptr[10]; + GUID guid_data[10]; + BOOL ret_value; +};
static LPSTR get_temp_buffer(void) { @@ -749,6 +756,113 @@ static void test_DirectPlayCreate(void)
}
+static BOOL CALLBACK callback_providersA(GUID* guid, char *name, DWORD major, DWORD minor, void *arg) +{ + struct provider_data *prov = arg; + + if (!prov) return TRUE; + + if (prov->call_count < sizeof(prov->guid_data) / sizeof(prov->guid_data[0])) + { + prov->guid_ptr[prov->call_count] = guid; + prov->guid_data[prov->call_count] = *guid; + + prov->call_count++; + } + + if (prov->ret_value) /* Only trace when looping all providers */ + trace("Provider #%d '%s' (%d.%d)\n", prov->call_count, name, major, minor); + return prov->ret_value; +} + +static BOOL CALLBACK callback_providersW(GUID* guid, WCHAR *name, DWORD major, DWORD minor, void *arg) +{ + struct provider_data *prov = arg; + + if (!prov) return TRUE; + + if (prov->call_count < sizeof(prov->guid_data) / sizeof(prov->guid_data[0])) + { + prov->guid_ptr[prov->call_count] = guid; + prov->guid_data[prov->call_count] = *guid; + + prov->call_count++; + } + + return prov->ret_value; +} + +static void test_EnumerateProviders(void) +{ + HRESULT hr; + int i; + struct provider_data arg; + + memset(&arg, 0, sizeof(arg)); + arg.ret_value = TRUE; + + hr = DirectPlayEnumerateA(callback_providersA, NULL); + ok(SUCCEEDED(hr), "DirectPlayEnumerateA failed\n"); + + SetLastError(0xdeadbeef); + hr = DirectPlayEnumerateA(NULL, &arg); + ok(FAILED(hr), "DirectPlayEnumerateA expected to fail\n"); + ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got 0x%x\n", GetLastError()); + + SetLastError(0xdeadbeef); + hr = DirectPlayEnumerateA(NULL, NULL); + ok(FAILED(hr), "DirectPlayEnumerateA expected to fail\n"); + ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got 0x%x\n", GetLastError()); + + hr = DirectPlayEnumerateA(callback_providersA, &arg); + ok(SUCCEEDED(hr), "DirectPlayEnumerateA failed\n"); + ok(arg.call_count > 0, "Expected at least one valid provider\n"); + trace("Found %d providers\n", arg.call_count); + + /* The returned GUID values must have persisted after enumeration (bug 37185) */ + for(i = 0; i < arg.call_count; i++) + { + ok(IsEqualGUID(arg.guid_ptr[i], &arg.guid_data[i]), "#%d Expected equal GUID values\n", i); + } + + memset(&arg, 0, sizeof(arg)); + arg.ret_value = FALSE; + hr = DirectPlayEnumerateA(callback_providersA, &arg); + ok(SUCCEEDED(hr), "DirectPlayEnumerateA failed\n"); + ok(arg.call_count == 1, "Expected 1, got %d\n", arg.call_count); + + hr = DirectPlayEnumerateW(callback_providersW, NULL); + ok(SUCCEEDED(hr), "DirectPlayEnumerateW failed\n"); + + SetLastError(0xdeadbeef); + hr = DirectPlayEnumerateW(NULL, &arg); + ok(FAILED(hr), "DirectPlayEnumerateW expected to fail\n"); + ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got 0x%x\n", GetLastError()); + + SetLastError(0xdeadbeef); + hr = DirectPlayEnumerateW(NULL, NULL); + ok(FAILED(hr), "DirectPlayEnumerateW expected to fail\n"); + ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got 0x%x\n", GetLastError()); + + memset(&arg, 0, sizeof(arg)); + arg.ret_value = TRUE; + hr = DirectPlayEnumerateW(callback_providersW, &arg); + ok(SUCCEEDED(hr), "DirectPlayEnumerateW failed\n"); + ok(arg.call_count > 0, "Expected at least one valid provider\n"); + + /* The returned GUID values must have persisted after enumeration (bug 37185) */ + for(i = 0; i < arg.call_count; i++) + { + ok(IsEqualGUID(arg.guid_ptr[i], &arg.guid_data[i]), "#%d Expected equal GUID values\n", i); + } + + memset(&arg, 0, sizeof(arg)); + arg.ret_value = FALSE; + hr = DirectPlayEnumerateW(callback_providersW, &arg); + ok(SUCCEEDED(hr), "DirectPlayEnumerateW failed\n"); + ok(arg.call_count == 1, "Expected 1, got %d\n", arg.call_count); +} + /* EnumConnections */
static BOOL CALLBACK EnumAddress_cb2( REFGUID guidDataType, @@ -6544,6 +6658,7 @@ START_TEST(dplayx)
test_COM(); test_COM_dplobby(); + test_EnumerateProviders();
if (!winetest_interactive) {