windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/w32extend.h
2020-09-26 16:20:57 +08:00

419 lines
13 KiB
C++

// w32extend.h - win32 helpers
// copyright (c) Microsoft Corp. 1998
#pragma once
#ifndef W32EXTEND_H
#define W32EXTEND_H
#include <guiddef.h>
#include <ocidl.h>
#include <urlmon.h>
#if defined(DEBUG) || defined(W32_OBJECT_STREAMING)
#include <atlconv.h>
#endif
using namespace ::ATL;
#include <atltmp.h>
#include <trace.h>
#include <throw.h>
// build a class to override the standard GUID in basetyps.h
// in order to put them into STL containers and dump them to debug
class GUID2 : public GUID {
private:
void init(const LPCOLESTR guid) {
OLECHAR temp[42]; // max guid string size
HRESULT hr = StringCchCopyW(temp, SIZEOF_CH(temp), guid);
if (FAILED(hr)) {
memset(this, 0, sizeof(GUID));
THROWCOM(hr);
}
hr = CLSIDFromString(temp, this);
if (FAILED(hr)) {
memset(this, 0, sizeof(GUID));
THROWCOM(hr);
}
}
public:
inline GUID2() : GUID(GUID_NULL) {}
inline GUID2(const GUID2 &g) : GUID(g) {}
inline GUID2(const struct _GUID &g) : GUID(g) {}
inline GUID2(const struct _GUID *g) : GUID(*g) {}
inline GUID2(const BSTR guid) {
if (!guid || !SysStringLen(guid)) {
memset(this, 0, sizeof(GUID));
} else {
init(guid);
}
}
inline GUID2(const LPCOLESTR guid) {
if (!guid || !ocslen(guid)) {
memset(this, 0, sizeof(GUID));
} else {
init(guid);
}
}
// operators
GUID2 & operator=(const BSTR guid) {
if (!guid || !SysStringLen(guid)) {
memset(this, 0, sizeof(GUID));
} else {
init(guid);
}
return *this;
}
GUID2& operator=(const LPCOLESTR guid) {
if (!guid || !ocslen(guid)) {
memset(this, 0, sizeof(GUID));
} else {
init(guid);
}
}
GUID2 & operator=(const GUID2 &g) {
if (&g != this) {
ASSERT(sizeof(*this) == sizeof(struct _GUID));
memcpy(this, &g, sizeof(GUID2));
}
return *this;
}
GUID2 & operator=(const struct _GUID &g) {
if (&g != this) {
ASSERT(sizeof(*this) == sizeof(g));
memcpy(this, &g, min(sizeof(GUID2), sizeof(GUID)));
}
return *this;
}
BSTR GetBSTR() const {
OLECHAR guidstr[(((sizeof(_GUID) * 2/* bin to char*/) + 1/*str null term*/) * 2/*ansi to unicode*/)];
int rc = StringFromGUID2(*this, guidstr, sizeof(guidstr)/sizeof(OLECHAR));
ASSERT(rc);
return SysAllocString(guidstr);
}
#if defined(DEBUG) || defined(W32_OBJECT_STREAMING)
void inline Dump(tostream &dc) const {
BSTR guidstr(GetBSTR());
USES_CONVERSION;
dc << OLE2T(guidstr);
::SysFreeString(guidstr);
return;
}
#endif
bool inline operator<(const GUID2 &op2) const {
if (memcmp(this, &op2, sizeof(GUID2)) < 0) {
return true;
}
return false;
}
bool inline operator>(const GUID2 &op2) const {
if (memcmp(this, &op2, sizeof(GUID2)) > 0) {
return true;
}
return false;
}
bool inline operator==(const GUID2 &op2) const {
if (!memcmp(this, &op2, sizeof(GUID2))) {
return true;
}
return false;
}
bool inline operator!=(const GUID2 &op2) const {
if (memcmp(this, &op2, sizeof(GUID2))) {
return true;
}
return false;
}
bool inline operator<(const GUID &op2) const {
if (memcmp(this, &op2, sizeof(GUID)) < 0) {
return true;
}
return false;
}
bool inline operator>(const GUID &op2) const {
if (memcmp(this, &op2, sizeof(GUID)) > 0) {
return true;
}
return false;
}
bool inline operator==(const GUID &op2) const {
if (!memcmp(this, &op2, sizeof(GUID))) {
return true;
}
return false;
}
bool inline operator!=(const GUID &op2) const {
if (memcmp(this, &op2, sizeof(GUID))) {
return true;
}
return false;
}
};
typedef CComPtr<IUnknown> PUnknown;
#if defined(DEBUG) || defined(W32_OBJECT_STREAMING)
inline tostream &operator<<(tostream &dc, const GUID2 &g)
{
g.Dump(dc);
return dc;
}
inline tostream &operator<<(tostream &dc, const GUID &g)
{
GUID2 g2(g);
g2.Dump(dc);
return dc;
}
inline tostream &operator<<(tostream &dc, const RECT& r)
{
dc << "T(" << r.top <<
") L(" << r.left <<
") B(" << r.bottom <<
") R(" << r.right <<
") W(" << (r.right - r.left) <<
") H(" << (r.bottom - r.top) << ")";
return dc;
}
inline tostream &operator<<(tostream &dc, const SIZE& s)
{
dc << "X(" << s.cx << ") Y(" << s.cy << ")";
return dc;
}
#if 0
inline tostream &operator<<(tostream &dc, ULONGLONG &ul) {
TCHAR buf[128];
_stprintf(buf, "%I64X", ul);
dc << buf;
return dc;
}
#endif
inline tostream &operator<<(tostream &dc, const VARIANT &v)
{
USES_CONVERSION;
switch (v.vt) {
case VT_UI4:
dc << _T("VT_UI4: ") << v.ulVal;
break;
case VT_UI8: {
dc << _T("VT_UI8: ");
TCHAR buf[128];
_ui64tot(v.ullVal, buf, 16);
dc << buf;
} break;
case VT_BSTR:
dc << _T("VT_BSTR: ") << OLE2T(v.bstrVal);
break;
case VT_UNKNOWN:
dc << _T("VT_UNKNOWN: ") << v.punkVal;
break;
case VT_DISPATCH:
dc << _T("VT_DISPATCH: ") << v.pdispVal;
break;
case VT_UI1 | VT_ARRAY:
dc << _T("VT_UI1 | VT_ARRAY: blob");
break;
default:
dc << std::endl << "cant dump variant. vt = " << v.vt << std::endl;
}
return dc;
}
#endif
inline bool operator!(const VARIANT &v) {
return v.vt == VT_EMPTY || v.vt == VT_NULL;
}
// provide an operator form and work around the fact that VarCmp
// only supports unsigned ints of size 1
inline bool operator==(const VARIANT &lhs, const VARIANT &rhs) {
HRESULT hrc = VarCmp(const_cast<VARIANT*>(&lhs),
const_cast<VARIANT*>(&rhs),
LOCALE_USER_DEFAULT,
0);
if (hrc == DISP_E_BADVARTYPE) {
// check for types VarCmp doesn't support that we need to support
// coerce unsigned to next largest signed if possible and then
// fall back to VarCmp for lowest risk way to get most identical
// behavior
// for UI8 which is max compiler supports we'll do the compare
// ourselves using the compiler support
switch (lhs.vt) {
case VT_UI2: {
VARIANT v;
VariantInit(&v);
hrc = VariantChangeTypeEx(&v, const_cast<VARIANT *>(&lhs), LOCALE_USER_DEFAULT, 0, VT_I4);
if (SUCCEEDED(hrc)) {
return operator==(v, rhs);
}
} break;
case VT_UI4: {
VARIANT v;
VariantInit(&v);
hrc = VariantChangeTypeEx(&v, const_cast<VARIANT *>(&lhs), LOCALE_USER_DEFAULT, 0, VT_I8);
if (SUCCEEDED(hrc)) {
return operator==(v, rhs);
}
} break;
case VT_UI8: {
if (rhs.vt == VT_UI8) {
return lhs.ullVal == rhs.ullVal;
}
VARIANT v;
VariantInit(&v);
hrc = VariantChangeTypeEx(&v, const_cast<VARIANT *>(&rhs), LOCALE_USER_DEFAULT, 0, VT_UI8);
if (SUCCEEDED(hrc)) {
return operator==(lhs, v);
}
} break;
default: {
// the problem is either lhs of some type we can't help with
// or its the rhs. so we'll check the rhs...
switch(rhs.vt) {
case VT_UI2: {
VARIANT v;
VariantInit(&v);
hrc = VariantChangeTypeEx(&v, const_cast<VARIANT *>(&rhs), LOCALE_USER_DEFAULT, 0, VT_I4);
if (SUCCEEDED(hrc)) {
return operator==(lhs, v);
}
} break;
case VT_UI4: {
VARIANT v;
VariantInit(&v);
hrc = VariantChangeTypeEx(&v, const_cast<VARIANT *>(&rhs), LOCALE_USER_DEFAULT, 0, VT_I8);
if (SUCCEEDED(hrc)) {
return operator==(lhs, v);
}
} break;
case VT_UI8: {
if (lhs.vt == VT_UI8) {
return lhs.ullVal == rhs.ullVal;
}
VARIANT v;
VariantInit(&v);
hrc = VariantChangeTypeEx(&v, const_cast<VARIANT *>(&lhs), LOCALE_USER_DEFAULT, 0, VT_UI8);
if (SUCCEEDED(hrc)) {
return operator==(v, rhs);
}
}}; //switch rhs
// must be some other bad type we can't help with
}}; //switch lhs
}
return (hrc == VARCMP_EQ);
}
inline bool operator!=(const VARIANT &lhs, const VARIANT &rhs) {
return !operator==(lhs, rhs);
}
typedef CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> PQEnumVARIANT;
typedef CComPtr<IUnknown> PUnknown;
typedef CComQIPtr<IPersist> PQPersist;
typedef CComQIPtr<IPropertyBag, &IID_IPropertyBag> PQPropertyBag;
typedef CComQIPtr<IPropertyBag2> PQPropertyBag2;
typedef CComQIPtr<IPersistPropertyBag> PQPersistPropertyBag;
typedef CComQIPtr<IPersistPropertyBag2> PQPersistPropertyBag2;
typedef CComQIPtr<IMoniker, &IID_IMoniker> PQMoniker;
typedef CComQIPtr<IBindCtx> PQBindCtx;
typedef CComQIPtr<IServiceProvider> PQServiceProvider;
typedef CComQIPtr<IGlobalInterfaceTable> PQGIT;
typedef CComQIPtr<IRunningObjectTable> PQROT;
typedef CComQIPtr<IOleWindow> PQOleWindow;
typedef CComQIPtr<IMalloc> PQMalloc;
typedef CComQIPtr<IObjectWithSite> PQObjectWithSite;
typedef CComQIPtr<IConnectionPoint> PQConnectionPoint;
typedef CComQIPtr<IInternetHostSecurityManager> PQSecurityManager;
class W32Moniker : public PQMoniker {
public:
inline W32Moniker() {}
inline W32Moniker(const PQMoniker &a) : PQMoniker(a) {}
inline W32Moniker(IMoniker *p) : PQMoniker(p) {}
inline W32Moniker(IUnknown *p) : PQMoniker(p) {}
inline W32Moniker(const W32Moniker &a) : PQMoniker(a) {}
PQPropertyBag GetPropertyBag() const {
PQPropertyBag pPropBag;
HRESULT hr = (*this)->BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast<LPVOID *>(&pPropBag));
if (FAILED(hr)) {
TRACELSM(TRACE_ERROR, (dbgDump << "W32Moniker::GetPropertyBag() can't bind to storage hr = " << hr), "");
THROWCOM(hr);
}
return pPropBag;
}
PUnknown GetObject() const {
PUnknown pObj;
HRESULT hr = (*this)->BindToObject(0, 0, __uuidof(IUnknown), reinterpret_cast<LPVOID *>(&pObj));
if (FAILED(hr)) {
TRACELSM(TRACE_ERROR, (dbgDump << "W32Moniker::GetObject() can't bind to object. hr = " << hr), "");
THROWCOM(hr);
}
return pObj;
}
CString DisplayName() const {
LPOLESTR lpszName;
HRESULT hr = (*this)->GetDisplayName(NULL, NULL, &lpszName);
if (FAILED(hr)) {
return CString();
}
CString rc(lpszName);
CoTaskMemFree(lpszName);
return rc;
}
};
inline HRESULT IsSafeZone(DWORD dwZone) {
switch (dwZone) {
case URLZONE_LOCAL_MACHINE:
case URLZONE_INTRANET:
case URLZONE_TRUSTED:
// the fixed list of zones we trust
return NOERROR;
default:
// everything else is untrusted
return E_FAIL;
}
}
inline HRESULT IsSafeSite(IUnknown* pSite) {
PQServiceProvider psp(pSite);
if (!psp) {
// no service provider interface on the site implies that we're not running in IE
// so by defn running local and trusted thus we return OK
return NOERROR;
}
PQSecurityManager pManager;
HRESULT hr = psp->QueryService(SID_SInternetHostSecurityManager, IID_IInternetHostSecurityManager, (LPVOID *)&pManager);
if (FAILED(hr)) {
// no security manager interface on the site's service provider implies that we're not
// running in IE, so by defn running local and trusted thus we return OK
return NOERROR;
}
const int MAXZONE = MAX_SIZE_SECURITY_ID+6/*scheme*/+4/*zone(dword)*/+1/*wildcard*/+1/*trailing null*/;
char pbSecurityId[MAXZONE];
DWORD pcbSecurityId = sizeof(pbSecurityId);
ZeroMemory(pbSecurityId, sizeof(pbSecurityId));
hr = pManager->GetSecurityId(reinterpret_cast<BYTE*>(pbSecurityId), &pcbSecurityId, NULL);
if(FAILED(hr)){
// security manager not working(unexpected). but, the site tried to provide one. thus we
// must assume untrusted content and fail
return E_FAIL;
}
char *pbEnd = pbSecurityId + pcbSecurityId - 1;
if (*pbEnd == '*') { //ignore the optional wildcard flag
pbEnd--;
}
pbEnd -= 3; // point to beginning of little endian zone dword
DWORD dwZone = *(reinterpret_cast<long *>(pbEnd));
return IsSafeZone(dwZone);
}
typedef CComQIPtr<IDispatch, &IID_IDispatch> PQDispatch;
#endif // w32extend.h