From 0421278838371dd987d6d9b7a4ada1347730f733 Mon Sep 17 00:00:00 2001 From: Ismael Barros Date: Thu, 17 Jul 2008 19:32:15 +0300 Subject: [PATCH] dplayx: Implemented wide version of EnumConnections 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 file changed, 123 insertions(+), 202 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 31ca31a8f3e..cb3a93132a2 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 -- 2.11.4.GIT