Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

650 lines
17 KiB

/*==========================================================================
*
* Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
*
* File: classfac.c
* Content: direct draw class factory code
*
* History:
* Date By Reason
* ==== == ======
* 24-dec-95 craige initial implementation
* 05-jan-96 kylej added interface structures
* 14-mar-96 colinmc added a class factory for clippers
* 22-mar-96 colinmc Bug 13316: uninitialized interfaces
* 22-oct-97 jeffno Merge class factories, add classfac for CLSID_DirectDrawFactory2
*
***************************************************************************/
#include "ddrawpr.h"
static IClassFactoryVtbl directDrawClassFactoryVtbl;
typedef struct DDRAWCLASSFACTORY
{
IClassFactoryVtbl *lpVtbl;
DWORD dwRefCnt;
CLSID TargetCLSID;
} DDRAWCLASSFACTORY, *LPDDRAWCLASSFACTORY;
#define VALIDEX_DIRECTDRAWCF_PTR( ptr ) \
( !IsBadWritePtr( ptr, sizeof( DDRAWCLASSFACTORY )) && \
(ptr->lpVtbl == &directDrawClassFactoryVtbl) )
/************************************************************
*
* DirectDraw Driver Class Factory Member Functions.
*
************************************************************/
#define DPF_MODNAME "DirectDrawClassFactory::QueryInterface"
/*
* DirectDrawClassFactory_QueryInterface
*/
STDMETHODIMP DirectDrawClassFactory_QueryInterface(
LPCLASSFACTORY this,
REFIID riid,
LPVOID *ppvObj )
{
LPDDRAWCLASSFACTORY pcf;
DPF( 2, A, "ClassFactory::QueryInterface" );
ENTER_DDRAW();
TRY
{
pcf = (LPDDRAWCLASSFACTORY)this;
if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
{
DPF_ERR( "Invalid this ptr" );
LEAVE_DDRAW();
return E_FAIL;
}
if( !VALID_PTR_PTR( ppvObj ) )
{
DPF_ERR( "Invalid object ptr" );
LEAVE_DDRAW();
return E_INVALIDARG;
}
*ppvObj = NULL;
if( !VALID_IID_PTR( riid ) )
{
DPF_ERR( "Invalid iid ptr" );
LEAVE_DDRAW();
return E_INVALIDARG;
}
if( IsEqualIID(riid, &IID_IClassFactory) ||
IsEqualIID(riid, &IID_IUnknown))
{
pcf->dwRefCnt++;
*ppvObj = this;
LEAVE_DDRAW();
return S_OK;
}
else
{
DPF( 0, "E_NOINTERFACE" );
LEAVE_DDRAW();
return E_NOINTERFACE;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
} /* DirectDrawClassFactory_QueryInterface */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawClassFactory::AddRef"
/*
* DirectDrawClassFactory_AddRef
*/
STDMETHODIMP_(ULONG) DirectDrawClassFactory_AddRef( LPCLASSFACTORY this )
{
LPDDRAWCLASSFACTORY pcf;
ENTER_DDRAW();
TRY
{
pcf = (LPDDRAWCLASSFACTORY)this;
if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
{
DPF_ERR( "Invalid this ptr" );
LEAVE_DDRAW();
return (ULONG)E_FAIL;
}
pcf->dwRefCnt++;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return (ULONG)E_INVALIDARG;
}
DPF( 5, "ClassFactory::AddRef, dwRefCnt=%ld", pcf->dwRefCnt );
LEAVE_DDRAW();
return pcf->dwRefCnt;
} /* DirectDrawClassFactory_AddRef */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawClassFactory::Release"
/*
* DirectDrawClassFactory_Release
*/
STDMETHODIMP_(ULONG) DirectDrawClassFactory_Release( LPCLASSFACTORY this )
{
LPDDRAWCLASSFACTORY pcf;
ENTER_DDRAW();
TRY
{
pcf = (LPDDRAWCLASSFACTORY)this;
if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
{
DPF_ERR( "Invalid this ptr" );
LEAVE_DDRAW();
return (ULONG)E_FAIL;
}
pcf->dwRefCnt--;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return (ULONG)E_INVALIDARG;
}
DPF( 5, "ClassFactory::Release, dwRefCnt=%ld", pcf->dwRefCnt );
if( pcf->dwRefCnt != 0 )
{
LEAVE_DDRAW();
return pcf->dwRefCnt;
}
MemFree( pcf );
LEAVE_DDRAW();
return 0;
} /* DirectDrawClassFactory_Release */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawClassFactory::CreateInstance"
/*
* DirectDrawClassFactory_CreateInstance
*
* Creates an instance of a DirectDraw object
*/
STDMETHODIMP DirectDrawClassFactory_CreateInstance(
LPCLASSFACTORY this,
LPUNKNOWN pUnkOuter,
REFIID riid,
LPVOID *ppvObj
)
{
HRESULT hr = DD_OK;
LPDDRAWI_DIRECTDRAW_INT pdrv_int = NULL;
LPDDRAWCLASSFACTORY pcf;
LPDIRECTDRAWCLIPPER pclipper;
DPF( 2, A, "ClassFactory::CreateInstance" );
pcf = (LPDDRAWCLASSFACTORY) this;
if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
{
DPF_ERR( "Invalid this ptr" );
return E_INVALIDARG;
}
if( !VALIDEX_IID_PTR( riid ) )
{
DPF_ERR( "Invalid iid ptr" );
return E_INVALIDARG;
}
if( !VALIDEX_PTR_PTR( ppvObj ) )
{
DPF_ERR( "Invalid object ptr" );
return E_INVALIDARG;
}
#ifdef POSTPONED
if (pUnkOuter && !IsEqualIID(riid,&IID_IUnknown))
{
DPF_ERR("Can't aggregate with a punkouter != IUnknown");
return CLASS_E_NOAGGREGATION;
}
#else
if (pUnkOuter)
{
return CLASS_E_NOAGGREGATION;
}
#endif
/*
* is DirectDraw supported on this system?
*/
if( !DirectDrawSupported( TRUE ) )
{
DPF_ERR( "DirectDraw not supported!" );
return E_FAIL;
}
/*
* go build an DirectDraw interface
*
* NOTE: We provide the "uninitialized callback table
* to prevent the use of this object for anything other
* than AddRef(), Release() or Initialized().
*/
ENTER_DDRAW();
if ( IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDraw ) ||
IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDraw7 ) )
{
if ( IsEqualIID(riid, &IID_IUnknown) )
{
/*
* If we're aggregated, then we don't need to worry about the IUnknown being
* the runtime identity (we are hidden inside the outer, since it's the one
* that will field the QI for IUnknown).
* This means we can point an aggregated interface at the nondelegating
* unknowns
*/
if (pUnkOuter)
{
#ifdef POSTPONED
pdrv_int = NewDriverInterface( NULL, &ddUninitNonDelegatingUnknownCallbacks );
#else
pdrv_int = NewDriverInterface( NULL, &ddUninitCallbacks );
#endif
}
else
{
/*
* Not aggregated, so the IUnknown has to have the same pointer value
* as the IDirectDraw interfaces, since QI always simply returns the
* this ptr when asked for IUnknown
* (Note this actually doesn't work right now because Initalize will swap
* vtbls).
*/
pdrv_int = NewDriverInterface( NULL, &ddUninitCallbacks );
}
}
else if ( IsEqualIID(riid, &IID_IDirectDraw) )
{
pdrv_int = NewDriverInterface( NULL, &ddUninitCallbacks );
}
else if ( IsEqualIID(riid, &IID_IDirectDraw2) )
{
pdrv_int = NewDriverInterface( NULL, &dd2UninitCallbacks );
}
else if ( IsEqualIID(riid, &IID_IDirectDraw4) )
{
pdrv_int = NewDriverInterface( NULL, &dd4UninitCallbacks );
}
else if ( IsEqualIID(riid, &IID_IDirectDraw7) )
{
pdrv_int = NewDriverInterface( NULL, &dd7UninitCallbacks );
}
if( NULL == pdrv_int )
{
DPF( 0, "Call to NewDriverInterface failed" );
hr = E_OUTOFMEMORY;
}
#ifdef POSTPONED
/*
*
*/
if (pUnkOuter)
{
pdrv_int->lpLcl->pUnkOuter = pUnkOuter;
}
else
{
pdrv_int->lpLcl->pUnkOuter = (IUnknown*) &UninitNonDelegatingIUnknownInterface;
}
#endif
pdrv_int->dwIntRefCnt--;
pdrv_int->lpLcl->dwLocalRefCnt--;
/*
* NOTE: We call DD_QueryInterface() explicitly rather than
* going through the vtable as the "uninitialized" interface
* we are using here has QueryInterface() disabled.
*/
if (SUCCEEDED(hr))
{
hr = DD_QueryInterface( (LPDIRECTDRAW) pdrv_int, riid, ppvObj );
if( FAILED( hr ) )
{
DPF( 0, "Could not get interface id, hr=%08lx", hr );
RemoveLocalFromList( pdrv_int->lpLcl );
RemoveDriverFromList( pdrv_int, FALSE );
MemFree( pdrv_int->lpLcl );
MemFree( pdrv_int );
}
else
{
DPF( 5, "New Interface=%08lx", *ppvObj );
}
}
}
else
if ( IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDrawClipper ) )
{
/*
* Build a new clipper.
*
* Unlike the DirectDraw driver objects, clippers create via
* CoCreateInstance() are born pretty much initialized. The only
* thing initialization might actually do is to reparent the
* clipper to a given driver object. Otherwise all Initialize()
* does is set a flag.
*/
hr = InternalCreateClipper( NULL, 0UL, &pclipper, NULL, FALSE, NULL, NULL );
if( FAILED( hr ) )
{
DPF_ERR( "Failed to create the new clipper interface" );
}
/*
* NOTE: Bizarre code fragment below works as follows:
*
* 1) InternalCreateClipper() returns a clipper with a reference count
* of 1 for each of the interface, local and global objects.
* 2) QueryInterface() can do one of two things. It can either just return
* the same interface in which case the interface, local and global
* objects all get a reference count of 2 or it can return a different
* interface in which case both interfaces have a reference count of
* 1 and the local and global objects have a reference count of 2.
* 3) The immediate Release() following the QueryInterface() will in either
* case decrement the reference counts of the local and global objects
* to 1 (as required). If the same interface was returned by
* QueryInterface() then its reference count is decremented to 1 (as
* required). If a different interface was returned then the old
* interface is decremented to zero and it is released (as required).
* Also, if QueryInterface() fails, the Release() will decrement all
* the reference counts to 0 and the object will be freed.
*
* So it all makes perfect sense - really! (CMcC)
*
* ALSO NOTE: We call DD_Clipper_QueryInterface() explicitly rather than
* going through the vtable as the "uninitialized" interface we are using
* here has QueryInterface() disabled.
*/
hr = DD_Clipper_QueryInterface( pclipper, riid, ppvObj );
DD_Clipper_Release( pclipper );
if( FAILED( hr ) )
{
DPF( 0, "Could not get interface id, hr=%08lx", hr );
}
else
{
DPF( 5, "New Interface=%08lx", *ppvObj );
}
}
#ifdef POSTPONED
else if ( IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDrawFactory2) )
{
LPDDFACTORY2 lpDDFac = NULL;
/*
* Build a new DirectDrawFactory2
* This returns an object, with refcnt=0. The QI then bumps that to 1.
*/
hr = InternalCreateDDFactory2( &lpDDFac, pUnkOuter );
if( SUCCEEDED( hr ) )
{
/*
* The QI should catch that the vtable is the ddrawfactory2 vtable,
* and simply bump the addref on the passed-in pointer. This means we
* won't orphan the pointer created by InternalCreateDDFactory2.
*/
hr = ((IUnknown*)lpDDFac)->lpVtbl->QueryInterface( (IUnknown*)lpDDFac, riid, ppvObj );
if( SUCCEEDED( hr ) )
{
DPF( 5, "New DDFactory2 Interface=%08lx", *ppvObj );
}
else
{
MemFree(lpDDFac);
DPF( 0, "Could not get DDFactory2 interface id, hr=%08lx", hr );
}
}
else
{
DPF_ERR( "Failed to create the new dd factory2 interface" );
}
}
#endif
LEAVE_DDRAW();
return hr;
} /* DirectDrawClassFactory_CreateInstance */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawClassFactory::LockServer"
/*
* DirectDrawClassFactory_LockServer
*
* Called to force our DLL to stayed loaded
*/
STDMETHODIMP DirectDrawClassFactory_LockServer(
LPCLASSFACTORY this,
BOOL fLock
)
{
HRESULT hr;
HANDLE hdll;
LPDDRAWCLASSFACTORY pcf;
pcf = (LPDDRAWCLASSFACTORY) this;
if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
{
DPF_ERR( "Invalid this ptr" );
return E_INVALIDARG;
}
/*
* call CoLockObjectExternal
*/
DPF( 2, A, "ClassFactory::LockServer" );
hr = E_UNEXPECTED;
hdll = LoadLibrary( "OLE32.DLL" );
if( hdll != NULL )
{
HRESULT (WINAPI * lpCoLockObjectExternal)(LPUNKNOWN, BOOL, BOOL );
lpCoLockObjectExternal = (LPVOID) GetProcAddress( hdll, "CoLockObjectExternal" );
if( lpCoLockObjectExternal != NULL )
{
hr = lpCoLockObjectExternal( (LPUNKNOWN) this, fLock, TRUE );
}
else
{
DPF_ERR( "Error! Could not get procaddr for CoLockObjectExternal" );
}
}
else
{
DPF_ERR( "Error! Could not load OLE32.DLL" );
}
/*
* track the number of server locks total
*/
if( SUCCEEDED( hr ) )
{
ENTER_DDRAW();
if( fLock )
{
dwLockCount++;
}
else
{
#ifdef DEBUG
if( (int) dwLockCount <= 0 )
{
DPF( 0, "Invalid LockCount in LockServer! (%d)", dwLockCount );
DEBUG_BREAK();
}
#endif
dwLockCount--;
}
DPF( 5, "LockServer:dwLockCount =%ld", dwLockCount );
LEAVE_DDRAW();
}
return hr;
} /* DirectDrawClassFactory_LockServer */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawClassFactory::CreateInstance"
static IClassFactoryVtbl directDrawClassFactoryVtbl =
{
DirectDrawClassFactory_QueryInterface,
DirectDrawClassFactory_AddRef,
DirectDrawClassFactory_Release,
DirectDrawClassFactory_CreateInstance,
DirectDrawClassFactory_LockServer
};
#undef DPF_MODNAME
#define DPF_MODNAME "DllGetClassObject"
/*
* DllGetClassObject
*
* Entry point called by COM to get a ClassFactory pointer
*/
HRESULT WINAPI DllGetClassObject(
REFCLSID rclsid,
REFIID riid,
LPVOID *ppvObj )
{
LPDDRAWCLASSFACTORY pcf;
HRESULT hr;
/*
* validate parms
*/
if( !VALIDEX_PTR_PTR( ppvObj ) )
{
DPF_ERR( "Invalid object ptr" );
return E_INVALIDARG;
}
*ppvObj = NULL;
if( !VALIDEX_IID_PTR( rclsid ) )
{
DPF_ERR( "Invalid clsid ptr" );
return E_INVALIDARG;
}
if( !VALIDEX_IID_PTR( riid ) )
{
DPF_ERR( "Invalid iid ptr" );
return E_INVALIDARG;
}
/*
* is this one our class ids?
*/
if( IsEqualCLSID( rclsid, &CLSID_DirectDraw ) ||
IsEqualCLSID( rclsid, &CLSID_DirectDraw7 ) ||
IsEqualCLSID( rclsid, &CLSID_DirectDrawClipper ) ||
IsEqualCLSID( rclsid, &CLSID_DirectDrawFactory2 ))
{
/*
* It's the DirectDraw driver class ID.
*/
/*
* only allow IUnknown and IClassFactory
*/
if( !IsEqualIID( riid, &IID_IUnknown ) &&
!IsEqualIID( riid, &IID_IClassFactory ) )
{
return E_NOINTERFACE;
}
/*
* create a class factory object
*/
ENTER_DDRAW();
pcf = MemAlloc( sizeof( DDRAWCLASSFACTORY ) );
if( pcf == NULL )
{
LEAVE_DDRAW();
return E_OUTOFMEMORY;
}
pcf->lpVtbl = &directDrawClassFactoryVtbl;
pcf->dwRefCnt = 0;
memcpy(&pcf->TargetCLSID,rclsid,sizeof(*rclsid));
#pragma message( REMIND( "Do we need to have a refcnt of 0 after DllGetClassObject?" ))
hr = DirectDrawClassFactory_QueryInterface( (LPCLASSFACTORY) pcf, riid, ppvObj );
if( FAILED( hr ) )
{
MemFree( pcf );
*ppvObj = NULL;
DPF( 0, "QueryInterface failed, rc=%08lx", hr );
}
else
{
DPF( 5, "DllGetClassObject succeeded, pcf=%08lx", pcf );
}
LEAVE_DDRAW();
return hr;
}
else
{
return E_FAIL;
}
} /* DllGetClassObject */
/*
* DllCanUnloadNow
*
* Entry point called by COM to see if it is OK to free our DLL
*/
HRESULT WINAPI DllCanUnloadNow( void )
{
HRESULT hr;
DPF( 2, A, "DllCanUnloadNow called" );
hr = S_FALSE;
ENTER_DDRAW();
/*
* Only unload if there are no driver objects and no global
* clipper objects (there won't be any local clipper objects
* as they are destroyed by their driver so the check on driver
* object handles them).
*/
if( ( lpDriverObjectList == NULL ) &&
( lpDriverLocalList == NULL ) &&
( lpGlobalClipperList == NULL ) )
{
if( dwLockCount == 0 )
{
DPF( 3, "It is OK to unload" );
hr = S_OK;
}
}
LEAVE_DDRAW();
return hr;
} /* DllCanUnloadNow */