Bruno Jesus : dplayx: Cache GUID values so they persist after enumeration.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jan 16 14:12:31 CST 2015


Module: wine
Branch: master
Commit: 2d08038bac1beb29161143385642701190f8a4c1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2d08038bac1beb29161143385642701190f8a4c1

Author: Bruno Jesus <00cpxxx at 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)
     {




More information about the wine-cvs mailing list