[PATCH 4/4] dplayx: Implemented wide version of EnumConnections

Ismael Barros razielmine at gmail.com
Mon Jul 20 10:52:52 CDT 2009


  Now both ANSI and wide versions of EnumConnections call an auxiliar
function with parameter bAnsi=(TRUE|FALSE).
  This approach is used instead of the traditional Wine approach because
in the middle of the function we need to call a callback function with
either ANSI or wide strings.
  The code of the auxiliar function is basically the code of the
previous ANSI version cleaned up, as the previous code implemented
Lobby Providers support with a copy/paste and a few changes.
  This patch fixes connection enumeration in GTA2.

  Changed DP_BuildSPCompoundAddr to be more generic, and renamed
it to DP_BuildCompoundAddr.
---
 dlls/dplayx/dplay.c |  325 +++++++++++++++++++--------------------------------
 1 files changed, 123 insertions(+), 202 deletions(-)

diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c
index 31ca31a..cb3a931 100644
--- a/dlls/dplayx/dplay.c
+++ b/dlls/dplayx/dplay.c
@@ -194,8 +194,8 @@ static HRESULT DP_IF_InitializeConnection
 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
     LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
     DWORD dwFlags, LPVOID lpContext );
-static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
-                                    LPDWORD lpdwBufSize );
+static BOOL DP_BuildCompoundAddr( GUID guidDataType, LPGUID lpcSpGuid,
+                                  LPVOID* lplpAddrBuf, LPDWORD lpdwBufSize );
 
 
 
@@ -2293,7 +2293,8 @@ static HRESULT DP_IF_EnumSessions
 
      WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
 
-     if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
+     if( !DP_BuildCompoundAddr( DPAID_ServiceProvider, (LPGUID)&DPSPGUID_TCPIP,
+                                &lpConnection, &dwSize ) )
      {
        ERR( "Can't build compound addr\n" );
        return DPERR_GENERIC;
@@ -3785,15 +3786,16 @@ static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
   IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
   return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
 }
-
-static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
-                                    LPDWORD lpdwBufSize )
+static BOOL DP_BuildCompoundAddr( GUID guidDataType,
+                                  LPGUID lpcSpGuid,
+                                  LPVOID* lplpAddrBuf,
+                                  LPDWORD lpdwBufSize )
 {
   DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
   HRESULT                  hr;
 
   dpCompoundAddress.dwDataSize = sizeof( GUID );
-  dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
+  dpCompoundAddress.guidDataType = guidDataType;
   dpCompoundAddress.lpData = lpcSpGuid;
 
   *lplpAddrBuf = NULL;
@@ -3823,11 +3825,26 @@ static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
   return TRUE;
 }
 
-static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
-          ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
+static HRESULT WINAPI DP_IF_EnumConnections
+          ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication,
+            LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext,
+            DWORD dwFlags, BOOL bAnsi )
 {
-  IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
-  TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
+  HKEY hkResult;
+  WCHAR searchSubKeySP[] = {
+    '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 };
+  WCHAR searchSubKeyLP[] = {
+    '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', '\\',
+    'L', 'o', 'b', 'b', 'y', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
+  WCHAR guidDataSubKey[] = { 'G', 'u', 'i', 'd', 0 };
+  WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
+  DWORD dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
+  FILETIME filetime;
 
   /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
   if( dwFlags == 0 )
@@ -3836,232 +3853,136 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
   }
 
   if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
-          ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
-    )
+          ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) )
   {
     return DPERR_INVALIDFLAGS;
   }
 
   if( !lpEnumCallback )
   {
-     return DPERR_INVALIDPARAMS;
+    return DPERR_INVALIDPARAMS;
   }
 
-  /* Enumerate DirectPlay service providers */
-  if( dwFlags & DPCONNECTION_DIRECTPLAY )
-  {
-    HKEY hkResult;
-    LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
-    LPCSTR guidDataSubKey  = "Guid";
-    char subKeyName[51];
-    DWORD dwIndex, sizeOfSubKeyName=50;
-    FILETIME filetime;
 
-    /* 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 DP_OK;
-    }
+  /* Need to loop over the service providers in the registry */
+  if( RegOpenKeyExW( HKEY_LOCAL_MACHINE,
+                     ( dwFlags & DPCONNECTION_DIRECTPLAY ) ? searchSubKeySP
+                                                           : searchSubKeyLP,
+                     0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
+  {
+    /* Hmmm. Does this mean that there are no service providers? */
+    ERR(": no service providers?\n");
+    return DP_OK;
+  }
 
 
-    /* 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=51 )
-    {
+  /* Traverse all the service providers we have available */
+  for( dwIndex=0;
+       RegEnumKeyExW( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
+                      NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
+       ++dwIndex, sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR) )
+  {
+    HKEY     hkServiceProvider;
+    GUID     serviceProviderGUID;
+    WCHAR    guidKeyContent[39];
+    DWORD    sizeOfReturnBuffer = sizeof(guidKeyContent);
+    DPNAME   dpName;
+    BOOL     continueEnumeration = TRUE;
 
-      HKEY     hkServiceProvider;
-      GUID     serviceProviderGUID;
-      DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
-      char     returnBuffer[51];
-      WCHAR    buff[51];
-      DPNAME   dpName;
-      BOOL     bBuildPass;
+    LPVOID   lpAddressBuffer = NULL;
+    DWORD    dwAddressBufferSize = 0;
 
-      LPVOID                   lpAddressBuffer = NULL;
-      DWORD                    dwAddressBufferSize = 0;
 
-      TRACE(" this time through: %s\n", subKeyName );
+    TRACE(" this time through: %s\n", debugstr_w(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 a handle for this particular service provider */
+    if( RegOpenKeyExW( hkResult, subKeyName, 0, KEY_READ,
+                       &hkServiceProvider ) != ERROR_SUCCESS )
+    {
+      ERR(": what the heck is going on?\n" );
+      continue;
+    }
 
-      if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
-                            NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
-                            &sizeOfReturnBuffer ) != ERROR_SUCCESS )
-      {
-        ERR(": missing GUID registry data members\n" );
-        RegCloseKey(hkServiceProvider);
-        continue;
-      }
+    if( RegQueryValueExW( hkServiceProvider, guidDataSubKey,
+                          NULL, NULL, (LPBYTE)guidKeyContent,
+                          &sizeOfReturnBuffer ) != ERROR_SUCCESS )
+    {
+      ERR(": missing GUID registry data members\n" );
       RegCloseKey(hkServiceProvider);
-
-      /* 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: Have I got a memory leak on the serviceProviderGUID? */
-
-      /* Fill in the DPNAME struct for the service provider */
-      dpName.dwSize             = sizeof( dpName );
-      dpName.dwFlags            = 0;
-      dpName.u1.lpszShortNameA = subKeyName;
-      dpName.u2.lpszLongNameA  = NULL;
-
-      /* Create the compound address for the service provider.
-       * NOTE: This is a gruesome architectural scar right now.  DP
-       * uses DPL and DPL uses DP.  Nasty stuff. This may be why the
-       * native dll just gets around this little bit by allocating an
-       * 80 byte buffer which isn't even filled with a valid compound
-       * address. Oh well. Creating a proper compound address is the
-       * way to go anyways despite this method taking slightly more
-       * heap space and realtime :) */
-
-      bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
-                                           &lpAddressBuffer,
-                                           &dwAddressBufferSize );
-      if( !bBuildPass )
-      {
-        ERR( "Can't build compound addr\n" );
-        return DPERR_GENERIC;
-      }
-
-      /* The enumeration will return FALSE if we are not to continue */
-      if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
-                           &dpName, dwFlags, lpContext ) )
-      {
-         return DP_OK;
-      }
+      continue;
     }
-  }
+    RegCloseKey(hkServiceProvider);
 
-  /* Enumerate DirectPlayLobby service providers */
-  if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
-  {
-    HKEY hkResult;
-    LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
-    LPCSTR guidDataSubKey  = "Guid";
-    char subKeyName[51];
-    DWORD dwIndex, sizeOfSubKeyName=50;
-    FILETIME filetime;
+    CLSIDFromString( guidKeyContent, &serviceProviderGUID );
 
-    /* Need to loop over the service providers in the registry */
-    if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
-                         0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
+    /* Fill in the DPNAME struct for the service provider */
+    dpName.dwSize = sizeof( dpName );
+    dpName.dwFlags = 0;
+    if ( bAnsi )
     {
-      /* Hmmm. Does this mean that there are no service providers? */
-      ERR(": no service providers?\n");
-      return DP_OK;
+      dpName.u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                            sizeOfSubKeyName+1 );
+      WideCharToMultiByte( CP_ACP, 0, subKeyName,
+                           -1, dpName.u1.lpszShortNameA, -1, 0, 0);
+      dpName.u2.lpszLongNameA = NULL;
     }
-
-
-    /* Traverse all the lobby providers we have available */
-    for( dwIndex=0;
-         RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
-                        NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
-         ++dwIndex, sizeOfSubKeyName=51 )
+    else
     {
+      dpName.u1.lpszShortName = subKeyName;
+      dpName.u2.lpszLongName = NULL;
+    }
 
-      HKEY     hkServiceProvider;
-      GUID     serviceProviderGUID;
-      DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
-      char     returnBuffer[51];
-      WCHAR    buff[51];
-      DPNAME   dpName;
-      HRESULT  hr;
-
-      DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
-      LPVOID                   lpAddressBuffer = NULL;
-      DWORD                    dwAddressBufferSize = 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;
-      }
-
-      if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
-                            NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
-                            &sizeOfReturnBuffer ) != ERROR_SUCCESS )
-      {
-        ERR(": missing GUID registry data members\n" );
-        RegCloseKey(hkServiceProvider);
-        continue;
-      }
-      RegCloseKey(hkServiceProvider);
-
-      /* 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: Have I got a memory leak on the serviceProviderGUID? */
-
-      /* Fill in the DPNAME struct for the service provider */
-      dpName.dwSize             = sizeof( dpName );
-      dpName.dwFlags            = 0;
-      dpName.u1.lpszShortNameA = subKeyName;
-      dpName.u2.lpszLongNameA  = NULL;
-
-      /* Create the compound address for the service provider.
-         NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
-               nast stuff. This may be why the native dll just gets around this little bit by
-               allocating an 80 byte buffer which isn't even a filled with a valid compound
-               address. Oh well. Creating a proper compound address is the way to go anyways
-               despite this method taking slightly more heap space and realtime :) */
-
-      dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
-      dpCompoundAddress.dwDataSize   = sizeof( GUID );
-      dpCompoundAddress.lpData       = &serviceProviderGUID;
-
-      if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
-                                     &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
-      {
-        ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
-        return hr;
-      }
-
-      /* Now allocate the buffer */
-      lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
-
-      if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
-                                     &dwAddressBufferSize, TRUE ) ) != DP_OK )
-      {
-        ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
-        HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
-        return hr;
-      }
-
+    /* Create the compound address for the service provider.
+     * NOTE: This is a gruesome architectural scar right now.  DP
+     *       uses DPL and DPL uses DP.  Nasty stuff. This may be why the
+     *       native dll just gets around this little bit by allocating an
+     *       80 byte buffer which isn't even filled with a valid compound
+     *       address. Oh well. Creating a proper compound address is the
+     *       way to go anyways despite this method taking slightly more
+     *       heap space and realtime :) */
+
+    if ( DP_BuildCompoundAddr( ( ( dwFlags & DPCONNECTION_DIRECTPLAY )
+                                 ? DPAID_ServiceProvider
+                                 : DPAID_LobbyProvider ),
+                               &serviceProviderGUID,
+                               &lpAddressBuffer,
+                               &dwAddressBufferSize ) )
+    {
       /* The enumeration will return FALSE if we are not to continue */
-      if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
-                           &dpName, dwFlags, lpContext ) )
-      {
-         HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
-         return DP_OK;
-      }
-      HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
+      continueEnumeration = lpEnumCallback( &serviceProviderGUID, lpAddressBuffer,
+                                            dwAddressBufferSize, &dpName,
+                                            dwFlags, lpContext );
+    }
+    else
+    {
+      ERR( "Couldn't build compound address\n" );
     }
+
+    HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
+    if ( bAnsi )
+      HeapFree( GetProcessHeap(), 0, dpName.u1.lpszShortNameA );
+
+    if (!continueEnumeration)
+      return DP_OK;
   }
 
   return DP_OK;
 }
 
+static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
+          ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
+{
+  IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
+  TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
+  return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, TRUE );
+}
+
 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
           ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
 {
   IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;
-  FIXME("(%p)->(%p,%p,%p,0x%08x): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
-  return DP_OK;
+  TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
+  return DP_IF_EnumConnections( iface, lpguidApplication, lpEnumCallback, lpContext, dwFlags, FALSE );
 }
 
 static HRESULT DP_IF_EnumGroupsInGroup
-- 
1.6.3.3




More information about the wine-patches mailing list