windows-nt/Source/XPSP1/NT/multimedia/directx/ddrawex/factory.cpp
2020-09-26 16:20:57 +08:00

359 lines
9.2 KiB
C++

/*==========================================================================
*
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
*
* File: factory.cpp
* Content: DirectDraw Factory support
* History:
* Date By Reason
* ==== == ======
* 24-feb-97 ralphl initial implementation
* 25-feb-97 craige minor tweaks for dx checkin
* 14-mar-97 jeffort version checking changed to support DX3 and above
* 09-apr-97 jeffort version checking added for DX2 and NT
* 30-apr-97 jeffort version >DX5 treated as DX5
* 10-jul-97 jeffort made OSVersion a static variable
* 09-sep-97 mikear QI for IUnknown when aggregating
***************************************************************************/
#include "ddfactry.h"
//#defines for registry lookup
#define REGSTR_PATH_DDRAW "Software\\Microsoft\\DirectDraw"
#define REGSTR_VAL_DDRAW_OWNDC "OWNDC"
CDDFactory::CDDFactory(IUnknown *pUnkOuter) :
m_cRef(1),
m_pUnkOuter(pUnkOuter != 0 ? pUnkOuter : CAST_TO_IUNKNOWN(this))
{
m_hDDrawDLL = NULL;
DllAddRef();
}
STDAPI DirectDrawFactory_CreateInstance(
IUnknown * pUnkOuter,
REFIID riid,
void ** ppv)
{
HRESULT hr;
CDDFactory *pFactory = new CDDFactory(pUnkOuter);
if( !pFactory )
{
hr = E_OUTOFMEMORY;
}
else
{
hr = pFactory->NonDelegatingQueryInterface(pUnkOuter ? IID_IUnknown : riid, ppv);
pFactory->NonDelegatingRelease();
}
return hr;
}
STDMETHODIMP CDDFactory::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
*ppv=NULL;
if (IID_IUnknown==riid)
{
*ppv=(INonDelegatingUnknown *)this;
}
else
{
if (IID_IDirectDrawFactory==riid)
{
*ppv=(IDirectDrawFactory *)this;
}
else
{
return E_NOINTERFACE;
}
}
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG) CDDFactory::NonDelegatingAddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CDDFactory::NonDelegatingRelease()
{
LONG lRefCount = InterlockedDecrement(&m_cRef);
if( lRefCount )
{
return lRefCount;
}
delete this;
DllRelease();
return 0;
}
// Standard IUnknown
STDMETHODIMP CDDFactory::QueryInterface(REFIID riid, void ** ppv)
{
return m_pUnkOuter->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG) CDDFactory::AddRef(void)
{
return m_pUnkOuter->AddRef();
}
STDMETHODIMP_(ULONG) CDDFactory::Release(void)
{
return m_pUnkOuter->Release();
}
/*
* CDDFactory::CreateDirectDraw
*/
STDMETHODIMP CDDFactory::CreateDirectDraw(
GUID * pGUID,
HWND hWnd,
DWORD dwCoopLevelFlags,
DWORD dwReserved,
IUnknown *pUnkOuter,
IDirectDraw **ppDirectDraw )
{
static OSVERSIONINFO osVer;
CDirectDrawEx *pDirectDrawEx;
HRESULT hr = S_OK;
BOOL fDDrawDllVerFound = FALSE;
*ppDirectDraw = NULL;
/*
* first, see if we can get at DirectDraw or not!
*/
if( m_hDDrawDLL == NULL )
{
char path[_MAX_PATH];
char DllName[25];
DWORD dwRet;
// m_hDDrawDLL = LoadLibrary( "ddraw.dll" );
dwRet = GetProfileString("ddrawex","realdll","ddraw.dll",DllName,25);
if( dwRet == 0 )
{
return DDERR_GENERIC;
}
m_hDDrawDLL = LoadLibrary( DllName );
if( m_hDDrawDLL == NULL )
{
return DDERR_LOADFAILED;
}
/*
* get ddraw.dll version number
*/
if( GetModuleFileName( (HINSTANCE)m_hDDrawDLL, path, sizeof( path ) ) )
{
int size;
DWORD tmp;
size = (int) GetFileVersionInfoSize( path, (LPDWORD) &tmp );
if( size != 0 )
{
LPVOID vinfo;
vinfo = (LPVOID) LocalAlloc( LPTR, size );
if(vinfo == NULL)
{
hr = DDERR_OUTOFMEMORY;
goto CleanUp;
}
if( GetFileVersionInfo( path, 0, size, vinfo ) )
{
VS_FIXEDFILEINFO *ver=NULL;
UINT cb;
if( VerQueryValue(vinfo, "\\", (LPVOID *)&ver, &cb) )
{
if( ver != NULL )
{
/*
* we only need the most significant dword,
* the LS dword contains the build number only...
* Hack: The '|5' forces recognition of DX6+
*/
m_dwDDVerMS = ver->dwFileVersionMS | 5;
fDDrawDllVerFound = TRUE;
}
}
}
LocalFree( vinfo );
}
}
osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if ( !fDDrawDllVerFound || !GetVersionEx(&osVer) )
{
hr = DDERR_BADVERSIONINFO;
goto CleanUp;
}
//if we are on NT4.0 Gold, the DLL version will be 4.00
if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT && LOWORD( m_dwDDVerMS) == 0)
{
//boost the LOWORD up so we will not fail the next check below
m_dwDDVerMS += 3;
}
/*
* don't work on anything but DX2 DX 3 or DX 5.
*/
if( !((HIWORD( m_dwDDVerMS ) >= 4) && (LOWORD( m_dwDDVerMS) >= 3)) )
{
hr = DDERR_UNSUPPORTED;
goto CleanUp;
}
if( LOWORD( m_dwDDVerMS) > 5)
{
//we will assume that any version >= DX5 will support what we need, so we
//will mark anything greater than 5 as DX5
m_dwDDVerMS = 5;
}
/*
* get the various entry points we need
*/
m_pDirectDrawCreate = (LPDIRECTDRAWCREATE) GetProcAddress((HINSTANCE) m_hDDrawDLL, "DirectDrawCreate" );
if( m_pDirectDrawCreate == NULL )
{
hr = DDERR_BADPROCADDRESS;
goto CleanUp;
}
m_pDirectDrawEnumerateW = (LPDIRECTDRAWENUMW) GetProcAddress( (HINSTANCE)m_hDDrawDLL, "DirectDrawEnumerateW" );
if( m_pDirectDrawEnumerateW == NULL )
{
hr = DDERR_BADPROCADDRESS;
goto CleanUp;
}
m_pDirectDrawEnumerateA = (LPDIRECTDRAWENUMA) GetProcAddress((HINSTANCE) m_hDDrawDLL, "DirectDrawEnumerateA" );
if( m_pDirectDrawEnumerateA == NULL )
{
hr = DDERR_BADPROCADDRESS;
goto CleanUp;
}
} // m_hDDrawDLL = NULL
/*
* create and initialize the ddrawex object
*/
pDirectDrawEx = new CDirectDrawEx(pUnkOuter);
if( !pDirectDrawEx )
{
hr = DDERR_OUTOFMEMORY;
goto CleanUp;
}
else
{
hr = pDirectDrawEx->Init( pGUID, hWnd, dwCoopLevelFlags, dwReserved, m_pDirectDrawCreate );
if( SUCCEEDED(hr) )
{
hr = pDirectDrawEx->NonDelegatingQueryInterface(IID_IDirectDraw, (void **)ppDirectDraw);
/*
* save the ddraw version number...
*/
if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
if( LOWORD( m_dwDDVerMS ) == 5 )
{
DWORD type;
DWORD value;
DWORD cb;
HKEY hkey;
//DX5 is busted with OwnDC for StretchBlt
//check a registry key to see if we are
//using dx5 style or dx3 style.
//default is dx3
pDirectDrawEx->m_dwDDVer = WINNT_DX5;
if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
{
cb = sizeof( value );
if( ERROR_SUCCESS == RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_OWNDC, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
pDirectDrawEx->m_dwDDVer = WINNT_DX5;
}
RegCloseKey(hkey);
}
}
else if (LOWORD (m_dwDDVerMS) == 4 )
{
pDirectDrawEx->m_dwDDVer = WINNT_DX3;
}
else if (LOWORD (m_dwDDVerMS) == 3 )
{
pDirectDrawEx->m_dwDDVer = WINNT_DX2;
}
//should never get here, alread checked above, but be a bit anal
else
{
hr = DDERR_UNSUPPORTED;
goto CleanUp;
}
}
else
{
if( LOWORD( m_dwDDVerMS ) == 5 )
{
pDirectDrawEx->m_dwDDVer = WIN95_DX5;
}
else if (LOWORD (m_dwDDVerMS) == 4 )
{
pDirectDrawEx->m_dwDDVer = WIN95_DX3;
}
else if (LOWORD (m_dwDDVerMS) == 3 )
{
pDirectDrawEx->m_dwDDVer = WIN95_DX2;
}
//should never get here, alread checked above, but be a bit anal
else
{
hr = DDERR_UNSUPPORTED;
goto CleanUp;
}
}
}
pDirectDrawEx->NonDelegatingRelease();
}
CleanUp:
if( hr != S_OK && m_hDDrawDLL != NULL )
{
FreeLibrary((HINSTANCE) m_hDDrawDLL );
m_hDDrawDLL = NULL;
}
return hr;
} /* CDDFactory::CreateDirectDraw */
/*
* CDDFactory::DirectDrawEnumerate
*
* implements ddraw enumerate.
*/
STDMETHODIMP CDDFactory::DirectDrawEnumerate(LPDDENUMCALLBACK lpCallback, LPVOID lpContext)
{
#pragma message( REMIND( "DDFactory::DirectDrawEnumerate assumes ANSI" ))
return m_pDirectDrawEnumerateA(lpCallback, lpContext);
} /* CDDFactory::DirectDrawEnumerate */