#include "dpsp.h" #define REGISTRY_NAMELEN 512 // space (in bytes) for a human readable (unicode) guid + some extra #define GUID_STRING_SIZE 80 #define SZ_SP_KEY "Software\\Microsoft\\DirectPlay\\Service Providers" #define SZ_GUID "Guid" #define SZ_FLAGS "dwFlags" #undef DPF_MODNAME #define DPF_MODNAME "FindApplicationInRegistry" // convert a hex char to an int - used by str to guid conversion // we wrote our own, since the ole one is slow, and requires ole32.dll // we use ansi strings here, since guids won't get internationalized int GetDigit(LPSTR lpstr) { char ch = *lpstr; if (ch >= '0' && ch <= '9') return(ch - '0'); if (ch >= 'a' && ch <= 'f') return(ch - 'a' + 10); if (ch >= 'A' && ch <= 'F') return(ch - 'A' + 10); return(0); } // walk the string, writing pairs of bytes into the byte stream (guid) // we need to write the bytes into the byte stream from right to left // or left to right as indicated by fRightToLeft void ConvertField(LPBYTE lpByte,LPSTR * ppStr,int iFieldSize,BOOL fRightToLeft) { int i; for (i=0;i<iFieldSize ;i++ ) { // don't barf on the field separators if ('-' == **ppStr) (*ppStr)++; if (fRightToLeft == TRUE) { // work from right to left within the byte stream *(lpByte + iFieldSize - (i+1)) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1); } else { // work from left to right within the byte stream *(lpByte + i) = 16*GetDigit(*ppStr) + GetDigit((*ppStr)+1); } *ppStr+=2; // get next two digit pair } } // ConvertField // convert the passed in string to a real GUID // walk the guid, setting each byte in the guid to the two digit hex pair in the // passed string HRESULT GUIDFromString(LPSTR lpStr, GUID * pGuid) { BYTE * lpByte; // byte index into guid int iFieldSize; // size of current field we're converting // since its a guid, we can do a "brute force" conversion // make sure we have a {xxxx-...} type guid if ('{' != *lpStr) return E_FAIL; lpStr++; lpByte = (BYTE *)pGuid; // data 1 iFieldSize = sizeof(unsigned long); ConvertField(lpByte,&lpStr,iFieldSize,TRUE); lpByte += iFieldSize; // data 2 iFieldSize = sizeof(unsigned short); ConvertField(lpByte,&lpStr,iFieldSize,TRUE); lpByte += iFieldSize; // data 3 iFieldSize = sizeof(unsigned short); ConvertField(lpByte,&lpStr,iFieldSize,TRUE); lpByte += iFieldSize; // data 4 iFieldSize = 8*sizeof(unsigned char); ConvertField(lpByte,&lpStr,iFieldSize,FALSE); lpByte += iFieldSize; // make sure we ended in the right place if ('}' != *lpStr) { DPF_ERR("invalid guid!!"); memset(pGuid,0,sizeof(GUID)); return E_FAIL; } return DP_OK; }// GUIDFromString BOOL FindSPInRegistry(LPGUID lpguid, LPSTR lpszSPName, DWORD dwNameSize, HKEY * lphkey) { HKEY hkeyDPSPs, hkeySP; DWORD dwIndex = 0; CHAR szGuidStr[GUID_STRING_SIZE]; DWORD dwGuidStrSize = GUID_STRING_SIZE; DWORD dwType = REG_SZ; GUID guidSP; LONG lReturn; BOOL bFound = FALSE; DWORD dwSaveNameSize = dwNameSize; DPF(7, "Entering FindSPInRegistry"); DPF(9, "Parameters: 0x%08x, 0x%08x, %lu, 0x%08x", lpguid, lpszSPName, dwNameSize, lphkey); // Open the Applications key lReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SZ_SP_KEY, 0, KEY_READ, &hkeyDPSPs); if(lReturn != ERROR_SUCCESS) { DPF_ERR("Unable to open DPlay service provider registry key!"); return FALSE; } // Walk the list of sps in the registry, looking for // the sp with the right GUID while(!bFound) { // Open the next application key dwSaveNameSize = dwNameSize; dwGuidStrSize = GUID_STRING_SIZE; lReturn = RegEnumKeyExA(hkeyDPSPs, dwIndex++, lpszSPName, &dwSaveNameSize, NULL, NULL, NULL, NULL); // If the enum returns no more apps, we want to bail if(lReturn != ERROR_SUCCESS) break; // Open the application key lReturn = RegOpenKeyExA(hkeyDPSPs, lpszSPName, 0, KEY_READ, &hkeySP); if(lReturn != ERROR_SUCCESS) { DPF_ERR("Unable to open sp key!"); continue; } // Get the GUID of the Game lReturn = RegQueryValueExA(hkeySP, SZ_GUID, NULL, &dwType, (LPBYTE)&szGuidStr, &dwGuidStrSize); if(lReturn != ERROR_SUCCESS) { RegCloseKey(hkeySP); DPF_ERR("Unable to query GUID key value!"); continue; } // Convert the string to a real GUID & Compare it to the passed in one GUIDFromString(szGuidStr, &guidSP); if(IsEqualGUID(&guidSP, lpguid)) { bFound = TRUE; break; } // Close the App key RegCloseKey(hkeySP); } // Close the DPApps key RegCloseKey(hkeyDPSPs); if(bFound) *lphkey = hkeySP; return bFound; } // FindSPInRegistry #undef DPF_MODNAME #define DPF_MODNAME "GetKeyValue" BOOL GetKeyValue(HKEY hkeyApp, LPSTR lpszKey, DWORD dwType, LPBYTE * lplpValue) { DWORD dwSize; LPBYTE lpTemp = NULL; LONG lReturn; DPF(7, "Entering GetKeyValue"); DPF(9, "Parameters: 0x%08x, 0x%08x, 0x%08x", hkeyApp, lpszKey, lplpValue); ASSERT(lplpValue); // Get the size of the buffer for the Path lReturn = RegQueryValueExA(hkeyApp, lpszKey, NULL, &dwType, NULL, &dwSize); if(lReturn != ERROR_SUCCESS) { DPF_ERR("Error getting size of key value!"); return FALSE; } // If the size is 1, then it is an empty string (only contains a // null terminator). Treat this the same as a NULL string or a // missing key and fail it. if(dwSize <= 1) return FALSE; ENTER_DPSP(); // Alloc the buffer for the Path lpTemp = MemAlloc(dwSize); LEAVE_DPSP(); if(!lpTemp) { DPF_ERR("Unable to allocate temporary string for Path!"); return FALSE; } // Get the value itself lReturn = RegQueryValueExA(hkeyApp, lpszKey, NULL, &dwType, (LPBYTE)lpTemp, &dwSize); if(lReturn != ERROR_SUCCESS) { MemFree(lpTemp); DPF_ERR("Unable to get key value!"); return FALSE; } *lplpValue = lpTemp; return TRUE; } // GetKeyValue #undef DPF_MODNAME #define DPF_MODNAME "GetFlagsFromRegistry" HRESULT GetFlagsFromRegistry(LPGUID lpguidSP, LPDWORD lpdwFlags) { LPSTR lpszSPName=NULL; HKEY hkeySP = NULL; LPBYTE lpValue=NULL; DWORD dwSize = 0; HRESULT hr = DP_OK; DPF(7, "Entering GetFlagsFromRegistry"); DPF(9, "Parameters: 0x%08x, 0x%08x", lpguidSP, lpdwFlags); ENTER_DPSP(); // Allocate memory for the App Name lpszSPName = MemAlloc(REGISTRY_NAMELEN); LEAVE_DPSP(); if(!lpszSPName) { DPF_ERR("Unable to allocate memory for sp name!"); return E_OUTOFMEMORY; } // Open the registry key for the App if(!FindSPInRegistry(lpguidSP, lpszSPName,REGISTRY_NAMELEN, &hkeySP)) { DPF_ERR("Unable to find sp in registry!"); hr = E_FAIL; goto CLEANUP_EXIT; } // Get the port value. if(!GetKeyValue(hkeySP, SZ_FLAGS, REG_BINARY, &lpValue)) { DPF_ERR("Unable to get flags value from registry!"); hr = E_FAIL; goto CLEANUP_EXIT; } *lpdwFlags = *(LPDWORD)lpValue; // fall through CLEANUP_EXIT: if (lpszSPName) MemFree(lpszSPName); if (lpValue) MemFree(lpValue); // Close the Apps key if(hkeySP) RegCloseKey(hkeySP); return hr; } // GetFlagsFromRegistry