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.
 
 
 
 
 
 

319 lines
5.8 KiB

// Copyright (c) 1997-1999 Microsoft Corporation
//
// Smart (Interface) pointer class
//
// 9-25-97 sburns
#ifndef SMARTPTR_HPP_INCLUDED
#define SMARTPTR_HPP_INCLUDED
namespace Burnslib
{
// Requires that T derive from IUnknown
template <class T>
class SmartInterface
{
public:
// need default ctor if we are to use STL containers to hold SmartInterfaces
SmartInterface()
:
#ifdef DBG
ptrGuard(0xDDDDDDDD),
#endif
ptr(0)
{
}
explicit
SmartInterface(T* p)
#ifdef DBG
:
ptrGuard(0xDDDDDDDD)
#endif
{
// don't assert(p), since construction w/ 0 is legal.
ptr = p;
if (ptr)
{
ptr->AddRef();
}
}
SmartInterface(const SmartInterface<T>& s)
#ifdef DBG
:
ptrGuard(0xDDDDDDDD)
#endif
{
// makes no sense to pass null pointers
ASSERT(s.ptr);
ptr = s.ptr;
if (ptr)
{
ptr->AddRef();
}
}
~SmartInterface()
{
Relinquish();
}
// Aquire means "take over from a dumb pointer, but don't AddRef it."
//
// This is used to take over ownership from a dumb pointer so that you
// don't have to remember to call Release on the dumb pointer.
//
// Example:
//
// SmartInterface<IFoo> smart(0);
// IFoo* dumb = 0;
//
// HRESULT hr =
// ::YourGetDumbPointerCall(
// __uuidof(IFoo),
// reinterpret_cast<void**>(&dumb));
// BREAK_ON_FAILED_HRESULT(hr);
//
// smart.Acquire(dumb);
//
// Don't call dumb->Release(), when smart dies it will release the
// pointer.
void
Acquire(T* p)
{
ASSERT(!ptr);
ptr = p;
}
HRESULT
AcquireViaQueryInterface(IUnknown& i)
{
return AcquireViaQueryInterface(i, __uuidof(T));
}
// fallback for those interfaces that are not
// declared w/ __declspec(uuid())
HRESULT
AcquireViaQueryInterface(IUnknown& i, const IID& interfaceDesired)
{
ASSERT(!ptr);
HRESULT hr =
i.QueryInterface(interfaceDesired, reinterpret_cast<void**>(&ptr));
// don't assert success, since we might just be testing to see
// if an interface is available.
return hr;
}
HRESULT
AcquireViaCreateInstance(
const CLSID& classID,
IUnknown* unknownOuter,
DWORD classExecutionContext)
{
return
AcquireViaCreateInstance(
classID,
unknownOuter,
classExecutionContext,
__uuidof(T));
}
// fallback for those interfaces that are not
// declared w/ __declspec(uuid())
HRESULT
AcquireViaCreateInstance(
const CLSID& classID,
IUnknown* unknownOuter,
DWORD classExecutionContext,
const IID& interfaceDesired)
{
ASSERT(!ptr);
HRESULT hr =
// REVIEWED-2002/02/18-sburns
// Callers of this function should make sure the flags do not allow for
// an out-of-proc create if the class only supports in-proc.
::CoCreateInstance(
classID,
unknownOuter,
classExecutionContext,
interfaceDesired,
reinterpret_cast<void**>(&ptr));
return hr;
}
void
Relinquish()
{
if (ptr)
{
ptr->Release();
ptr = 0;
}
}
operator T*() const
{
return ptr;
}
// this allows SmartInterface instances to be passed as the first
// parameter to AquireViaQueryInterface. Note that this is a conversion
// to IUnknown&, not IUnknown*. An operator IUnknown* would be ambiguous
// with respect to operator T*.
//
// (does not return a const IUnknown&, as COM interfaces are not const
// aware.)
operator IUnknown&() const
{
ASSERT(ptr);
return *(static_cast<IUnknown*>(ptr));
}
// don't appear to need this: less is better.
// T&
// operator*()
// {
// ASSERT(ptr);
// return *ptr;
// }
T*
operator->() const
{
ASSERT(ptr);
return ptr;
}
T*
operator=(T* rhs)
{
ASSERT(rhs);
if (ptr != rhs)
{
Relinquish();
ptr = rhs;
if (ptr)
{
ptr->AddRef();
}
}
return ptr;
}
// This is required by some STL container classes.
const SmartInterface<T>&
operator=(const SmartInterface<T>& rhs)
{
this->operator=(rhs.ptr);
return *this;
}
// // This might be a good idea, but std::list.erase chokes on it.
// ISSUE-2002/03/26-sburns maybe that's fixed w/ VS 7?
//
// T**
// operator& ()
// {
// ASSERT(!ptr);
//
// if (ptr)
// {
// return &ptr;
// }
// else
// {
// return 0;
// }
// }
private:
#ifdef DBG
// Some code that takes the address of an instance of this class is working
// by happy coincidence: that taking the address of an instance yields the
// same address as the ptr member. For chk builds, I am deliberately
// breaking that code by inserting a dummy guard value, so that &i != i.ptr
//
// You should not try to take the address of a SmartInterface in order to
// access the internal pointer. You should instead use one of the Acquire
// methods, or use a dumb pointer and then acquire it. Under no
// circumstances will we allow access to our internal state!
int ptrGuard;
#endif
T* ptr;
};
} // namespace Burnslib
#endif // SMARTPTR_HPP_INCLUDED