[DPlay] Rewrite of DirectPlayEnumerate[A|W]

Lionel Ulmer lionel.ulmer at free.fr
Sun May 22 14:52:37 CDT 2005


As seen in my debugging tutorial, just started looking a bit into DirectPlay
(not that it is used much in games, but well, it's just another part of
DirectX I did not know, so it's good to explore a bit :-) ).

       Lionel

Changelog:
 - rewrite DirectPlayEnumerateA and add W version at the same time

-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
Index: dlls/dplayx/dplay.c
===================================================================
RCS file: /home/wine/wine/dlls/dplayx/dplay.c,v
retrieving revision 1.57
diff -u -r1.57 dplay.c
--- dlls/dplayx/dplay.c	19 Apr 2005 09:48:09 -0000	1.57
+++ dlls/dplayx/dplay.c	22 May 2005 19:49:58 -0000
@@ -5157,6 +5157,7 @@
 /***************************************************************************
  *  DirectPlayEnumerate  [DPLAYX.9]
  *  DirectPlayEnumerateA [DPLAYX.2]
+ *  DirectPlayEnumerateW [DPLAYX.3]
  *
  *  The pointer to the structure lpContext will be filled with the
  *  appropriate data for each service offered by the OS. These services are
@@ -5176,125 +5177,162 @@
  * supply service providers to use specialized hardware, protocols, communications
  * media, and network resources.
  *
- * TODO: Allocate string buffer space from the heap (length from reg)
- *       Pass real device driver numbers...
- *       Get the GUID properly...
  */
-HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
-                                     LPVOID lpContext )
+HRESULT WINAPI DirectPlayEnumerateA_W(LPDPENUMDPCALLBACKA lpEnumCallbackA,
+				      LPDPENUMDPCALLBACKW lpEnumCallbackW,
+				      LPVOID lpContext)
 {
-
-  HKEY   hkResult;
-  LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
-  DWORD  dwIndex;
-  DWORD  sizeOfSubKeyName=50;
-  char   subKeyName[51];
-  FILETIME filetime;
-
-  TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
-
-  if( !lpEnumCallback || !*lpEnumCallback )
-  {
-     return DPERR_INVALIDPARAMS;
-  }
-
-  /* Need to loop over the service providers in the registry */
-  if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
-                       0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
-  {
-    /* Hmmm. Does this mean that there are no service providers? */
-    ERR(": no service providers?\n");
-    return DPERR_NOSERVICEPROVIDER;
-  }
-
-  /* Traverse all the service providers we have available */
-  for( dwIndex=0;
-       RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
-                      NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
-       ++dwIndex, sizeOfSubKeyName=50 )
-  {
-    LPCSTR   majVerDataSubKey = "dwReserved1";
-    LPCSTR   minVerDataSubKey = "dwReserved2";
-    LPCSTR   guidDataSubKey   = "Guid";
-    HKEY     hkServiceProvider;
-    GUID     serviceProviderGUID;
-    DWORD    returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
-    char     returnBuffer[51];
-    WCHAR    buff[51];
-    DWORD    majVersionNum , minVersionNum = 0;
-
-    TRACE(" this time through: %s\n", subKeyName );
-
-    /* Get a handle for this particular service provider */
-    if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
-                         &hkServiceProvider ) != ERROR_SUCCESS )
-    {
-      ERR(": what the heck is going on?\n" );
-      continue;
-    }
-
-    /* Get the GUID, Device major number and device minor number
-     * from the registry.
-     */
-    if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
-                            NULL, &returnTypeGUID, returnBuffer,
-                            &sizeOfReturnBuffer ) != ERROR_SUCCESS )
-    {
-      ERR(": missing GUID registry data members\n" );
-      continue;
-    }
-
-    /* FIXME: Check return types to ensure we're interpreting data right */
-    MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
-    CLSIDFromString( buff, &serviceProviderGUID );
-
-    /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
-
-    sizeOfReturnBuffer = 50;
-    if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
-                            NULL, &returnTypeReserved, returnBuffer,
-                            &sizeOfReturnBuffer ) != ERROR_SUCCESS )
+    HKEY   hkResult;
+    static const WCHAR searchSubKey[] = {
+	'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
+	'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
+	'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
+	'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
+    static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
+    static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
+    
+    DWORD  dwIndex;
+    FILETIME filetime;
+
+    char  *descriptionA = NULL;
+    DWORD max_sizeOfDescriptionA = 0;
+    WCHAR *descriptionW = NULL;
+    DWORD max_sizeOfDescriptionW = 0;
+    
+    if (!lpEnumCallbackA && !lpEnumCallbackW)
     {
-      ERR(": missing dwReserved1 registry data members\n") ;
-      continue;
+	return DPERR_INVALIDPARAMS;
     }
-    memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
-
-    sizeOfReturnBuffer = 50;
-    if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
-                            NULL, &returnTypeReserved, returnBuffer,
-                            &sizeOfReturnBuffer ) != ERROR_SUCCESS )
+    
+    /* Need to loop over the service providers in the registry */
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
+		      0, KEY_READ, &hkResult) != ERROR_SUCCESS)
     {
-      ERR(": missing dwReserved2 registry data members\n") ;
-      continue;
+	/* Hmmm. Does this mean that there are no service providers? */
+	ERR(": no service provider key in the registry - check your Wine installation !!!\n");
+	return DPERR_GENERIC;
     }
-    memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
-
-
-    /* The enumeration will return FALSE if we are not to continue */
-    if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
-                         majVersionNum, minVersionNum, lpContext ) )
+    
+    /* Traverse all the service providers we have available */
+    dwIndex = 0;
+    while (1)
     {
-      WARN("lpEnumCallback returning FALSE\n" );
-      break;
-    }
+	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;
+	
+	ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
+				  NULL, NULL, NULL, &filetime);
+	if (ret_value == ERROR_NO_MORE_ITEMS)
+	    break;
+	else if (ret_value != ERROR_SUCCESS)
+	{
+	    ERR(": could not enumerate on service provider key.\n");
+	    return DPERR_EXCEPTION;
+	}
+	TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
+	
+	/* Open the key for this service provider */
+	if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
+	{
+	    ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
+	    continue;
+	}
+	
+	/* Get the GUID from the registry */
+	if (RegQueryValueExW(hkServiceProvider, guidKey,
+			     NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
+	{
+	    ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
+	    continue;
+	}
+	if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
+	{
+	    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 );
+	
+	/* The enumeration will return FALSE if we are not to continue.
+	 *
+	 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
+	 *       and have no relations to any of the two dwReserved1 and dwReserved2 keys.
+	 *       I think that it simply means that they are in-line with DirectX 6.0
+	 */
+	if (lpEnumCallbackA)
+	{
+	    DWORD sizeOfDescription = 0;
+	    
+	    /* Note that this the the A case of this function, so use the A variant to get the description string */
+	    if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
+				 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
+	    {
+		ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
+		continue;
+	    }
+	    if (sizeOfDescription > max_sizeOfDescriptionA)
+	    {
+		HeapFree(GetProcessHeap(), 0, descriptionA);
+		max_sizeOfDescriptionA = sizeOfDescription;
+		descriptionA = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionA);
+	    }
+	    descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
+	    RegQueryValueExA(hkServiceProvider, "DescriptionA",
+			     NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
+	    
+	    if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
+		goto end;
+	}
+	else
+	{
+	    DWORD sizeOfDescription = 0;
+	    
+	    if (RegQueryValueExW(hkServiceProvider, descW,
+				 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
+	    {
+		ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
+		continue;
+	    }
+	    if (sizeOfDescription > max_sizeOfDescriptionW)
+	    {
+		HeapFree(GetProcessHeap(), 0, descriptionW);
+		max_sizeOfDescriptionW = sizeOfDescription;
+		descriptionW = HeapAlloc(GetProcessHeap(), 0, max_sizeOfDescriptionW);
+	    }
+	    descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
+	    RegQueryValueExW(hkServiceProvider, descW,
+			     NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
+
+	    if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
+		goto end;
+	}
+      
+      dwIndex++;
   }
 
-  return DP_OK;
-
+ end:
+    HeapFree(GetProcessHeap(), 0, descriptionA);
+    HeapFree(GetProcessHeap(), 0, descriptionW);
+    
+    return DP_OK;
 }
 
-/***************************************************************************
- *  DirectPlayEnumerateW [DPLAYX.3]
- *
- */
-HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
+HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
 {
+    TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
+    
+    return DirectPlayEnumerateA_W(lpEnumCallback, NULL, lpContext);
+}
 
-  FIXME(":stub\n");
-
-  return DPERR_OUTOFMEMORY;
-
+HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
+{
+    TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
+    
+    return DirectPlayEnumerateA_W(NULL, lpEnumCallback, lpContext);
 }
 
 typedef struct tagCreateEnum


More information about the wine-patches mailing list