Commit 2d08038b authored by Bruno Jesus's avatar Bruno Jesus Committed by Alexandre Julliard

dplayx: Cache GUID values so they persist after enumeration.

parent e584edd3
......@@ -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;
}
......
......@@ -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)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment