1029 lines
37 KiB
C++
1029 lines
37 KiB
C++
/****************************************************************************
|
|
*
|
|
* File: netinfo.cpp
|
|
* Project: DxDiag (DirectX Diagnostic Tool)
|
|
* Author: Mike Anderson (manders@microsoft.com)
|
|
* Purpose: Gather information about DirectPlay
|
|
*
|
|
* (C) Copyright 1998 Microsoft Corp. All rights reserved.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <tchar.h>
|
|
#include <Windows.h>
|
|
#include <multimon.h>
|
|
#include <stdio.h>
|
|
#include <dplobby.h>
|
|
#include "resource.h"
|
|
#include "reginfo.h"
|
|
#include "sysinfo.h"
|
|
#include "dispinfo.h" // for TestResult
|
|
#include "fileinfo.h" // for GetFileVersion
|
|
#include "netinfo.h"
|
|
|
|
static HRESULT NewNetSP(NetInfo* pNetInfo, NetSP** ppNetSPNew);
|
|
static VOID DeleteNetSP(NetInfo* pNetInfo, NetSP* pNetSP);
|
|
static HRESULT NewNetApp(NetInfo* pNetInfo, NetApp** ppNetAppNew);
|
|
static HRESULT GetDX7ServiceProviders(NetInfo* pNetInfo);
|
|
static HRESULT GetDX8ServiceProviders(NetInfo* pNetInfo);
|
|
static HRESULT GetDX7LobbyableApps(NetInfo* pNetInfo);
|
|
static HRESULT GetDX8LobbyableApps(NetInfo* pNetInfo);
|
|
static BOOL ConvertStringToGUID(const WCHAR* strBuffer, GUID* lpguid);
|
|
|
|
/****************************************************************************
|
|
*
|
|
* GetNetInfo
|
|
*
|
|
****************************************************************************/
|
|
HRESULT GetNetInfo(SysInfo* pSysInfo, NetInfo** ppNetInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
NetInfo* pNetInfo;
|
|
|
|
pNetInfo = new NetInfo;
|
|
if (pNetInfo == NULL)
|
|
return E_OUTOFMEMORY;
|
|
*ppNetInfo = pNetInfo;
|
|
ZeroMemory(pNetInfo, sizeof(NetInfo));
|
|
|
|
if( FALSE == BIsIA64() )
|
|
{
|
|
if (FAILED(hr = GetDX7ServiceProviders(pNetInfo)))
|
|
return hr;
|
|
if (FAILED(hr = GetDX7LobbyableApps(pNetInfo)))
|
|
return hr;
|
|
}
|
|
|
|
if( pSysInfo->m_dwDirectXVersionMajor >= 8 )
|
|
{
|
|
if (FAILED(hr = GetDX8ServiceProviders(pNetInfo)))
|
|
return hr;
|
|
if (FAILED(hr = GetDX8LobbyableApps(pNetInfo)))
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* NewNetSP
|
|
*
|
|
****************************************************************************/
|
|
HRESULT NewNetSP(NetInfo* pNetInfo, NetSP** ppNetSPNew)
|
|
{
|
|
NetSP* pNetSPNew;
|
|
|
|
pNetSPNew = new NetSP;
|
|
if (pNetSPNew == NULL)
|
|
return E_OUTOFMEMORY;
|
|
ZeroMemory(pNetSPNew, sizeof(NetSP));
|
|
if (pNetInfo->m_pNetSPFirst == NULL)
|
|
{
|
|
pNetInfo->m_pNetSPFirst = pNetSPNew;
|
|
}
|
|
else
|
|
{
|
|
NetSP* pNetSP;
|
|
for (pNetSP = pNetInfo->m_pNetSPFirst;
|
|
pNetSP->m_pNetSPNext != NULL;
|
|
pNetSP = pNetSP->m_pNetSPNext)
|
|
{
|
|
}
|
|
pNetSP->m_pNetSPNext = pNetSPNew;
|
|
}
|
|
pNetSPNew->m_bRegistryOK = TRUE; // so far
|
|
*ppNetSPNew = pNetSPNew;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* DeleteNetSP
|
|
*
|
|
****************************************************************************/
|
|
VOID DeleteNetSP(NetInfo* pNetInfo, NetSP* pNetSP)
|
|
{
|
|
NetSP* pNetSPPrev = NULL;
|
|
NetSP* pNetSPCur;
|
|
for (pNetSPCur = pNetInfo->m_pNetSPFirst;
|
|
pNetSPCur != NULL;
|
|
pNetSPCur = pNetSPCur->m_pNetSPNext)
|
|
{
|
|
if (pNetSPCur == pNetSP)
|
|
{
|
|
if (pNetSPPrev == NULL)
|
|
pNetInfo->m_pNetSPFirst = pNetSPCur->m_pNetSPNext;
|
|
else
|
|
pNetSPPrev->m_pNetSPNext = pNetSPCur->m_pNetSPNext;
|
|
delete pNetSPCur;
|
|
return;
|
|
}
|
|
pNetSPPrev = pNetSPCur;
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* NewNetApp
|
|
*
|
|
****************************************************************************/
|
|
HRESULT NewNetApp(NetInfo* pNetInfo, NetApp** ppNetAppNew)
|
|
{
|
|
NetApp* pNetAppNew;
|
|
|
|
pNetAppNew = new NetApp;
|
|
if (pNetAppNew == NULL)
|
|
return E_OUTOFMEMORY;
|
|
ZeroMemory(pNetAppNew, sizeof(NetApp));
|
|
if (pNetInfo->m_pNetAppFirst == NULL)
|
|
{
|
|
pNetInfo->m_pNetAppFirst = pNetAppNew;
|
|
}
|
|
else
|
|
{
|
|
NetApp* pNetApp;
|
|
for (pNetApp = pNetInfo->m_pNetAppFirst;
|
|
pNetApp->m_pNetAppNext != NULL;
|
|
pNetApp = pNetApp->m_pNetAppNext)
|
|
{
|
|
}
|
|
pNetApp->m_pNetAppNext = pNetAppNew;
|
|
}
|
|
pNetAppNew->m_bRegistryOK = TRUE; // so far
|
|
*ppNetAppNew = pNetAppNew;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* GetDX7ServiceProviders
|
|
*
|
|
****************************************************************************/
|
|
HRESULT GetDX7ServiceProviders(NetInfo* pNetInfo)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey = NULL;
|
|
HKEY hkey2 = NULL;
|
|
DWORD dwIndex;
|
|
DWORD dwBufferLen;
|
|
BOOL bTCPIPFound = FALSE;
|
|
BOOL bIPXFound = FALSE;
|
|
BOOL bModemFound = FALSE;
|
|
BOOL bSerialFound = FALSE;
|
|
TCHAR szName[MAX_PATH+1];
|
|
NetSP* pNetSPNew;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectPlay\\Service Providers"), 0, KEY_READ, &hkey))
|
|
{
|
|
dwIndex = 0;
|
|
while (ERROR_SUCCESS == RegEnumKey(hkey, dwIndex, szName, MAX_PATH+1))
|
|
{
|
|
// Note: I'm not putting the following keyname strings into resources because
|
|
// they're supposed to be in English regardless of user's system (at least on DX6
|
|
// and higher--see another note below). If I put them into resources, they're
|
|
// more likely to get inadvertently localized.
|
|
if (lstrcmpi(szName, TEXT("Internet TCP/IP Connection For DirectPlay")) == 0)
|
|
bTCPIPFound = TRUE;
|
|
else if (lstrcmpi(szName, TEXT("IPX Connection For DirectPlay")) == 0)
|
|
bIPXFound = TRUE;
|
|
else if (lstrcmpi(szName, TEXT("Modem Connection For DirectPlay")) == 0)
|
|
bModemFound = TRUE;
|
|
else if (lstrcmpi(szName, TEXT("Serial Connection For DirectPlay")) == 0)
|
|
bSerialFound = TRUE;
|
|
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
{
|
|
RegCloseKey(hkey);
|
|
return hr;
|
|
}
|
|
|
|
pNetSPNew->m_dwDXVer = 7;
|
|
|
|
// The following line is the right thing to do on DX5, but in DX6 the
|
|
// name will get overwritten by the "DescriptionW" / "DescriptionA" string.
|
|
lstrcpy(pNetSPNew->m_szName, szName);
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, szName);
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, KEY_READ, &hkey2))
|
|
{
|
|
// Get (localized) connection name, if it exists
|
|
TCHAR szDescription[200];
|
|
lstrcpy(szDescription, TEXT(""));
|
|
dwBufferLen = 200;
|
|
RegQueryValueEx(hkey2,
|
|
// 25080: Always use DescriptionW because it's more localized
|
|
// than DescriptionA is.
|
|
TEXT("DescriptionW"),
|
|
0, NULL, (LPBYTE)szDescription, &dwBufferLen);
|
|
|
|
if (lstrlen(szDescription) > 0)
|
|
lstrcpy(pNetSPNew->m_szName, szDescription);
|
|
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("Guid"), 0, NULL, (LPBYTE)pNetSPNew->m_szGuid, &dwBufferLen))
|
|
{
|
|
// On DX5, the names of the registry keys for "Internet TCP/IP Connection
|
|
// For DirectPlay", etc. were localized, so we need to check GUIDs to avoid
|
|
// incorrectly thinking that some standard service providers are missing:
|
|
if (!bTCPIPFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{36E95EE0-8577-11cf-960C-0080C7534E82}")) == 0)
|
|
{
|
|
bTCPIPFound = TRUE;
|
|
}
|
|
if (!bIPXFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{685BC400-9D2C-11cf-A9CD-00AA006886E3}")) == 0)
|
|
{
|
|
bIPXFound = TRUE;
|
|
}
|
|
if (!bModemFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{44EAA760-CB68-11cf-9C4E-00A0C905425E}")) == 0)
|
|
{
|
|
bModemFound = TRUE;
|
|
}
|
|
if (!bSerialFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{0F1D6860-88D9-11cf-9C4E-00A0C905425E}")) == 0)
|
|
{
|
|
bSerialFound = TRUE;
|
|
}
|
|
|
|
// If a non-English DX5 system was upgraded to DX6, it will have BOTH localized
|
|
// and non-localized keynames for each service provider. The DX6 ones have
|
|
// "DescriptionA" and "DescriptionW" strings
|
|
// If a SP with this GUID has already been enumerated, replace it with the current
|
|
// one if the current one has a description. Otherwise forget about the current
|
|
// one.
|
|
NetSP* pNetSPSearch;
|
|
BOOL bFound = FALSE;
|
|
for (pNetSPSearch = pNetInfo->m_pNetSPFirst; pNetSPSearch != NULL; pNetSPSearch = pNetSPSearch->m_pNetSPNext)
|
|
{
|
|
if (pNetSPSearch == pNetSPNew)
|
|
continue;
|
|
if (lstrcmp(pNetSPSearch->m_szGuid, pNetSPNew->m_szGuid) == 0)
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (bFound)
|
|
{
|
|
if (lstrlen(szDescription) > 0)
|
|
{
|
|
// Current SP is better, nuke old one
|
|
DeleteNetSP(pNetInfo, pNetSPSearch);
|
|
}
|
|
else
|
|
{
|
|
// Old SP is (probably) better, nuke current one
|
|
DeleteNetSP(pNetInfo, pNetSPNew);
|
|
goto LDoneWithSubKey;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR* pszFile;
|
|
dwBufferLen = MAX_PATH;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("Path"), 0, NULL, (LPBYTE)szPath, &dwBufferLen))
|
|
{
|
|
// On Win9x, szPath is full path. On NT, it's leaf only.
|
|
pszFile = _tcsrchr(szPath, TEXT('\\'));
|
|
if (pszFile == NULL)
|
|
{
|
|
lstrcpy(pNetSPNew->m_szFile, szPath);
|
|
GetSystemDirectory(pNetSPNew->m_szPath, MAX_PATH);
|
|
lstrcat(pNetSPNew->m_szPath, TEXT("\\"));
|
|
lstrcat(pNetSPNew->m_szPath, szPath);
|
|
}
|
|
else
|
|
{
|
|
lstrcpy(pNetSPNew->m_szPath, szPath);
|
|
lstrcpy(pNetSPNew->m_szFile, pszFile + 1); // skip backslash
|
|
}
|
|
|
|
WIN32_FIND_DATA findFileData;
|
|
HANDLE hFind = FindFirstFile(pNetSPNew->m_szPath, &findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
pNetSPNew->m_bFileMissing = TRUE;
|
|
LoadString(NULL, IDS_FILEMISSING, pNetSPNew->m_szVersion, 50);
|
|
LoadString(NULL, IDS_FILEMISSING_ENGLISH, pNetSPNew->m_szVersionEnglish, 50);
|
|
}
|
|
else
|
|
{
|
|
FindClose(hFind);
|
|
GetFileVersion(pNetSPNew->m_szPath, pNetSPNew->m_szVersion,
|
|
NULL, NULL, NULL);
|
|
GetFileVersion(pNetSPNew->m_szPath, pNetSPNew->m_szVersionEnglish,
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
LDoneWithSubKey:
|
|
RegCloseKey(hkey2);
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
if (!bTCPIPFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("Internet TCP/IP Connection For DirectPlay"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("Internet TCP/IP Connection For DirectPlay"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
if (!bIPXFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("IPX Connection For DirectPlay"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("IPX Connection For DirectPlay"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
if (!bModemFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("Modem Connection For DirectPlay"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("Modem Connection For DirectPlay"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
if (!bSerialFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("Serial Connection For DirectPlay"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("Serial Connection For DirectPlay"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* GetDX8ServiceProviders
|
|
*
|
|
****************************************************************************/
|
|
HRESULT GetDX8ServiceProviders(NetInfo* pNetInfo)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey = NULL;
|
|
HKEY hkey2 = NULL;
|
|
HKEY hkeyDLL = NULL;
|
|
DWORD dwIndex;
|
|
DWORD dwBufferLen;
|
|
BOOL bTCPIPFound = FALSE;
|
|
BOOL bIPXFound = FALSE;
|
|
BOOL bModemFound = FALSE;
|
|
BOOL bSerialFound = FALSE;
|
|
TCHAR szName[MAX_PATH+1];
|
|
NetSP* pNetSPNew;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectPlay8\\Service Providers"), 0, KEY_READ, &hkey))
|
|
{
|
|
dwIndex = 0;
|
|
while (ERROR_SUCCESS == RegEnumKey(hkey, dwIndex, szName, MAX_PATH+1))
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
{
|
|
RegCloseKey(hkey);
|
|
return hr;
|
|
}
|
|
|
|
pNetSPNew->m_dwDXVer = 8;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, KEY_READ, &hkey2))
|
|
{
|
|
TCHAR szDescription[200];
|
|
lstrcpy(szDescription, TEXT(""));
|
|
TCHAR szEnglishDescription[200];
|
|
|
|
dwBufferLen = 200;
|
|
if (ERROR_SUCCESS == RegQueryValueEx( hkey2, TEXT("Friendly Name"), 0, NULL, (LPBYTE)szDescription, &dwBufferLen) )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
lstrcpy(szEnglishDescription, szDescription);
|
|
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("GUID"), 0, NULL, (LPBYTE)pNetSPNew->m_szGuid, &dwBufferLen))
|
|
{
|
|
WCHAR strBuffer[MAX_PATH];
|
|
#ifdef _UNICODE
|
|
wcscpy( strBuffer, pNetSPNew->m_szGuid );
|
|
#else
|
|
MultiByteToWideChar( CP_ACP, 0, pNetSPNew->m_szGuid, -1,
|
|
strBuffer, _tcslen(pNetSPNew->m_szGuid) );
|
|
#endif
|
|
ConvertStringToGUID( strBuffer, &pNetSPNew->m_guid );
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
TCHAR szRegKey[200];
|
|
wsprintf( szRegKey, TEXT("CLSID\\%s\\InprocServer32"), pNetSPNew->m_szGuid );
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szRegKey, 0, KEY_READ, &hkeyDLL))
|
|
{
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkeyDLL, NULL, 0, NULL, (LPBYTE)pNetSPNew->m_szFile, &dwBufferLen))
|
|
{
|
|
GetSystemDirectory(pNetSPNew->m_szPath, MAX_PATH);
|
|
lstrcat(pNetSPNew->m_szPath, TEXT("\\"));
|
|
lstrcat(pNetSPNew->m_szPath, pNetSPNew->m_szFile);
|
|
|
|
WIN32_FIND_DATA findFileData;
|
|
HANDLE hFind = FindFirstFile(pNetSPNew->m_szPath, &findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
pNetSPNew->m_bFileMissing = TRUE;
|
|
LoadString(NULL, IDS_FILEMISSING, pNetSPNew->m_szVersion, 50);
|
|
LoadString(NULL, IDS_FILEMISSING_ENGLISH, pNetSPNew->m_szVersionEnglish, 50);
|
|
}
|
|
else
|
|
{
|
|
FindClose(hFind);
|
|
GetFileVersion(pNetSPNew->m_szPath, pNetSPNew->m_szVersion,
|
|
NULL, NULL, NULL);
|
|
GetFileVersion(pNetSPNew->m_szPath, pNetSPNew->m_szVersionEnglish,
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hkeyDLL);
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
|
|
if (!bTCPIPFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{EBFE7BA0-628D-11D2-AE0F-006097B01411}")) == 0)
|
|
{
|
|
if( lstrcmpi(pNetSPNew->m_szFile, TEXT("dpnwsock.dll") ) != 0)
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
|
|
lstrcpy( szEnglishDescription, TEXT("DirectPlay8 TCP/IP Service Provider") );
|
|
bTCPIPFound = TRUE;
|
|
}
|
|
|
|
if (!bIPXFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{53934290-628D-11D2-AE0F-006097B01411}")) == 0)
|
|
{
|
|
if( lstrcmpi(pNetSPNew->m_szFile, TEXT("dpnwsock.dll") ) != 0)
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
|
|
lstrcpy( szEnglishDescription, TEXT("DirectPlay8 IPX Service Provider") );
|
|
bIPXFound = TRUE;
|
|
}
|
|
if (!bModemFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{6D4A3650-628D-11D2-AE0F-006097B01411}")) == 0)
|
|
{
|
|
if( lstrcmpi(pNetSPNew->m_szFile, TEXT("dpnmodem.dll") ) != 0)
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
|
|
lstrcpy( szEnglishDescription, TEXT("DirectPlay8 Modem Service Provider") );
|
|
bModemFound = TRUE;
|
|
}
|
|
if (!bSerialFound &&
|
|
lstrcmpi(pNetSPNew->m_szGuid, TEXT("{743B5D60-628D-11D2-AE0F-006097B01411}")) == 0)
|
|
{
|
|
if( lstrcmpi(pNetSPNew->m_szFile, TEXT("dpnmodem.dll") ) != 0)
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
|
|
lstrcpy( szEnglishDescription, TEXT("DirectPlay8 Serial Service Provider") );
|
|
bSerialFound = TRUE;
|
|
}
|
|
|
|
lstrcpy(pNetSPNew->m_szName, szDescription);
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, szEnglishDescription);
|
|
|
|
RegCloseKey(hkey2);
|
|
}
|
|
else
|
|
{
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
if (!bTCPIPFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("DirectPlay8 TCP/IP Service Provider"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("DirectPlay8 TCP/IP Service Provider"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
if (!bIPXFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("DirectPlay8 IPX Service Provider"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("DirectPlay8 IPX Service Provider"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
if (!bModemFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("DirectPlay8 Modem Service Provider"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("DirectPlay8 Modem Service Provider"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
if (!bSerialFound)
|
|
{
|
|
if (FAILED(hr = NewNetSP(pNetInfo, &pNetSPNew)))
|
|
return hr;
|
|
lstrcpy(pNetSPNew->m_szName, TEXT("DirectPlay8 Serial Service Provider"));
|
|
lstrcpy(pNetSPNew->m_szNameEnglish, TEXT("DirectPlay8 Serial Service Provider"));
|
|
pNetSPNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* GetDX7LobbyableApps
|
|
*
|
|
****************************************************************************/
|
|
HRESULT GetDX7LobbyableApps(NetInfo* pNetInfo)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey = NULL;
|
|
HKEY hkey2 = NULL;
|
|
DWORD dwIndex;
|
|
DWORD dwBufferLen;
|
|
TCHAR szName[MAX_PATH+1];
|
|
NetApp* pNetAppNew;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectPlay\\Applications"), 0, KEY_READ, &hkey))
|
|
{
|
|
dwIndex = 0;
|
|
while (ERROR_SUCCESS == RegEnumKey(hkey, dwIndex, szName, MAX_PATH+1))
|
|
{
|
|
BOOL bSkip = FALSE;
|
|
|
|
// Bug 37989: skip any dplay app that has the DPLAPP_NOENUM flag set.
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, KEY_READ, &hkey2))
|
|
{
|
|
dwBufferLen = MAX_PATH;
|
|
DWORD dwFlags = 0;
|
|
dwBufferLen = sizeof(DWORD);
|
|
DWORD dwType = 0;
|
|
RegQueryValueEx(hkey2, TEXT("dwFlags"), 0, &dwType, (LPBYTE)&dwFlags, &dwBufferLen);
|
|
if( (dwFlags & DPLAPP_NOENUM) != 0 )
|
|
bSkip = TRUE;
|
|
RegCloseKey(hkey2);
|
|
}
|
|
|
|
if( bSkip )
|
|
{
|
|
dwIndex++;
|
|
continue;
|
|
}
|
|
|
|
if (FAILED(hr = NewNetApp(pNetInfo, &pNetAppNew)))
|
|
{
|
|
RegCloseKey(hkey);
|
|
return hr;
|
|
}
|
|
lstrcpy(pNetAppNew->m_szName, szName);
|
|
pNetAppNew->m_dwDXVer = 7;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, KEY_READ, &hkey2))
|
|
{
|
|
dwBufferLen = MAX_PATH;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("Path"), 0, NULL, (LPBYTE)pNetAppNew->m_szExePath, &dwBufferLen))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("File"), 0, NULL, (LPBYTE)pNetAppNew->m_szExeFile, &dwBufferLen))
|
|
{
|
|
lstrcat(pNetAppNew->m_szExePath, TEXT("\\"));
|
|
lstrcat(pNetAppNew->m_szExePath, pNetAppNew->m_szExeFile);
|
|
|
|
WIN32_FIND_DATA findFileData;
|
|
HANDLE hFind = FindFirstFile(pNetAppNew->m_szExePath, &findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
pNetAppNew->m_bFileMissing = TRUE;
|
|
LoadString(NULL, IDS_FILEMISSING, pNetAppNew->m_szExeVersion, 50);
|
|
LoadString(NULL, IDS_FILEMISSING, pNetAppNew->m_szExeVersionEnglish, 50);
|
|
}
|
|
else
|
|
{
|
|
FindClose(hFind);
|
|
GetFileVersion(pNetAppNew->m_szExePath, pNetAppNew->m_szExeVersion,
|
|
NULL, NULL, NULL);
|
|
GetFileVersion(pNetAppNew->m_szExePath, pNetAppNew->m_szExeVersionEnglish,
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("Guid"), 0, NULL, (LPBYTE)pNetAppNew->m_szGuid, &dwBufferLen))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hkey2);
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* GetDX8LobbyableApps
|
|
*
|
|
****************************************************************************/
|
|
HRESULT GetDX8LobbyableApps(NetInfo* pNetInfo)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey = NULL;
|
|
HKEY hkey2 = NULL;
|
|
DWORD dwIndex;
|
|
DWORD dwBufferLen;
|
|
TCHAR szGuid[MAX_PATH+1];
|
|
NetApp* pNetAppNew;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\DirectPlay8\\Applications"), 0, KEY_READ, &hkey))
|
|
{
|
|
dwIndex = 0;
|
|
while (ERROR_SUCCESS == RegEnumKey(hkey, dwIndex, szGuid, MAX_PATH+1))
|
|
{
|
|
if (FAILED(hr = NewNetApp(pNetInfo, &pNetAppNew)))
|
|
{
|
|
RegCloseKey(hkey);
|
|
return hr;
|
|
}
|
|
lstrcpy(pNetAppNew->m_szGuid, szGuid);
|
|
pNetAppNew->m_dwDXVer = 8;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szGuid, 0, KEY_READ, &hkey2))
|
|
{
|
|
dwBufferLen = MAX_PATH;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("ExecutablePath"), 0, NULL, (LPBYTE)pNetAppNew->m_szExePath, &dwBufferLen))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("ExecutableFilename"), 0, NULL, (LPBYTE)pNetAppNew->m_szExeFile, &dwBufferLen))
|
|
{
|
|
lstrcat(pNetAppNew->m_szExePath, TEXT("\\"));
|
|
lstrcat(pNetAppNew->m_szExePath, pNetAppNew->m_szExeFile);
|
|
|
|
WIN32_FIND_DATA findFileData;
|
|
HANDLE hFind = FindFirstFile(pNetAppNew->m_szExePath, &findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
pNetAppNew->m_bFileMissing = TRUE;
|
|
LoadString(NULL, IDS_FILEMISSING, pNetAppNew->m_szExeVersion, 50);
|
|
LoadString(NULL, IDS_FILEMISSING, pNetAppNew->m_szExeVersionEnglish, 50);
|
|
}
|
|
else
|
|
{
|
|
FindClose(hFind);
|
|
GetFileVersion(pNetAppNew->m_szExePath, pNetAppNew->m_szExeVersion,
|
|
NULL, NULL, NULL);
|
|
GetFileVersion(pNetAppNew->m_szExePath, pNetAppNew->m_szExeVersionEnglish,
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
|
|
dwBufferLen = MAX_PATH;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("LauncherPath"), 0, NULL, (LPBYTE)pNetAppNew->m_szLauncherPath, &dwBufferLen))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("LauncherFilename"), 0, NULL, (LPBYTE)pNetAppNew->m_szLauncherFile, &dwBufferLen))
|
|
{
|
|
lstrcat(pNetAppNew->m_szLauncherPath, TEXT("\\"));
|
|
lstrcat(pNetAppNew->m_szLauncherPath, pNetAppNew->m_szLauncherFile);
|
|
|
|
WIN32_FIND_DATA findFileData;
|
|
HANDLE hFind = FindFirstFile(pNetAppNew->m_szLauncherPath, &findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
pNetAppNew->m_bFileMissing = TRUE;
|
|
LoadString(NULL, IDS_FILEMISSING, pNetAppNew->m_szLauncherVersion, 50);
|
|
LoadString(NULL, IDS_FILEMISSING, pNetAppNew->m_szLauncherVersionEnglish, 50);
|
|
}
|
|
else
|
|
{
|
|
FindClose(hFind);
|
|
GetFileVersion(pNetAppNew->m_szExePath, pNetAppNew->m_szLauncherVersion,
|
|
NULL, NULL, NULL);
|
|
GetFileVersion(pNetAppNew->m_szExePath, pNetAppNew->m_szLauncherVersionEnglish,
|
|
NULL, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
|
|
dwBufferLen = 100;
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey2, TEXT("ApplicationName"), 0, NULL, (LPBYTE)pNetAppNew->m_szName, &dwBufferLen))
|
|
{
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
|
|
RegCloseKey(hkey2);
|
|
}
|
|
else
|
|
{
|
|
pNetAppNew->m_bRegistryOK = FALSE;
|
|
}
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* DestroyNetInfo
|
|
*
|
|
****************************************************************************/
|
|
VOID DestroyNetInfo(NetInfo* pNetInfo)
|
|
{
|
|
if( pNetInfo )
|
|
{
|
|
NetSP* pNetSP;
|
|
NetSP* pNetSPNext;
|
|
|
|
for (pNetSP = pNetInfo->m_pNetSPFirst; pNetSP != NULL;
|
|
pNetSP = pNetSPNext)
|
|
{
|
|
pNetSPNext = pNetSP->m_pNetSPNext;
|
|
delete pNetSP;
|
|
}
|
|
|
|
NetApp* pNetApp;
|
|
NetApp* pNetAppNext;
|
|
|
|
for (pNetApp = pNetInfo->m_pNetAppFirst; pNetApp != NULL;
|
|
pNetApp = pNetAppNext)
|
|
{
|
|
pNetAppNext = pNetApp->m_pNetAppNext;
|
|
delete pNetApp;
|
|
}
|
|
|
|
delete pNetInfo;
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* DiagnoseNetInfo
|
|
*
|
|
****************************************************************************/
|
|
VOID DiagnoseNetInfo(SysInfo* pSysInfo, NetInfo* pNetInfo)
|
|
{
|
|
NetSP* pNetSP;
|
|
NetApp* pNetApp;
|
|
TCHAR szMessage[500];
|
|
TCHAR szFmt[500];
|
|
BOOL bProblem = FALSE;
|
|
BOOL bShouldReinstall = FALSE;
|
|
|
|
_tcscpy( pSysInfo->m_szNetworkNotes, TEXT("") );
|
|
_tcscpy( pSysInfo->m_szNetworkNotesEnglish, TEXT("") );
|
|
|
|
// Report any problems
|
|
if( pNetInfo != NULL )
|
|
{
|
|
for (pNetSP = pNetInfo->m_pNetSPFirst; pNetSP != NULL; pNetSP = pNetSP->m_pNetSPNext)
|
|
{
|
|
if (!pNetSP->m_bRegistryOK)
|
|
{
|
|
LoadString(NULL, IDS_SPREGISTRYERRORFMT, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetSP->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotes, szMessage);
|
|
|
|
LoadString(NULL, IDS_SPREGISTRYERRORFMT_ENGLISH, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetSP->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotesEnglish, szMessage);
|
|
|
|
pNetSP->m_bProblem = TRUE;
|
|
bProblem = TRUE;
|
|
bShouldReinstall = TRUE;
|
|
}
|
|
else if (pNetSP->m_bFileMissing)
|
|
{
|
|
LoadString(NULL, IDS_FILEMISSING, pNetSP->m_szVersion, 50);
|
|
LoadString(NULL, IDS_SPFILEMISSINGFMT, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetSP->m_szFile, pNetSP->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotes, szMessage);
|
|
|
|
LoadString(NULL, IDS_FILEMISSING_ENGLISH, pNetSP->m_szVersion, 50);
|
|
LoadString(NULL, IDS_SPFILEMISSINGFMT_ENGLISH, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetSP->m_szFile, pNetSP->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotesEnglish, szMessage);
|
|
|
|
pNetSP->m_bProblem = TRUE;
|
|
bShouldReinstall = TRUE;
|
|
bProblem = TRUE;
|
|
}
|
|
}
|
|
for (pNetApp = pNetInfo->m_pNetAppFirst; pNetApp != NULL; pNetApp = pNetApp->m_pNetAppNext)
|
|
{
|
|
if (!pNetApp->m_bRegistryOK)
|
|
{
|
|
LoadString(NULL, IDS_APPREGISTRYERRORFMT, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetApp->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotes, szMessage);
|
|
|
|
LoadString(NULL, IDS_APPREGISTRYERRORFMT_ENGLISH, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetApp->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotesEnglish, szMessage);
|
|
|
|
pNetApp->m_bProblem = TRUE;
|
|
bProblem = TRUE;
|
|
}
|
|
/* 26298: Don't scare users with this warning...it's usually harmless:
|
|
else if (pNetApp->m_bFileMissing)
|
|
{
|
|
LoadString(NULL, IDS_FILEMISSING, pNetApp->m_szVersion, 50);
|
|
LoadString(NULL, IDS_APPFILEMISSINGFMT, szFmt, 500);
|
|
wsprintf(szMessage, szFmt, pNetApp->m_szFile, pNetApp->m_szName);
|
|
_tcscat(pSysInfo->m_szNetworkNotes, szMessage);
|
|
pNetApp->m_bProblem = TRUE;
|
|
bProblem = TRUE;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bProblem = TRUE;
|
|
bShouldReinstall = TRUE;
|
|
}
|
|
|
|
if( bShouldReinstall )
|
|
{
|
|
BOOL bTellUser = FALSE;
|
|
|
|
// Figure out if the user can install DirectX
|
|
if( BIsPlatform9x() )
|
|
bTellUser = TRUE;
|
|
else if( BIsWin2k() && pSysInfo->m_dwDirectXVersionMajor >= 8 )
|
|
bTellUser = TRUE;
|
|
|
|
if( bTellUser )
|
|
{
|
|
LoadString(NULL, IDS_REINSTALL_DX, szMessage, 500);
|
|
_tcscat( pSysInfo->m_szNetworkNotes, szMessage);
|
|
|
|
LoadString(NULL, IDS_REINSTALL_DX_ENGLISH, szMessage, 500);
|
|
_tcscat( pSysInfo->m_szNetworkNotesEnglish, szMessage);
|
|
}
|
|
}
|
|
|
|
if (!bProblem)
|
|
{
|
|
LoadString(NULL, IDS_NOPROBLEM, szMessage, 500);
|
|
_tcscat(pSysInfo->m_szNetworkNotes, szMessage);
|
|
|
|
LoadString(NULL, IDS_NOPROBLEM_ENGLISH, szMessage, 500);
|
|
_tcscat(pSysInfo->m_szNetworkNotesEnglish, szMessage);
|
|
}
|
|
|
|
// Show test results or instructions to run test:
|
|
if (pNetInfo && pNetInfo->m_testResult.m_bStarted)
|
|
{
|
|
LoadString(NULL, IDS_DPLAYRESULTS, szMessage, 500);
|
|
_tcscat( pSysInfo->m_szNetworkNotes, szMessage );
|
|
_tcscat( pSysInfo->m_szNetworkNotes, pNetInfo->m_testResult.m_szDescription );
|
|
_tcscat( pSysInfo->m_szNetworkNotes, TEXT("\r\n") );
|
|
|
|
LoadString(NULL, IDS_DPLAYRESULTS_ENGLISH, szMessage, 500);
|
|
_tcscat( pSysInfo->m_szNetworkNotesEnglish, szMessage );
|
|
_tcscat( pSysInfo->m_szNetworkNotesEnglish, pNetInfo->m_testResult.m_szDescriptionEnglish );
|
|
_tcscat( pSysInfo->m_szNetworkNotesEnglish, TEXT("\r\n") );
|
|
}
|
|
else
|
|
{
|
|
LoadString(NULL, IDS_DPLAYINSTRUCTIONS, szMessage, 500);
|
|
_tcscat(pSysInfo->m_szNetworkNotes, szMessage);
|
|
|
|
LoadString(NULL, IDS_DPLAYINSTRUCTIONS_ENGLISH, szMessage, 500);
|
|
_tcscat(pSysInfo->m_szNetworkNotesEnglish, szMessage);
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* ConvertStringToGUID
|
|
*
|
|
****************************************************************************/
|
|
BOOL ConvertStringToGUID(const WCHAR* strBuffer, GUID* lpguid)
|
|
{
|
|
UINT aiTmp[10];
|
|
|
|
if( swscanf( strBuffer, L"{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}",
|
|
&lpguid->Data1,
|
|
&aiTmp[0], &aiTmp[1],
|
|
&aiTmp[2], &aiTmp[3],
|
|
&aiTmp[4], &aiTmp[5],
|
|
&aiTmp[6], &aiTmp[7],
|
|
&aiTmp[8], &aiTmp[9] ) != 11 )
|
|
{
|
|
ZeroMemory(lpguid, sizeof(GUID));
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
lpguid->Data2 = (USHORT) aiTmp[0];
|
|
lpguid->Data3 = (USHORT) aiTmp[1];
|
|
lpguid->Data4[0] = (BYTE) aiTmp[2];
|
|
lpguid->Data4[1] = (BYTE) aiTmp[3];
|
|
lpguid->Data4[2] = (BYTE) aiTmp[4];
|
|
lpguid->Data4[3] = (BYTE) aiTmp[5];
|
|
lpguid->Data4[4] = (BYTE) aiTmp[6];
|
|
lpguid->Data4[5] = (BYTE) aiTmp[7];
|
|
lpguid->Data4[6] = (BYTE) aiTmp[8];
|
|
lpguid->Data4[7] = (BYTE) aiTmp[9];
|
|
return TRUE;
|
|
}
|
|
}
|