|
|
#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
|