From c53db1934baf45b4ee554ade38e397455c91d50e Mon Sep 17 00:00:00 2001 From: Lionel Ulmer Date: Mon, 23 May 2005 11:49:36 +0000 Subject: [PATCH] Rewrite DirectPlayEnumerateA and add W version at the same time. --- dlls/dplayx/dplay.c | 257 ++++++++++++++++++++++++++------------------ 1 file changed, 150 insertions(+), 107 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 78cef8d600..4c0fa96848 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -5155,8 +5155,7 @@ HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, } /*************************************************************************** - * DirectPlayEnumerate [DPLAYX.9] - * DirectPlayEnumerateA [DPLAYX.2] + * DirectPlayEnumerateAW * * 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 +5175,169 @@ HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, * 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 ) -{ - - 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 */ +static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, + LPDPENUMDPCALLBACKW lpEnumCallbackW, + LPVOID lpContext) +{ + 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; - sizeOfReturnBuffer = 50; - if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey, - NULL, &returnTypeReserved, returnBuffer, - &sizeOfReturnBuffer ) != ERROR_SUCCESS ) + 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; - } - } - - return DP_OK; + 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++; + } + + end: + HeapFree(GetProcessHeap(), 0, descriptionA); + HeapFree(GetProcessHeap(), 0, descriptionW); + + return DP_OK; +} +/*************************************************************************** + * DirectPlayEnumerate [DPLAYX.9] + * DirectPlayEnumerateA [DPLAYX.2] + */ +HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext ) +{ + TRACE("(%p,%p)\n", lpEnumCallback, lpContext); + + return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext); } /*************************************************************************** * DirectPlayEnumerateW [DPLAYX.3] - * */ -HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext ) +HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext ) { - - FIXME(":stub\n"); - - return DPERR_OUTOFMEMORY; - + TRACE("(%p,%p)\n", lpEnumCallback, lpContext); + + return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext); } typedef struct tagCreateEnum -- 2.32.0.93.g670b81a890