windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/dvdcheck/dvddetect/dvddetect.cpp
2020-09-26 16:20:57 +08:00

846 lines
25 KiB
C++

// DvdCheck.cpp : Determine if DVD exists on a system. Differentiate between MCI and DirectShow Solutions
//
// Modified 3/31/99 by Steve Rowe (strowe)
// Modified 2000/10/11 by Glenn Evans (glenne) to hunt down version & company names & MCI solutions
//
#include <streams.h>
#include <windows.h>
#include <initguid.h>
#include <uuids.h>
#include "DvdDetect.h"
#include "crc32.h"
DVDResult::DVDResult()
: m_pName( NULL )
, m_pCompanyName( NULL )
, m_Version( 0 )
, m_fFound( false )
, m_dwCRC( 0 )
{
SetName( TEXT("") );
SetCompanyName( TEXT("") );
}
DVDResult::~DVDResult()
{
delete [] m_pName;
delete [] m_pCompanyName;
}
static TCHAR* CloneString( const TCHAR* pStr )
{
if( pStr ) {
TCHAR* pNew = new TCHAR[ lstrlen( pStr ) +1 ];
if( pNew ) {
lstrcpy( pNew, pStr );
return pNew;
}
}
return NULL;
}
void DVDResult::SetVersion( UINT64 version)
{
m_Version = version;
}
void DVDResult::SetCRC( DWORD CRC)
{
m_dwCRC = CRC;
}
void DVDResult::SetFound( bool fFound)
{
m_fFound = fFound;
}
void DVDResult::SetName( const TCHAR* pName )
{
delete [] m_pName;
m_pName = CloneString( pName );
}
void DVDResult::SetCompanyName( const TCHAR* pName )
{
delete [] m_pCompanyName;
m_pCompanyName = CloneString( pName );
}
// NOTE: strmiids.lib is necessary for this to compile.
// This is the KSProxy GUID.
DEFINE_GUID(DVD_KSPROXY, 0x17CCA71BL, 0xECD7, 0x11D0, 0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22,
0x31, 0x96);
//
// More or less lifted from the w2k SFP code
//
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
};
static HRESULT GetFileVersion (const TCHAR* pszFile, // file
DVDResult& result
)
{
DWORD dwSize, dwHandle;
VS_FIXEDFILEINFO *pFixedVersionInfo;
DWORD dwVersionInfoSize;
DWORD dwReturnCode;
dwSize = GetFileVersionInfoSize( const_cast<TCHAR *>(pszFile), &dwHandle);
HRESULT hr = S_OK;
// .txt and .inf, etc files might not have versions
if( dwSize == 0 )
{
dwReturnCode = GetLastError();
hr = E_FAIL;
} else {
LPVOID pVersionInfo= new BYTE [dwSize];
if( NULL == pVersionInfo) {
hr = E_OUTOFMEMORY;
} else {
if( !GetFileVersionInfo( const_cast<TCHAR *>(pszFile), dwHandle, dwSize, pVersionInfo ) ) {
dwReturnCode = GetLastError();
DbgLog((LOG_ERROR, 1, TEXT("Error in GetFileVersionInfo for %s. ec=%d"),
pszFile, dwReturnCode));
hr = E_FAIL;
} else {
if( !VerQueryValue( pVersionInfo,
TEXT("\\"), // we need the root block
(LPVOID *) &pFixedVersionInfo,
(PUINT) &dwVersionInfoSize ) )
{
dwReturnCode = GetLastError();
hr = E_FAIL;
} else {
result.SetVersion( ((UINT64(pFixedVersionInfo->dwFileVersionMS))<<32) + pFixedVersionInfo->dwFileVersionLS);
}
// Structure used to store enumerated languages and code pages.
// Read the list of languages and code pages.
LANGANDCODEPAGE *lpTranslate;
UINT cbTranslate;
if( VerQueryValue(pVersionInfo,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID*)&lpTranslate,
&cbTranslate) )
{
// Read the file description for each language and code page.
for( DWORD i=0; i < (cbTranslate/sizeof(struct LANGANDCODEPAGE)); i++ )
{
TCHAR SubBlock[512];
// Retrieve file description for language and code page "i".
TCHAR* lpBuffer;
UINT dwBytes;
wsprintf( SubBlock,
TEXT("\\StringFileInfo\\%04x%04x\\CompanyName"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
if( VerQueryValue(pVersionInfo,
SubBlock,
(VOID **)&lpBuffer,
&dwBytes) )
{
result.SetCompanyName( lpBuffer );
}
}
}
}
delete [] pVersionInfo;
}
}
return hr;
}
static bool EndsIn( const TCHAR* pStr, const TCHAR* pExtension )
{
int iExtLen = lstrlen( pExtension );
int iStrLen = lstrlen( pStr );
if( iStrLen >= iExtLen ) {
return lstrcmp( &pStr[iStrLen - iExtLen], pExtension ) == 0;
} else {
return false;
}
}
#define MAKE_VER_NUM( v1, v2, v3, v4 ) (((UINT64(v1) << 16 | (v2) )<<16 | (v3) ) << 16 | (v4) )
static void StrCpy( TCHAR* pDest, WCHAR* pSrc, int iDestSize )
{
#ifdef UNICODE
lstrcpyn(pDest, pSrc, iDestSize );
#else
WideCharToMultiByte(
CP_ACP,
0, // flags
pSrc, // src
-1, // cch
pDest, // dest
iDestSize, // cb
0, // lpDefaultChar
0); // lpUsedDefaultChar
#endif
}
static HRESULT GetFilenameFromCLSID( const VARIANT& varFilterClsid, TCHAR szFilename[ MAX_PATH ] )
{
HRESULT hr = E_FAIL;
TCHAR szKey[512];
TCHAR szQuery[512];
// Convert BSTR to string and free variant storage
StrCpy( szQuery, varFilterClsid.bstrVal, sizeof( szQuery )/ sizeof( szQuery[0]) );
SysFreeString(varFilterClsid.bstrVal);
// Create key name for reading filename registry
wsprintf(szKey, TEXT("Software\\Classes\\CLSID\\%s\\InprocServer32\0"),
szQuery);
// Variables needed for registry query
HKEY hkeyFilter=0;
DWORD dwSize=MAX_PATH;
int rc=0;
// Open the CLSID key that contains information about the filter
rc = RegOpenKey(HKEY_LOCAL_MACHINE, szKey, &hkeyFilter);
if (rc == ERROR_SUCCESS)
{
rc = RegQueryValueEx(hkeyFilter, NULL, // Read (Default) value
NULL, NULL, (BYTE *)szFilename, &dwSize);
if (rc == ERROR_SUCCESS)
{
hr = S_OK;
}
rc = RegCloseKey(hkeyFilter);
}
return hr;
}
static const TCHAR* FilenameFromPathname( const TCHAR* pStr )
{
const TCHAR* pSlash=0;
const TCHAR* pOrig = pStr;
while( *pStr ) {
if( *pStr == TEXT('\\') ) {
pSlash = pStr;
}
pStr++;
}
if( pSlash ) {
return pSlash +1;
} else {
return pOrig;
}
}
static bool GetFileLength( const TCHAR* pszPathname, ULONGLONG* pullFileSize )
{
WIN32_FIND_DATA wInfo;
HANDLE hInfo = FindFirstFile( pszPathname, &wInfo );
FindClose(hInfo);
if (hInfo!=INVALID_HANDLE_VALUE) {
if( pullFileSize ) {
*pullFileSize = (ULONGLONG(wInfo.nFileSizeHigh) << 32) | wInfo.nFileSizeLow;
}
return true;
} else {
if( pullFileSize ) {
*pullFileSize = 0;
}
return false;
}
}
static DWORD CRCFromFile( const TCHAR* pFile )
{
ULONGLONG length;
DWORD dwCRC = 0;
if( GetFileLength( pFile, &length )) {
BYTE* pBuffer = new BYTE[ULONG(length)];
if( pBuffer ) {
HANDLE hFile = ::CreateFile( pFile,
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if( hFile != INVALID_HANDLE_VALUE ) {
DWORD dwActual;
if( ReadFile( hFile, pBuffer, ULONG(length), &dwActual, NULL ) ) {
dwCRC=CRC32( pBuffer, ULONG(length));
}
CloseHandle( hFile );
}
delete [] pBuffer;
}
}
return dwCRC;
}
static HRESULT AddSWFilter( IMoniker* pMon, DVDResult& result )
{
IPropertyBag *pPropBag;
HRESULT hr = pMon->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
if(SUCCEEDED(hr))
{
CLSID filterCLSID;
HRESULT hrGotFilename=E_FAIL;
TCHAR szFilename[ MAX_PATH ];
// open clsid/{filter-clsid} key
VARIANT varbstrClsid;
varbstrClsid.vt = VT_BSTR;
varbstrClsid.bstrVal = 0;
hr = pPropBag->Read(L"CLSID", &varbstrClsid, 0);
if(SUCCEEDED(hr)) {
ASSERT(varbstrClsid.vt == VT_BSTR);
WCHAR *strFilter = varbstrClsid.bstrVal;
if (CLSIDFromString(varbstrClsid.bstrVal, &filterCLSID) == S_OK) {
}
hrGotFilename = GetFilenameFromCLSID( varbstrClsid, szFilename );
SysFreeString(varbstrClsid.bstrVal);
}
pPropBag->Release();
if ( DVD_KSPROXY == filterCLSID || CLSID_AVIDec == filterCLSID ) {
; // ignore this filter if it is the AVI Decompressor or KSProxy
} else {
if( S_OK == hrGotFilename ) {
HRESULT hres = GetFileVersion( szFilename, result );
if( S_OK == hres ) {
result.SetName( FilenameFromPathname( szFilename ));
result.SetFound( true );
result.SetCRC( CRCFromFile( szFilename ));
}
}
}
} else {
DbgLog((LOG_ERROR, 1, TEXT("ERROR: WARNING: BindToStorage failed"))) ;
return E_UNEXPECTED;
}
return S_OK;
}
static HRESULT AddHWFilter( IMoniker* pMon, DVDResult& result )
{
IPropertyBag *pPropBag;
HRESULT hr = pMon->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
if(SUCCEEDED(hr))
{
result.SetFound( true );
VARIANT var ;
var.vt = VT_EMPTY ;
hr = pPropBag->Read(L"FriendlyName", &var, 0) ;
if (SUCCEEDED(hr))
{
DbgLog((LOG_TRACE, 5, TEXT("FriendlyName: %S"), var.bstrVal)) ;
//
// We have got a device under the required category. The proxy
// for it is already instantiated. So add to the list of HW
// decoders to be used for building the graph.
//
TCHAR szName[512];
// Convert BSTR to string and free variant storage
StrCpy( szName, var.bstrVal, sizeof( szName )/ sizeof( szName[0]) );
result.SetName( szName );
VariantClear(&var) ;
}
else
{
ASSERT(SUCCEEDED(hr)) ; // so that we know
result.SetName( TEXT("generic HW") );
}
pPropBag->Release();
} else {
DbgLog((LOG_ERROR, 1, TEXT("ERROR: WARNING: BindToStorage failed"))) ;
return E_UNEXPECTED;
}
return S_OK;
}
// Check if there are any SW DVD Decoders
static HRESULT SWCheck(DVDResult& result)
{
HRESULT hres = S_OK; // result for the function
HRESULT hr; // temporary result...
// Create filter mapper to find software decoders
IFilterMapper2 * pMapper ; // filter mapper object pointer
hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC,
IID_IFilterMapper2, (LPVOID *)&pMapper) ;
if (FAILED(hr) || NULL == pMapper)
{
DbgLog((LOG_ERROR, 0,
TEXT("ERROR: Couldn't create class FilterMapper for DVD SW Dec category (Error 0x%lx)"),
hr)) ;
ASSERT( !"Can't create filtermapper" );
return E_UNEXPECTED;
}
const UINT NUM_TYPES = 3; // the number of type/subtype pairs
GUID types[NUM_TYPES * 2];
types[0] = MEDIATYPE_MPEG2_PES;
types[1] = MEDIASUBTYPE_MPEG2_VIDEO;
types[2] = MEDIATYPE_DVD_ENCRYPTED_PACK;
types[3] = MEDIASUBTYPE_MPEG2_VIDEO;
types[4] = MEDIATYPE_Video;
types[5] = MEDIASUBTYPE_MPEG2_VIDEO;
IEnumMoniker *pEnumMon = NULL ;
hr = pMapper->EnumMatchingFilters(&pEnumMon, 0, TRUE, MERIT_DO_NOT_USE+1,
TRUE, NUM_TYPES, types, NULL, NULL, FALSE, TRUE, 0, NULL,
NULL, NULL);
if (FAILED(hr) || NULL == pEnumMon)
{
DbgLog((LOG_ERROR, 1, TEXT("ERROR: No matching filter enum found (Error 0x%lx)"), hr)) ;
pMapper->Release();
return E_UNEXPECTED;
}
// now we check if we have a solution.
// we ignore the AVI decompressor and KSProxy CLSID's.
ULONG ul ;
IMoniker *pMon = NULL;
while ( S_OK == pEnumMon->Next(1, &pMon, &ul) && 1 == ul)
{
hres = AddSWFilter( pMon, result );
}
// clean up after ourselves
if (NULL != pEnumMon) {
pEnumMon->Release();
}
if (NULL != pMapper) {
pMapper->Release();
}
if( hres == S_OK && !result.Found()==false ) {
return S_FALSE;
} else {
return hres;
}
} // end of SWCheck
static TCHAR CharUpper( TCHAR c )
{
// see the docs on CharUpper, single char if upper address WORD is NULL
return (TCHAR) CharUpper( (LPTSTR)c );
}
static void Truncate( TCHAR* pStr, const TCHAR* pTruncateAt )
{
int iTruncLen = lstrlen( pTruncateAt );
int iStrLen = lstrlen( pStr );
for( int i=0; i < iStrLen - iTruncLen; i++ ) {
for( int j=0; j < iTruncLen; j++ ) {
if( CharUpper( pStr[i+j] ) != pTruncateAt[j] ) {
goto NextLoop;
}
}
pStr[i+iTruncLen]=TEXT('\0');
break;
NextLoop:
;
}
}
// Determine if there are any MCI DVD devices present
static HRESULT MCICheck( DVDResult& result)
{
TCHAR lpRetString[255];
LPCTSTR lpDefault = TEXT("*!*");
GetPrivateProfileString(
TEXT("mci"),
TEXT("DVDVideo"),
lpDefault,
lpRetString,
255,
TEXT("system.ini") );
if (lstrcmp(lpRetString, lpDefault)) {// if they are not the same
// truncate ret string to *.drv
Truncate( lpRetString, TEXT(".DRV") );
result.SetName( lpRetString );
result.SetFound( true );
// try to hunt down version info
//
// File is in system
//
// Create key name for reading filename registry
TCHAR szPathname[MAX_PATH];
GetSystemDirectory( szPathname, sizeof(szPathname)/sizeof(szPathname[0]));
lstrcat( szPathname, TEXT("\\") );
lstrcat( szPathname, lpRetString );
HRESULT hres = GetFileVersion( szPathname, result );
if( S_OK == hres ) {
result.SetCRC( CRCFromFile( szPathname ));
} else {
GetWindowsDirectory( szPathname, sizeof(szPathname)/sizeof(szPathname[0]));
lstrcat( szPathname, TEXT("\\") );
lstrcat( szPathname, lpRetString );
hres = GetFileVersion( szPathname, result );
if( S_OK == hres ) {
result.SetCRC( CRCFromFile( szPathname ));
} else {
ASSERT(!"Can't find DVD MCI filename");
return S_FALSE;
}
}
return hres;
} else {
return S_FALSE; // can't really fail this check
}
} // end of MCICheck
// Check if there are any HW DVD Decoders
// we use DevEnum to check for DVDHWDecodersCategory
static HRESULT HWCheck(DVDResult& result)
{
ICreateDevEnum *pCreateDevEnum ;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum) ;
if (FAILED(hr) || NULL == pCreateDevEnum)
{
DbgLog((LOG_ERROR, 0, TEXT("WARNING: Couldn't create system dev enum (Error 0x%lx)"), hr)) ;
// need to put some better error handling in here
return E_UNEXPECTED;
}
IEnumMoniker *pEnumMon ;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_DVDHWDecodersCategory,
&pEnumMon, 0) ;
pCreateDevEnum->Release() ;
if (S_FALSE == hr )
{
// should indicate that we have no enumerator but not an error because
// this means there are no such devices.
DbgLog((LOG_ERROR, 0,
TEXT("WARNING: Couldn't create class enum for DVD HW Dec category (Error 0x%lx)"),
hr)) ;
return S_FALSE;
}
if (FAILED(hr) || NULL == pEnumMon)
{
DbgLog((LOG_ERROR, 0,
TEXT("ERROR: Couldn't create class enum for DVD HW Dec category (Error 0x%lx)"),
hr)) ;
return E_UNEXPECTED;
}
hr = pEnumMon->Reset() ;
ULONG ul ;
IMoniker *pMon ;
if (S_OK == pEnumMon->Next(1, &pMon, &ul) && 1 == ul) {
// Always comes back as WDM generic Filter Proxy (ksproxy.ax)
hr = AddHWFilter( pMon, result );
}
if (NULL != pEnumMon) {
pEnumMon->Release();
}
return result.Found() ? S_OK : S_FALSE;
} // end of HWCheck
HRESULT DVDDetect( DVDResult& mci, DVDResult& sw, DVDResult& hw )
// Primary entry point - will determine if any DVD is present
{
HRESULT hres = CoInitialize(NULL);
if( SUCCEEDED( hres )) {
//
// DSHOW HARDWARE CHECK
//
hres = HWCheck(hw);
if( SUCCEEDED( hres)) {
//
// DSHOW SOFTWARE CHECK
//
hres = SWCheck(sw);
if( SUCCEEDED( hres)) {
//
// MCI CHECK
//
hres = MCICheck(mci);
}
}
CoUninitialize();
} else {
ASSERT( !"Can't CoInit" );
}
return hres;
}
// Decoder exe CompanyName version crc
//
// Ravisent 2000 "QIDVDF.AX" "RAVISENT Technologies Inc." 1.2.0.115 0x786cd58f
// Ravisent (ATIPlayer) "QIDVDF.AX" "Quadrant International, Inc." 1.1.0.37 0x41a24b10
// Intervideo 1.31 (WinDVD) "IVIVIDEO.AX" " InterVideo Inc." 1.0.0.1 0xadf3b652 Will have to get version through registry
// Intervideo 2.111 (WinDVD) "IVIVIDEO.AX" " InterVideo Inc." 1.0.0.1 0x42b020f8
// Mediamatics "DVD Express AV Decoder.dll" "Mediamatics, Inc." 5.0.0.15
// 5.0.0.38
// 5.0.0.42
// 5.0.0.45
// 5.0.0.75 0xdf2fa5df
// 5.0.0.97
//
// MGI (SoftDVDMax) "ZVIDFLT.AX" "MGI Software Corp." 1.0.0.1 0x4d91884f
//
// MGI Build 00089 "DVDVideo.ax" "MGI Software Corp." 1.8.6.0 0x6bc2c0d4 can't find setup.ddl in Win2k, causes error in Whistler
// MGI Build 33959 "zvidflt.ax" "MGI Software Corp." 1.0.0.1 0x0482b35b works fine in both win2k and whistler
// MGI karaoke "zvidflt.ax" "MGI Software Corp." 1.0.0.1 0x4d91884f no disk in drive error on whistler, no windows 2000 compatible decoder on win2k
// MGI 4.00.0001 "zvidflt.ax" "MGI Software Corp." 1.0.0.1 0xd6a7abc3 works fin in both Win2k and Whistler
// MGI 5.0DH "zvidflt.ax" "MGI Software Corp." 1.0.0.1 0xd66f9452 works fine in both win2k and whistler
//
// Zoran 3.07.01 "Softpeg.drv" "" 0.0.0.0 0x0 Win2k cant install, whistler says software ot configured to run on your machine
// Zoran 3.25.02 "zvidflt.ax" "Zoran/CompCore Corp." 1.0.0.0 0x1e44e3d6 DVD Authentication error in whistler, no video or error in win2k
// Zoran 3.25.03 "Softpeg.drv" "" 0.0.0.0 0x0 drive not ready or no disk in drive on both win2k and whistler
// Cyberlink PowerDVD 2.50 "clvsd.ax" "CyberLink Corp." 2.0.0.0 0x964ef3b9 Generates errors in all dshow players in both Win2k and Whistler
// Cyberlink PowerDVD 2.5.5 "clvsd.ax "CyberLink Corp." 2.0.0.0 0x964ef3b9 Works fine in Whistler, Win2k there's no video
#define MAKE_VER_NUM( v1, v2, v3, v4 ) (((UINT64(v1) << 16 | (v2) )<<16 | (v3) ) << 16 | (v4) )
static bool AreEquivalent( const char* pStr1, const char* pStr2 )
{
return lstrcmpiA( pStr1, pStr2 ) ==0;
}
static bool AreEquivalent( const WCHAR* pStr1, const WCHAR* pStr2 )
{
return lstrcmpiW( pStr1, pStr2 ) ==0;
}
DecoderVendor DVDResult::GetVendor() const
{
const TCHAR* pName = GetCompanyName();
//TBD: vendor_NEC
if( AreEquivalent( pName, TEXT("Mediamatics, Inc.") )) {
return vendor_MediaMatics;
} else if( AreEquivalent( pName, TEXT(" InterVideo Inc.")) ) {
return vendor_Intervideo;
} else if( AreEquivalent( pName, TEXT("RAVISENT Technologies Inc.")) ||
AreEquivalent( pName, TEXT("Quadrant International, Inc.")) )
{
return vendor_Ravisent;
} else if( AreEquivalent( pName, TEXT("CyberLink Corp.")) ) {
return vendor_CyberLink;
} else if( AreEquivalent( pName, TEXT("MGI Software Corp.")) ||
AreEquivalent( pName, TEXT("Zoran/CompCore Corp.")) )
{
return vendor_MGI;
} else {
return vendor_Unknown;
}
}
#if 0
//
// only valid AFTER GUI setup and at first boot
//
static bool IsWin9xUpgrade()
{
// The answer file has the answer (system32\$winnt$.inf)
// [data]
// win9xupgrade=yes
TCHAR dir[MAX_PATH];
UINT uiResult = GetWindowsDirectory( dir, sizeof(dir)/sizeof(dir[0]) );
if( uiResult > 0 ) {
lstrcat( dir, TEXT("\\system32\\$winnt$.inf") );
TCHAR buffer[100];
buffer[0]=0;
DWORD dwResult = GetPrivateProfileString(
TEXT("data"), // section name
TEXT("win9xupgrade"), // key name
TEXT(""), // default string
buffer, // destination buffer
sizeof(buffer)/sizeof(buffer[0]), // size of destination buffer in TCHARS
dir );// initialization file name
bool fResult = ( dwResult > 0 ) && AreEquivalent( buffer, TEXT("yes") );
return fResult;
} else {
return true;
}
}
#endif
static bool DoesAspi32Exist( bool fWillBe9xUpgrade )
{
if( fWillBe9xUpgrade ) {
return false;
} else {
TCHAR szPathname[MAX_PATH];
GetWindowsDirectory( szPathname, sizeof(szPathname)/sizeof(szPathname[0]));
//
// NOTE: this will fail under Win9x (since its system\drivers) implying there isn't going
// to be an aspi32 under Whislter (blocked & deleted). So under 9x, we return true
// and under Whistler their apps only survive if its around.
//
lstrcat( szPathname, TEXT("\\system32\\drivers\\aspi32.sys") );
ULONGLONG ullLength;
return GetFileLength( szPathname, &ullLength );
}
}
bool DVDResult::ShouldUpgrade( bool fWillBe9xUpgrade ) const
{
switch( GetVendor() ) {
case vendor_MediaMatics:
return GetVersion() <= MAKE_VER_NUM( 5,1,0,5 ); // TBD: arbitrary right now for debugging purposes
// return GetVersion() <= MAKE_VER_NUM( 5,0,0,15 );
case vendor_Intervideo:
{
// so far all versions require aspi32
if( GetVersion() <= MAKE_VER_NUM(1,0,0,1 )) {
bool fAspiExists = DoesAspi32Exist(fWillBe9xUpgrade);
if( !fAspiExists ) {
return true;
}
}
// all unknown versions are 1.0.0.1
// We correct the known ones to numbers above that
switch( GetCRC()) {
case 0xadf3b652: // 1.31.0.0
return false;
case 0x42b020f8: // 2.111.0.0
return false;
default:
return true;
}
}
default:
return false;
}
}
DVDResult* DVDDetectBuffer::Detect()
{
if(SUCCEEDED(DVDDetect( mci, sw, hw )))
{
const DVDResult* pResult;
if( sw.Found()) {
return &sw;
} else if( mci.Found()) {
return &mci;
} else {
// hardware, so we don't care about the decoder OR the app for now
return NULL;
}
}
return NULL;
}
HRESULT DVDDetectBuffer::DetectAll()
{
return DVDDetect( mci, sw, hw );
}
#define RUN_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Run")
static bool RegSetRunValue( const TCHAR* pString, const TCHAR* pValue )
{
HKEY hRunKey;
LONG lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, RUN_KEY, 0, KEY_SET_VALUE, &hRunKey) ;
if (ERROR_SUCCESS == lRet) {
lRet = RegSetValueEx(hRunKey, pString, 0, REG_SZ, (BYTE *)pValue, sizeof(pValue[0])*(lstrlen(pValue)+1) );
RegCloseKey( hRunKey );
return ( ERROR_SUCCESS == lRet);
}
return false;
}
static bool RegRunDeleteValue( const TCHAR* pString )
{
HKEY hRunKey;
LONG lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RUN_KEY, 0, KEY_SET_VALUE, &hRunKey) ;
if (ERROR_SUCCESS == lRet) {
lRet = RegDeleteValue( hRunKey, pString ) ;
// either we nuked it or it didn't exist in the first place, either way its gone
bool fWorked = ( lRet == ERROR_SUCCESS || lRet == ERROR_FILE_NOT_FOUND );
ASSERT( fWorked ) ;
RegCloseKey( hRunKey );
return fWorked;
}
return false;
}
#define DVDUPGRADE_NAME TEXT("DVDUpgrade")
bool DVDDetectSetupRun::Remove()
{
bool fOk = RegRunDeleteValue( DVDUPGRADE_NAME );
ASSERT(fOk);
return fOk;
}
bool DVDDetectSetupRun::Add()
{
bool fOk;
fOk = RegSetRunValue( DVDUPGRADE_NAME, TEXT("DVDUpgrd.exe /upgrade"));
ASSERT(fOk);
return fOk;
}
extern "C" BOOL
IsDvdPresent (
VOID
)
{
DVDDetectBuffer buffer;
const DVDResult* pResult = buffer.Detect();
if( pResult ) {
const DVDResult& result = *pResult;
// at this point the $winnt$.inf doesn't exist, so we must assume
// that we're bing called from the win95upg
const bool fInWin9xUpgrade = true;
return result.ShouldUpgrade(fInWin9xUpgrade);
}
return false;
}