summaryrefslogtreecommitdiff
path: root/src/inc/winrt/paraminstanceapi.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc/winrt/paraminstanceapi.h')
-rw-r--r--src/inc/winrt/paraminstanceapi.h1749
1 files changed, 1749 insertions, 0 deletions
diff --git a/src/inc/winrt/paraminstanceapi.h b/src/inc/winrt/paraminstanceapi.h
new file mode 100644
index 0000000000..062c7f3d08
--- /dev/null
+++ b/src/inc/winrt/paraminstanceapi.h
@@ -0,0 +1,1749 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/***************************************************************
+
+*
+* Portions of this header fall under the following
+* copyrights and/or licenses:
+*
+* rfc4122 and supporting functions
+* * Algorithm from RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace
+* * By Paul J. Leach, Michael Mealling and Rich Sals, July 2005.
+* *
+* * This function is adapted from the routines in the document
+* * uuid_create_sha1_from_name and format_uuid_v3or5
+* *
+* *
+* * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
+* * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
+* * Digital Equipment Corporation, Maynard, Mass.
+* * Copyright (c) 1998 Microsoft.
+* * To anyone who acknowledges that this file is provided "AS IS"
+* * without any express or implied warranty: permission to use, copy,
+* * modify, and distribute this file for any purpose is hereby
+* * granted without fee, provided that the above copyright notices and
+* * this notice appears in all source code copies, and that none of
+* * the names of Open Software Foundation, Inc., Hewlett-Packard
+* * Company, Microsoft, or Digital Equipment Corporation be used in
+* * advertising or publicity pertaining to distribution of the software
+* * without specific, written prior permission. Neither Open Software
+* * Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital
+* * Equipment Corporation makes any representations about the
+* * suitability of this software for any purpose.
+* *
+*/
+
+#ifdef _MSC_VER
+#pragma once
+#endif /* _MSC_VER */
+
+#ifndef WINRT_PARAMINSTANCEAPI_H
+#define WINRT_PARAMINSTANCEAPI_H
+
+#ifdef __cplusplus
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4180 ) // qualifier applied to function type has no meaning; ignored
+#endif
+
+#include <wtypes.h>
+#include <ntassert.h>
+#include <sal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <objbase.h>
+#include <limits.h>
+
+//#ifdef _MSC_VER
+//#include <new.h>
+//#else
+//#include <new>
+//#endif
+
+#ifndef WINRT_PARAMINSTANCE_NOCRYPT_SHA1
+#include <bcrypt.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma push_macro("CHKHR")
+#pragma push_macro("CHKNT")
+#endif
+
+namespace Ro { namespace detail {
+
+ //
+ // Debugging aide. Set breakpoint on _FailedHR
+ // to see HRESULT propagation.
+ //
+ #ifdef DEBUG
+ inline HRESULT __declspec(noinline) _FailedHR(HRESULT hr) { static HRESULT _hr = hr; return hr; }
+ #else
+ inline HRESULT _FailedHR(HRESULT hr) { return hr; }
+ #endif
+}}
+
+#undef CHKHR
+//
+// Call HRESULT returning code and propagate any errors.
+// Note: only use in code that is exception-safe / uses RAII.
+//
+#define CHKHR(expr) \
+ { HRESULT _zzhr; \
+ _zzhr = expr; \
+ if (FAILED(_zzhr)) return Ro::detail::_FailedHR(_zzhr); }
+
+#undef CHKNT
+//
+// Call NTSTATUS returning code and propagate any errors, as HRESULTs.
+// Note:
+// - only use in code that is exception-safe / uses RAII / RRID.
+// - HRESULT_FROM_NT does safely convert STATUS_SUCCESS into
+// a SUCCEEDED hr.
+//
+#define CHKNT(expr) \
+ CHKHR( HRESULT_FROM_NT( expr ) )
+
+namespace Ro { namespace detail {
+
+ //
+ // Runtime check for an invariant. This check executes in release builds.
+ //
+
+ inline HRESULT Verify(bool invariant, HRESULT defaultHr = E_UNEXPECTED)
+ {
+ if (!invariant)
+ {
+ CHKHR(defaultHr);
+ }
+ return S_OK;
+ }
+}}
+
+
+extern "C" {
+
+
+// sha1 adaptor
+// create hash instance
+
+HRESULT _RoSha1Create(
+ __out void** handle);
+
+
+// sha1 adaptor
+// append more data to the input stream
+
+HRESULT _RoSha1AppendData(
+ __in void* handle,
+ __in size_t numBytes,
+ __in_bcount(numBytes) const void* data);
+
+
+// sha1 adaptor
+// return the first 16 bytes of SHA1 hash
+
+HRESULT _RoSha1Finish(
+ __in void* handle,
+ __out BYTE (*hashValue)[20]);
+
+
+// sha1 adaptor
+// free this instance
+
+void _RoSha1Release(__in void* handle);
+
+}
+
+struct IRoSimpleMetaDataBuilder;
+struct IRoMetaDataLocator;
+
+// The 'detail' namespace includes implementation details that
+// are subject to change without notice.
+namespace Ro { namespace detail
+{
+ struct SimpleMetaDataBuffer;
+}}
+
+
+//
+// Purpose:
+// Given a parameterized type instance name and metadata,
+// computes the IID for that instance.
+//
+// Parameters:
+//
+// nameElementCount
+// number of elements in nameElements
+// nameElements
+// a parsed WinRt type name, as would be returned by RoParseTypeName.
+// Eg: ["W.F.C.IVector`1", "N1.N2.IFoo"]
+// metaDataLocator
+// A callback to use for resolving metadata.
+//
+// An implementation could, for example, forward all calls
+// to RoGetMetaData, then passing the results to
+// RoWriteImporterToPushSimpleMetaData. As RoGetMetadata does
+// not cache results, such an implementation would be inefficient.
+// A better implementation will cache the results to RoGetMetaData,
+// as appropriate.
+//
+// The Locator helper function can be used to wrap a lambda
+// expression, or function pointer. eg:
+// RoGetParameterizedTypeInstanceIID(
+// ...,
+// Locate([&](PCWSTR* name, IRoSimpleMetaDataBuilder& push){...}),
+// ...);
+// iid
+// out param. Returns the iid for the parameterized type specified
+// by nameElements
+// extra
+// out param. returns a handle that holds extra information about the
+// IID result, for diagnostic purposes. If this handle is not desired,
+// provide nullptr instead.
+//
+// Notes:
+// - This function is stateless. IRoMetaDataLocator will not be preserved
+// between calls.
+// - This function does not perform deep semantic analysis. For instance,
+// if IRoSimpleMetaDataBuilder specifies that a struct contains an interface pointer,
+// this API will return success, even though such metadata is semantically
+// invalid. The value of the IID returned is unspecified in such cases.
+// - This function does introduce reentrancy. Its implementation
+// of IRoSimpleMetaDataBuilder may make reentrant calls to IRoMetaDataLocator.
+// - If a call to IRoSimpleMetaDataBuilder fails, this function will return that
+// failure code.
+//
+
+
+DECLARE_HANDLE(ROPARAMIIDHANDLE);
+
+inline HRESULT RoGetParameterizedTypeInstanceIID(
+ UINT32 nameElementCount,
+ __in_ecount(nameElementCount) PCWSTR* nameElements,
+ __in const IRoMetaDataLocator& metaDataLocator,
+ __out GUID* iid,
+ __deref_opt_out ROPARAMIIDHANDLE* pExtra = nullptr);
+
+// Frees the 'extra' handle allocated
+// by RoGetParameterizedTypeInstanceIID
+inline void RoFreeParameterizedTypeExtra(__in ROPARAMIIDHANDLE extra);
+
+// Fetches the TypeSignature used to compute the IID by the last
+// call to RoGetParameterizedTypeInstanceIID on this extra handle.
+// The string contains ASCII code only, and the string is valid
+// until RoFreeParameterizedTypeExtra is called on the extra pointer.
+inline PCSTR RoParameterizedTypeExtraGetTypeSignature(__in ROPARAMIIDHANDLE extra);
+
+namespace Ro { namespace detail
+{
+
+ // private type used in helper function
+
+ template <typename Fn>
+ struct _Locator;
+}} // namespace Ro::detail
+
+namespace Ro
+{
+
+ // helper function to create IRoMetaDataLocator from lambda expression
+
+ template <typename Fn>
+ Ro::detail::_Locator<Fn> Locator(const Fn& fn);
+} // namespace Ro
+
+
+//
+// Purpose:
+// Destination for IRoMetaDataLocator::Locate to write parsed metadata to.
+// 'Locate' should set the appropriate Windows Runtime metadata information gleaned
+// from Windows Runtime metadata file, or other appropriate source.
+//
+// Notes:
+// - Methods for base types and COM interfaces (eg, Int32 and IInspectable
+// respectively) are not needed -- RoGetParameterizedTypeInstanceIID already
+// knows the WinRT base type names, so will not invoke IMetDataLocator
+// to discover them.
+// - This is not a COM interface. It does not derive from IUnknown.
+//
+
+struct IRoSimpleMetaDataBuilder
+{
+
+ // Notes:
+ // IInspectable and other non-WinRT interfaces are not permissible.
+ // Not for use with parameterized type instances. See SetParameterizedInterface
+
+ STDMETHOD(SetWinRtInterface)(
+ GUID iid) = 0;
+
+
+ // Notes:
+ // Not for use with parameterized type instances. See SetParameterizedDelegate
+
+ STDMETHOD(SetDelegate)(
+ GUID iid) = 0;
+
+
+ // Notes:
+ // Call this method when an interface group has a default interface
+ // that is a non-parametric type.
+
+ STDMETHOD(SetInterfaceGroupSimpleDefault)(
+ PCWSTR name,
+ PCWSTR defaultInterfaceName,
+ __in_opt const GUID* defaultInterfaceIID) = 0;
+
+
+ // Notes:
+ // Call this method when an interface group has a parameterized
+ // interface as its default interface.
+
+ STDMETHOD(SetInterfaceGroupParameterizedDefault)(
+ PCWSTR name,
+ UINT32 elementCount,
+ __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements) = 0;
+
+ STDMETHOD(SetRuntimeClassSimpleDefault)(
+ PCWSTR name,
+ PCWSTR defaultInterfaceName,
+ __in_opt const GUID* defaultInterfaceIID) = 0;
+
+ STDMETHOD(SetRuntimeClassParameterizedDefault)(
+ PCWSTR name,
+ UINT32 elementCount,
+ __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements) = 0;
+
+ STDMETHOD(SetStruct)(
+ PCWSTR name,
+ UINT32 numFields,
+ __in_ecount(numFields) PCWSTR* fieldTypeNames) = 0;
+
+ STDMETHOD(SetEnum)(
+ PCWSTR name,
+ PCWSTR baseType) = 0;
+
+
+ // Notes:
+ // This is only for the 'non-instantiated' parameterized interface itself -
+ // instances are handled by RoGetParameterizedTypeInstanceIID, and the
+ // caller need not parse them.
+
+ STDMETHOD(SetParameterizedInterface)(
+ GUID piid,
+ UINT32 numArgs) = 0;
+
+ STDMETHOD(SetParameterizedDelegate)(
+ GUID piid,
+ UINT32 numArgs) = 0;
+};
+
+
+//
+// Purpose:
+// Callback for resolving metadata.
+//
+
+struct IRoMetaDataLocator
+{
+
+ //
+ // Parameters:
+ // nameElement
+ // a metadata typeref name to resolve.
+ // Eg: "N1.N2.IFoo", or "W.F.C.IVector`1".
+ // pushMetaData
+ // data sink for providing information about the
+ // type information for nameElement
+ //
+
+ STDMETHOD(Locate)(
+ PCWSTR nameElement,
+ __in IRoSimpleMetaDataBuilder& metaDataDestination
+ ) const = 0;
+};
+
+namespace Ro { namespace detail {
+
+
+ //
+ // helper function, moves range of elements
+ //
+
+ template <typename T>
+ void _VecMoveRange(
+ __in_ecount(size) T* dst,
+ __in_ecount(size) T* src,
+ size_t size)
+ {
+ for (size_t i = 0; i != size; ++i)
+ {
+ dst[i] = static_cast<T&&>(src[i]);
+ }
+ }
+
+ //
+ // specializations to move strings more efficiently
+ //
+
+ inline void _VecMoveRange(
+ __in_ecount(size) char* dst,
+ __in_ecount(size) char* src,
+ size_t size)
+ {
+ errno_t err = memcpy_s(dst, size*sizeof(*dst), src, size*sizeof(*dst));
+ NT_ASSERT(!err);
+ (void)err;
+ }
+ inline void _VecMoveRange(
+ __in_ecount(size) wchar_t* dst,
+ __in_ecount(size) wchar_t* src,
+ size_t size)
+ {
+ errno_t err = memcpy_s(dst, size*sizeof(*dst), src, size*sizeof(*dst));
+ NT_ASSERT(!err);
+ (void)err;
+ }
+
+
+ //
+ // helper function, moves range of elements
+ //
+
+ template <typename T>
+ void _VecCopyRange(
+ __in_ecount(size) T* dst,
+ __in_ecount(size) const T* src,
+ size_t size)
+ {
+ for (size_t i = 0; i != _size; ++i)
+ {
+ dst[i] = src[i];
+ }
+ }
+
+ //
+ // specializations to move strings more efficiently
+ //
+
+ inline void _VecCopyRange(
+ __in_ecount(size) char* dst,
+ __in_ecount(size) const char* src,
+ size_t size)
+ {
+ errno_t err = memcpy_s(dst, size*sizeof(*dst), const_cast<char*>(src), size*sizeof(*dst));
+ NT_ASSERT(!err);
+ (void)err;
+ }
+ inline void _VecCopyRange(
+ __in_ecount(size) wchar_t* dst,
+ __in_ecount(size) const wchar_t* src,
+ size_t size)
+ {
+ errno_t err = memcpy_s(dst, size*sizeof(*dst), const_cast<wchar_t*>(src), size*sizeof(*dst));
+ NT_ASSERT(!err);
+ (void)err;
+ }
+
+ //
+ // Single-owner smart pointer for arrays
+ //
+
+ template <class T>
+ struct ArrayHolder
+ {
+ ArrayHolder() : _value(NULL)
+ {
+ }
+ T* Value() const
+ {
+ return _value;
+ }
+ T*& Value()
+ {
+ return _value;
+ }
+ T* Detach()
+ {
+ T* tmp = _value;
+ _value = NULL;
+ return tmp;
+ }
+ ~ArrayHolder()
+ {
+ delete[] _value;
+ }
+
+ private:
+ T* _value;
+ };
+
+ //
+ // Single-owner smart pointer for object pointer
+ //
+
+ template <class T>
+ struct ElementHolder
+ {
+ ElementHolder() : _value(NULL)
+ {
+ }
+ T* operator->() const
+ {
+ return _value;
+ }
+ T* Value() const
+ {
+ return _value;
+ }
+ T*& Value()
+ {
+ return _value;
+ }
+ T* Detach()
+ {
+ T* tmp = _value;
+ _value = NULL;
+ return tmp;
+ }
+ ~ElementHolder()
+ {
+ delete _value;
+ }
+
+ private:
+ T* _value;
+ };
+
+
+
+ //
+ // simple vector, with small vector optimization
+ // T - must be default constructable and movable.
+ // const input overload of AppendN requires copyable.
+ // FixedBufSize - number of bytes to use for small array
+ // optimization, to avoid heap allocation in case of
+ // small vectors. Defaults to at least one element,
+ // otherwise the largest value such that <= 64 bytes
+ // are used.
+ //
+
+ template <
+ typename T,
+ size_t FixedBufSize = 0
+ >
+ class Vec
+ {
+ private:
+ static const size_t _fixedBufSize =
+ FixedBufSize/sizeof(T)
+ ? FixedBufSize/sizeof(T)
+ : (((64/sizeof(T)) > 0) ? (64/sizeof(T))
+ : 1);
+ public:
+ Vec() :
+ _size(0),
+ _cap(_countof(_fixedBuf)),
+ _buf(_fixedBuf)
+ {
+ }
+
+
+ // Appends an element, or a default value if one
+ // it not specified. If called with an rvalue,
+ // it uses move assignment instead of copy.
+
+ HRESULT Append(T value = T())
+ {
+ if (_cap - _size < 1)
+ {
+ CHKHR(_Grow());
+ }
+ _buf[_size] = static_cast<T&&>(value);
+ ++_size;
+
+ return S_OK;
+ }
+
+ // Moves elements (move assignment) into array.
+
+ HRESULT MoveN(__in_ecount(n) T* values, size_t n)
+ {
+ if (_cap - _size < n)
+ {
+ CHKHR(_Grow(n - (_cap - _size)));
+ }
+ _VecMoveRange(_buf + _size, values, n);
+ _size += n;
+
+ return S_OK;
+ }
+
+
+ // Appends elements. Does not invoke move assignment.
+
+ HRESULT AppendN(__in_ecount(n) const T* values, size_t n)
+ {
+ if (_cap - _size < n)
+ {
+ CHKHR(_Grow(n - (_cap - _size)));
+ }
+ _VecCopyRange(_buf + _size, values, n);
+ _size += n;
+
+ return S_OK;
+ }
+
+ HRESULT Pop()
+ {
+ CHKHR(Verify( _size > 0 ));
+ --_size;
+ return S_OK;
+ }
+
+ HRESULT Resize(size_t newSize)
+ {
+ if (_cap < newSize)
+ {
+ CHKHR(_Grow(newSize - _cap));
+ }
+ _size = newSize;
+ return S_OK;
+ }
+
+ size_t Size() const
+ {
+ return _size;
+ }
+
+ T& operator[](size_t index)
+ {
+ NT_ASSERT(index < _size);
+ return _buf[index];
+ }
+
+ T& Last()
+ {
+ return (*this)[_size-1];
+ }
+
+ ~Vec()
+ {
+ if (_buf != _fixedBuf)
+ {
+ delete[] _buf;
+ }
+ }
+
+ private:
+
+ //
+ // growth factor (does not check for overflow) -- returns amount to grow by
+ //
+
+ static size_t _GrowthIncrement(size_t n)
+ {
+ return n / 2;
+ }
+
+ HRESULT _Grow(size_t byAtLeast = 4)
+ {
+ size_t increase = _GrowthIncrement(_cap);
+ if (increase < byAtLeast)
+ {
+ increase = byAtLeast;
+ }
+ size_t newCap = _cap + increase;
+ if (newCap <= _cap)
+ {
+ CHKHR(E_OUTOFMEMORY);
+ }
+ ArrayHolder<T> newBuf;
+
+ void* p = (newBuf.Value() = new (std::nothrow) T[newCap]);
+ if (!p)
+ {
+ CHKHR(E_OUTOFMEMORY);
+ }
+
+ _VecMoveRange( newBuf.Value(), _buf, _size );
+
+ if (_buf != _fixedBuf)
+ {
+ delete _buf;
+ }
+ _buf = newBuf.Detach();
+ _cap = newCap;
+
+ return S_OK;
+ }
+
+ size_t _size;
+ size_t _cap;
+ T* _buf;
+ T _fixedBuf[_fixedBufSize];
+ };
+
+ struct SimpleMetaDataBuilder : IRoSimpleMetaDataBuilder
+ {
+ public:
+ SimpleMetaDataBuilder(SimpleMetaDataBuffer& buffer, const IRoMetaDataLocator& locator)
+ : _buffer(&buffer), _locator(&locator), _invoked(false)
+ {
+ }
+ IFACEMETHOD(SetWinRtInterface)(GUID iid);
+ IFACEMETHOD(SetDelegate)(GUID iid);
+ IFACEMETHOD(SetInterfaceGroupSimpleDefault)(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID);
+ IFACEMETHOD(SetInterfaceGroupParameterizedDefault)(PCWSTR name, UINT32 elementCount, __in_ecount(elementCount) PCWSTR *defaultInterfaceNameElements);
+ IFACEMETHOD(SetRuntimeClassSimpleDefault)(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID);
+ IFACEMETHOD(SetRuntimeClassParameterizedDefault)(PCWSTR name, UINT32 elementCount, __in_ecount(elementCount) PCWSTR *defaultInterfaceNameElements);
+ IFACEMETHOD(SetStruct)(PCWSTR name, UINT32 numFields, __in_ecount(numFields) PCWSTR *fieldTypeNames);
+ IFACEMETHOD(SetEnum)(PCWSTR name, PCWSTR baseType);
+ IFACEMETHOD(SetParameterizedInterface)(GUID piid, UINT32 numArgs);
+ IFACEMETHOD(SetParameterizedDelegate)(GUID piid, UINT32 numArgs);
+
+
+ // Runs the locating process for a parameterized type.
+ // Notes:
+ // _buffer->_nestingLevel is used to determine the number of
+ // arguments left to consume for nested parameterized types.
+
+ HRESULT SendArguments(UINT32 nameElementCount, __in_ecount(nameElementCount) PCWSTR *nameElements);
+
+ private:
+
+
+ // Writes the type signature for the type 'name'
+ // Notes:
+ // - If a builtin type, writes the type directly.
+ // - Otherwise, uses the IRoMetaDataLocator to
+ // write the type signature into _buffer
+ // - As the sole function to call
+ // IRoMetaDataLocator, it also performs the check
+ // on recursion depth bounds.
+
+ HRESULT _WriteType(PCWSTR name);
+
+
+ // The tail portion of IG and RC formats is the same. This
+ // function implements the shared portion of that format.
+
+ HRESULT _CommonInterfaceGroupSimple(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID);
+
+
+ // Called at the beginning of every 'Set' method. Set must only be called once.
+
+ HRESULT _OnSet();
+
+
+ // Called at the end of every 'Set' method, only if successful.
+
+ void _Completed();
+
+ static char _AsciiLower(char ch)
+ {
+ if ('A' <= ch && ch <= 'Z')
+ {
+ return ch + ('a' - 'A');
+ }
+ else
+ {
+ return ch;
+ }
+ }
+
+
+ // Writes a guid into the type signature being built, in lower case.
+
+ HRESULT _WriteGuid(const GUID& iid);
+ HRESULT _WriteString(PCSTR str);
+ HRESULT _WriteChar(char c);
+ HRESULT _WriteWideString(PCWSTR str);
+
+ SimpleMetaDataBuilder();
+ SimpleMetaDataBuilder(const SimpleMetaDataBuilder&);
+ void operator=(const SimpleMetaDataBuilder&);
+
+ SimpleMetaDataBuffer* _buffer;
+ const IRoMetaDataLocator* _locator;
+ bool _invoked;
+ };
+
+
+ // If the type string describes a built-in type, modifies
+ // this instance to use builtin type table entry instead of name.
+
+ inline bool _IsBuiltin(__in PCWSTR name, __out PCSTR * typeSignature)
+ {
+ *typeSignature = nullptr;
+
+ struct BuiltinEntry { PCWSTR name; PCSTR typeSignature; };
+ static const BuiltinEntry entries[] = {
+
+ { L"UInt8", "u1" },
+ { L"Int16", "i2" },
+ { L"UInt16", "u2" },
+ { L"Int32", "i4" },
+ { L"UInt32", "u4" },
+ { L"Int64", "i8" },
+ { L"UInt64", "u8" },
+ { L"Single", "f4" },
+ { L"Double", "f8" },
+ { L"Boolean", "b1" },
+ { L"Char16", "c2" },
+ { L"String", "string" },
+ { L"Guid", "g16" },
+ { L"Object", "cinterface(IInspectable)" },
+ };
+ for (const BuiltinEntry* tip = entries;
+ tip != &entries[_countof(entries)];
+ ++tip)
+ {
+ if (wcscmp(tip->name, name) == 0)
+ {
+ *typeSignature = tip->typeSignature;
+ return true;
+ }
+ }
+
+ // if not found, assume is a normal type name
+
+ return false;
+ }
+
+
+ // Linked list (stack allocated) of type resolution calls,
+ // used to detect if an InterfaceGroup/RuntimeClass type
+ // signature depends on itself. In that case, we use "*"
+ // in the type signature instead of recurring further.
+
+ struct ResolutionPathEntry
+ {
+ ResolutionPathEntry* _next;
+ PCWSTR _typeName;
+
+ ResolutionPathEntry(PCWSTR typeName)
+ : _next(nullptr)
+ , _typeName(typeName)
+ {
+ }
+ };
+
+ inline void Push(ResolutionPathEntry*& top, ResolutionPathEntry* item)
+ {
+ item->_next = top;
+ top = item;
+ }
+ inline HRESULT Pop(ResolutionPathEntry*& top)
+ {
+ if (!top)
+ {
+ return E_UNEXPECTED;
+ }
+ top = top->_next;
+ return S_OK;
+ }
+
+
+ // Holds metadata state that is shared between RoGetParamInstanceIID and SimpleMetaDataBuilder
+
+ struct SimpleMetaDataBuffer
+ {
+ SimpleMetaDataBuffer()
+ {
+ Clear();
+ }
+
+ // reset all tables
+ void Clear()
+ {
+ _recursionDepth = 0;
+ _topLevelTypes = 0;
+ _resolutionPath = nullptr;
+ _outputStream.Resize(0);
+ }
+
+ static const size_t _maxTypeName = 256;
+
+
+ // Estimate of 'reasonable' level of Interface Group / Runtime
+ // Class / Parameterized Type nesting.
+
+ static const size_t _maxRecursionDepth = 64;
+
+ Vec<char, _maxTypeName> _outputStream;
+ ResolutionPathEntry* _resolutionPath;
+
+
+ // RAII object, places an item on the resolution path, and pops it on destruction
+
+ class ResolutionPathGuard
+ {
+ private:
+ ResolutionPathEntry _entry;
+ SimpleMetaDataBuffer* _buffer;
+
+ public:
+ ResolutionPathGuard(PCWSTR typeName, SimpleMetaDataBuffer* buffer)
+ : _buffer(buffer)
+ , _entry(typeName)
+ {
+ Push(buffer->_resolutionPath, &_entry);
+ }
+ ~ResolutionPathGuard()
+ {
+ HRESULT hr = Pop(_buffer->_resolutionPath);
+ NT_ASSERT(SUCCEEDED(hr));
+ (void)hr;
+ }
+ };
+
+
+ // Searches the resolution path for 'name' returning true if exists
+
+ bool ExistsCycle(PCWSTR typeName)
+ {
+ for (auto pTip = _resolutionPath; pTip; pTip = pTip->_next)
+ {
+ if (wcscmp(typeName, pTip->_typeName) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ // Indicates the nesting level of compound types, used
+ // to properly balance parenthesis on parameterized types,
+ // and used to bound recursion depth.
+ //
+ // - Pinterfaces
+ // : push 'numArgs' on to _nestingLevel
+ // - A compound type that doesn't know number of arguments
+ // eg, RoGetParameterizedInstanceIID arguments, or
+ // SetIG..Parameterized
+ // : will 0) note nesting level
+ // 1) iterate calling Locate on the compound arguments.
+ // 2) the above should cause exactly one push of _nestingLevel
+ // 3) reduce nesting level back to original nesting level,
+ // inserting the difference in closing parens
+ // - Compound types that do know number of arguments (eg SetStruct)
+ // : will 1) increase nesting level by 1
+ // 2) iterate calling Locate on arguments
+ // 3) decrease nesting level again
+ //
+ //
+
+ Vec<size_t> _nestedArgs;
+
+ // topLevelTypes should be incremented once, by the initial
+ // parameterized type, then never again.
+
+ size_t _topLevelTypes;
+ size_t _recursionDepth;
+ };
+}} // namespace Ro::detail
+
+namespace Ro { namespace detail
+{
+ template <typename Fn>
+ struct _Locator : IRoMetaDataLocator
+ {
+ Fn _fn;
+
+ _Locator(const Fn& fn)
+ : _fn(fn)
+ {
+ }
+
+ IFACEMETHOD(Locate)(
+ PCWSTR name,
+ IRoSimpleMetaDataBuilder& pushMetaData) const
+ {
+ return _fn(name, pushMetaData);
+ }
+ };
+}} // namespace Ro::detail
+
+namespace Ro
+{
+ template <typename Fn>
+ Ro::detail::_Locator<Fn> Locator(const Fn& fn)
+ {
+ return Ro::detail::_Locator<Fn>(fn);
+ }
+}
+
+namespace Ro { namespace detail
+{
+
+ // Figure out if we're compiling for a big- or little-endian machine.
+
+ inline bool BigEndian()
+ {
+ unsigned long n = 0xff000000L;
+
+ return 0 != *reinterpret_cast<unsigned char *>(&n);
+ }
+
+
+ // HostToNetworkLong converts a 32-bit long to network byte order
+
+ inline ULONG HostToNetworkLong(ULONG hostlong)
+ {
+ if (BigEndian())
+ return hostlong;
+ else
+ return ( (hostlong >> 24) & 0x000000FFL) |
+ ( (hostlong >> 8) & 0x0000FF00L) |
+ ( (hostlong << 8) & 0x00FF0000L) |
+ ( (hostlong << 24) & 0xFF000000L);
+ }
+
+
+ // HostToNetworkLong converts a 16-bit short to network byte order
+
+ inline USHORT HostToNetworkShort(USHORT hostshort)
+ {
+ if (BigEndian())
+ return hostshort;
+ else
+ return ((hostshort >> 8) & 0x00FF) | ((hostshort << 8) & 0xFF00);
+ }
+
+
+ // NetworkToHostLong converts a 32-bit long to local host byte order
+
+ inline ULONG NetworkToHostLong(ULONG netlong)
+ {
+ if (BigEndian())
+ return netlong;
+ else
+ return ( (netlong >> 24) & 0x000000FFL) |
+ ( (netlong >> 8) & 0x0000FF00L) |
+ ( (netlong << 8) & 0x00FF0000L) |
+ ( (netlong << 24) & 0xFF000000L);
+ }
+
+
+ // NetworkToHostShort converts a 16-bit short to local host byte order
+
+ inline USHORT NetworkToHostShort(USHORT netshort)
+ {
+ if (BigEndian())
+ return netshort;
+ else
+ return ((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00);
+ }
+
+
+ // smart pointer for Sha1 handle
+
+ struct Sha1Holder
+ {
+ Sha1Holder() : _handle(nullptr)
+ {
+ }
+ void*& Value()
+ {
+ return _handle;
+ }
+ ~Sha1Holder()
+ {
+ if (_handle)
+ {
+ _RoSha1Release(_handle);
+ }
+ }
+ private:
+ void* _handle;
+ };
+
+
+
+ //
+ // Computes the rfc4122 v5 UUID from GUID,name pair.
+ //
+ // Notes:
+ // - see copyright at beginning of file.
+ //
+
+ inline HRESULT
+ GuidFromName(
+ __in const GUID& guidNamespace,
+ __in_bcount(dwcbSize) const void* pbName,
+ __in DWORD dwcbSize,
+ __out GUID* pGuid)
+ {
+ Sha1Holder sha1;
+
+ CHKHR( _RoSha1Create(&sha1.Value()) );
+ {
+ GUID networkOrderGuidNamespace = guidNamespace;
+
+ // Put name space ID in network byte order so it hashes the same
+ // no matter what endian machine we're on
+
+ if (!BigEndian())
+ {
+ networkOrderGuidNamespace.Data1 = HostToNetworkLong (networkOrderGuidNamespace.Data1);
+ networkOrderGuidNamespace.Data2 = HostToNetworkShort(networkOrderGuidNamespace.Data2);
+ networkOrderGuidNamespace.Data3 = HostToNetworkShort(networkOrderGuidNamespace.Data3);
+ }
+ CHKHR( _RoSha1AppendData(sha1.Value(), sizeof(networkOrderGuidNamespace), reinterpret_cast<BYTE*>(&networkOrderGuidNamespace)) );
+ }
+ CHKHR( _RoSha1AppendData(sha1.Value(), dwcbSize, pbName) );
+
+ {
+ BYTE sha1Result[20];
+ CHKHR( _RoSha1Finish(sha1.Value(), &sha1Result) );
+
+ errno_t err = memcpy_s(pGuid, sizeof(GUID), &sha1Result[0], sizeof(GUID));
+ CHKHR(Verify( 0 == err ));
+
+
+ // Restore the byte order
+
+ if (!BigEndian())
+ {
+ pGuid->Data1 = NetworkToHostLong (pGuid->Data1);
+ pGuid->Data2 = NetworkToHostShort(pGuid->Data2);
+ pGuid->Data3 = NetworkToHostShort(pGuid->Data3);
+ }
+
+
+ // set version number
+ // 1: clear version number nibble
+ // 2: set version 5 = name-based SHA1
+
+ pGuid->Data3 &= 0x0FFF;
+ pGuid->Data3 |= (5 << 12);
+
+
+ // set variant field by clearing variant bits.
+
+ pGuid->Data4[0] &= 0x3F;
+ pGuid->Data4[0] |= 0x80;
+ }
+ return S_OK;
+ }
+}} // namespace Ro::detail
+
+inline HRESULT RoGetParameterizedTypeInstanceIID(
+ UINT32 nameElementCount,
+ __in_ecount(nameElementCount) PCWSTR* nameElements,
+ __in const IRoMetaDataLocator& metaDataLocator,
+ __out GUID* iid,
+ __deref_opt_out ROPARAMIIDHANDLE* pExtra)
+{
+ using namespace Ro::detail;
+ memset(iid, 0, sizeof(*iid));
+
+ SimpleMetaDataBuffer reserveBuffer;
+ SimpleMetaDataBuffer *pBuffer = &reserveBuffer;
+
+ // if user wishes to hold on to the result value,
+ // dynamically allocate this buffer.
+ if (pExtra)
+ {
+ pBuffer = new (std::nothrow) SimpleMetaDataBuffer;
+ *pExtra = static_cast<ROPARAMIIDHANDLE>(static_cast<void*>(pBuffer));
+ }
+ SimpleMetaDataBuffer& buffer = *pBuffer;
+ SimpleMetaDataBuilder builder(*pBuffer, metaDataLocator);
+
+ // send initial arguments
+ CHKHR(builder.SendArguments(nameElementCount, nameElements));
+
+ // verify that precisely one type was resolved, to completion.
+ CHKHR(Verify(buffer._topLevelTypes == 1
+ && buffer._nestedArgs.Size() == 0,
+ E_INVALIDARG));
+
+ // compute type signature hash
+ static const GUID guidPinterfaceNamespace
+ = { 0x11f47ad5, 0x7b73, 0x42c0, { 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee }};
+
+ CHKHR(Ro::detail::Verify( buffer._outputStream.Size() <= DWORD(-1) ));
+
+ // null terminate
+ CHKHR( buffer._outputStream.Append('\0') );
+
+
+ //
+ // Unit test logging, to verify proper signatures
+ //
+ #ifdef UNITTEST_TRACE
+ {
+ CHKHR( UNITTEST_TRACE("type signature", &buffer._outputStream[0]) );
+ }
+ #endif
+
+
+ CHKHR( GuidFromName(guidPinterfaceNamespace,
+ &buffer._outputStream[0],
+ DWORD(buffer._outputStream.Size() - 1), // does not include terminator
+ iid) );
+ return S_OK;
+}
+
+inline void RoFreeParameterizedTypeExtra(__in ROPARAMIIDHANDLE extra)
+{
+ using namespace Ro::detail;
+ delete static_cast<SimpleMetaDataBuffer*>(static_cast<void*>(extra));
+}
+inline PCSTR RoParameterizedTypeExtraGetTypeSignature(__in ROPARAMIIDHANDLE extra)
+{
+ using namespace Ro::detail;
+ SimpleMetaDataBuffer* pBuffer = static_cast<SimpleMetaDataBuffer*>(static_cast<void*>(extra));
+
+ return &pBuffer->_outputStream[0];
+}
+
+namespace Ro { namespace detail
+{
+
+ inline HRESULT SimpleMetaDataBuilder::_WriteType(PCWSTR name)
+ {
+ PCSTR builtInName = nullptr;
+ SimpleMetaDataBuilder builder(*_buffer, *_locator);
+
+ if (_IsBuiltin(name, &builtInName))
+ {
+ CHKHR(builder._OnSet());
+ CHKHR(builder._WriteString(builtInName));
+ builder._Completed();
+ }
+ else
+ {
+ size_t newDepth = ++_buffer->_recursionDepth;
+ size_t pinterfaceNesting = _buffer->_nestedArgs.Size();
+ if (newDepth + pinterfaceNesting > _buffer->_maxRecursionDepth)
+ {
+
+ // Terminate recursion; bounds call stack consumption
+
+ CHKHR(E_UNEXPECTED);
+ }
+ CHKHR(_locator->Locate(name, builder));
+
+ // Note, buffers aren't reusable, so it's fine that we don't
+ // unwind this value on return. Also note, we do not unwind
+ // this value if the user provides inconsistent data either
+ // (eg, if they provide only 1 argument to a 2 parameter
+ // parameterized type).
+
+ --_buffer->_recursionDepth;
+ }
+ return S_OK;
+ }
+
+ inline HRESULT SimpleMetaDataBuilder::_OnSet()
+ {
+ if (_invoked)
+ {
+ CHKHR(E_INVALIDARG);
+ }
+ _invoked = true;
+
+
+ // Reduce the number of arguments left for this compound type.
+
+ if(_buffer->_nestedArgs.Size() > 0)
+ {
+ --(_buffer->_nestedArgs.Last());
+ }
+ else
+ {
+
+ // Increase number of top level types in signature
+ // string. (should never exceed one)
+
+ ++_buffer->_topLevelTypes;
+ }
+
+ return S_OK;
+ }
+
+ inline void SimpleMetaDataBuilder::_Completed()
+ {
+ }
+ inline HRESULT SimpleMetaDataBuilder::SendArguments(UINT32 nameElementCount, __in_ecount(nameElementCount) PCWSTR *nameElements)
+ {
+ CHKHR(Verify(nameElementCount > 0));
+
+ CHKHR(Verify(_buffer->_nestedArgs.Size() <= UINT32(-1)));
+ UINT32 previousLevel = UINT32(_buffer->_nestedArgs.Size());
+
+ for (UINT32 i = 0; i < nameElementCount; ++i)
+ {
+ CHKHR(_WriteType(nameElements[i]));
+
+
+ // Close any nested parameterized types that are complete
+
+ while (_buffer->_nestedArgs.Size() > previousLevel
+ && _buffer->_nestedArgs.Last() == 0)
+ {
+ CHKHR(_buffer->_nestedArgs.Pop());
+ CHKHR(_WriteChar(')'));
+ }
+
+ // insert separator between parameterized type arguments
+
+ CHKHR(_WriteChar(';'));
+ }
+
+ // remove final separator
+
+ CHKHR(_buffer->_outputStream.Pop());
+
+
+ // Verify that all the arguments were consumed.
+
+ CHKHR(Verify(_buffer->_nestedArgs.Size() == previousLevel,
+ E_INVALIDARG));
+ return S_OK;
+ }
+
+ inline HRESULT SimpleMetaDataBuilder::_WriteGuid(const GUID& iid)
+ {
+ static const size_t guidStringLength = _countof("{11223344-1122-1122-1122-334455667788}") - 1;
+ WCHAR tmpString[guidStringLength+1];
+
+ int numWritten = StringFromGUID2(iid, tmpString, guidStringLength + 1);
+ CHKHR(Verify( numWritten == guidStringLength + 1 ));
+ NT_ASSERT( numWritten == guidStringLength + 1 );
+
+ size_t offset = _buffer->_outputStream.Size();
+ CHKHR(Verify( offset + guidStringLength > offset ))
+ CHKHR( _buffer->_outputStream.Resize(offset + guidStringLength) );
+ char* writePtr = &_buffer->_outputStream[offset];
+
+
+ // All characters are ascii. Just truncate.
+
+ for(size_t i = 0; i < guidStringLength; ++i)
+ {
+ writePtr[i] = _AsciiLower(char(tmpString[i]));
+ }
+ return S_OK;
+ }
+ inline HRESULT SimpleMetaDataBuilder::_WriteString(PCSTR str)
+ {
+ CHKHR( _buffer->_outputStream.AppendN(str, strlen(str)) );
+ return S_OK;
+ }
+ inline HRESULT SimpleMetaDataBuilder::_WriteChar(char c)
+ {
+ CHKHR( _buffer->_outputStream.Append(c) );
+ return S_OK;
+ }
+ inline HRESULT SimpleMetaDataBuilder::_WriteWideString(PCWSTR str)
+ {
+ size_t len = wcslen(str);
+ size_t offset = _buffer->_outputStream.Size();
+ int written;
+
+
+ // provision enough space for conversion to take place
+
+ size_t provision = len + 1;
+ for(;;)
+ {
+ CHKHR( _buffer->_outputStream.Resize(offset+provision));
+ char* writePtr = &_buffer->_outputStream[offset];
+
+ CHKHR(Verify(len <= INT_MAX));
+ CHKHR(Verify(provision <= INT_MAX));
+
+ written = WideCharToMultiByte(
+ CP_UTF8,
+ 0,
+ str,
+ int(len),
+ writePtr,
+ int(provision),
+ nullptr,
+ nullptr
+ );
+
+ if (written > 0)
+ {
+ break;
+ }
+ else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ CHKHR(HRESULT_FROM_WIN32(GetLastError()));
+ }
+ else
+ {
+ provision *= 2;
+ CHKHR(Verify( offset + provision > offset ));
+ }
+ }
+
+ // reduce size to reflect number of characters actually written.
+ // Note that since we specified string length, no null terminator
+ // was injected, so we don't have to remove it.
+
+ CHKHR( _buffer->_outputStream.Resize(offset+written) );
+
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetWinRtInterface(
+ GUID iid)
+ {
+ CHKHR(_OnSet());
+
+ CHKHR(_WriteGuid(iid));
+
+ _Completed();
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetDelegate(
+ GUID iid)
+ {
+ CHKHR(_OnSet());
+
+ CHKHR(_WriteString("delegate("));
+ CHKHR(_WriteGuid(iid));
+ CHKHR(_WriteChar(')'));
+
+ _Completed();
+ return S_OK;
+ }
+
+ inline HRESULT SimpleMetaDataBuilder::_CommonInterfaceGroupSimple(
+ PCWSTR name,
+ PCWSTR defaultInterfaceName,
+ __in_opt const GUID * defaultInterfaceIID)
+ {
+ CHKHR(_WriteWideString(name));
+ CHKHR(_WriteChar(';'));
+
+
+ // InterfaceGroups and RuntimeClasses take one nested argument
+
+ CHKHR(_buffer->_nestedArgs.Append(1));
+ if (!defaultInterfaceIID)
+ {
+ CHKHR(_WriteType(defaultInterfaceName));
+ }
+ else
+ {
+
+ // complete the type signature immediately; no nested
+ // call needed to resolve the interface.
+
+ SimpleMetaDataBuilder builder(*_buffer, *_locator);
+ CHKHR(builder.SetWinRtInterface(*defaultInterfaceIID))
+ }
+ CHKHR(_WriteChar(')'));
+ CHKHR(_buffer->_nestedArgs.Pop());
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetInterfaceGroupSimpleDefault(
+ PCWSTR name,
+ PCWSTR defaultInterfaceName,
+ __in_opt const GUID* defaultInterfaceIID)
+ {
+ CHKHR(_OnSet());
+
+ CHKHR(_WriteString("ig("));
+ CHKHR(_CommonInterfaceGroupSimple(name, defaultInterfaceName, defaultInterfaceIID));
+
+ _Completed();
+ return S_OK;
+ }
+
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetInterfaceGroupParameterizedDefault(
+ PCWSTR name,
+ UINT32 elementCount,
+ __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements)
+ {
+ CHKHR(_OnSet());
+
+
+ // If an interface group or runtime class has a compound type as its default, and that
+ // type directly or indirectly refers to itself, the second occurrence instead used '*'
+ // to signal that the default interface has already been specified earlier up the call
+ // stack. This prevents unbounded recursion.
+
+ if (_buffer->ExistsCycle(name))
+ {
+ CHKHR( _WriteString("ig(") );
+ CHKHR( _WriteWideString(name) );
+ CHKHR( _WriteString(";*)") );
+ }
+ else
+ {
+ SimpleMetaDataBuffer::ResolutionPathGuard guard(name, _buffer);
+
+ CHKHR( _WriteString("ig(") );
+ CHKHR( _WriteWideString(name) );
+ CHKHR( _WriteChar(';') );
+
+
+ // InterfaceGroups and RuntimeClasses take one nested argument
+
+ CHKHR( _buffer->_nestedArgs.Append(1) );
+ CHKHR( SendArguments(elementCount, defaultInterfaceNameElements) );
+ CHKHR( _buffer->_nestedArgs.Pop() );
+ CHKHR( _WriteChar(')') );;
+
+ }
+ _Completed();
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetRuntimeClassSimpleDefault(
+ PCWSTR name,
+ PCWSTR defaultInterfaceName,
+ __in_opt const GUID* defaultInterfaceIID)
+ {
+ CHKHR(_OnSet());
+
+ CHKHR(_WriteString("rc("));
+ CHKHR(_CommonInterfaceGroupSimple(name, defaultInterfaceName, defaultInterfaceIID));
+
+ _Completed();
+ return S_OK;
+ }
+
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetRuntimeClassParameterizedDefault(
+ PCWSTR name,
+ UINT32 elementCount,
+ __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements)
+ {
+ CHKHR(_OnSet());
+
+ if (_buffer->ExistsCycle(name))
+ {
+ CHKHR(_WriteString("rc("));
+ CHKHR(_WriteWideString(name));
+ CHKHR(_WriteString(";*)"));
+ }
+ else
+ {
+ SimpleMetaDataBuffer::ResolutionPathGuard guard(name, _buffer);
+
+ CHKHR(_WriteString("rc("));
+ CHKHR(_WriteWideString(name));
+ CHKHR(_WriteChar(';'));
+
+
+ // InterfaceGroups and RuntimeClasses take one nested argument
+
+ CHKHR(_buffer->_nestedArgs.Append(1));
+ CHKHR(SendArguments(elementCount, defaultInterfaceNameElements));
+ CHKHR(_buffer->_nestedArgs.Pop());
+
+ CHKHR(_WriteChar(')'));
+ }
+ _Completed();
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetStruct(
+ PCWSTR name,
+ UINT32 numFields,
+ __in_ecount(numFields) PCWSTR* fieldTypeNames)
+ {
+ CHKHR(_OnSet());
+ CHKHR(_WriteString("struct("));
+ CHKHR(_WriteWideString(name));
+ CHKHR(_WriteChar(';'));
+
+ CHKHR(_buffer->_nestedArgs.Append(1));
+ CHKHR(SendArguments(numFields, fieldTypeNames));
+ CHKHR(_buffer->_nestedArgs.Pop());
+
+ CHKHR(_WriteChar(')'));
+
+ _Completed();
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetEnum(
+ PCWSTR name,
+ PCWSTR baseType)
+ {
+ CHKHR(_OnSet());
+
+ CHKHR(_WriteString("enum("));
+ CHKHR(_WriteWideString(name));
+ CHKHR(_WriteChar(';'));
+ CHKHR(_buffer->_nestedArgs.Append(1));
+ CHKHR(_WriteType(baseType));
+ CHKHR(_buffer->_nestedArgs.Pop());
+ CHKHR(_WriteChar(')'));
+
+ _Completed();
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetParameterizedInterface(
+ GUID piid,
+ UINT32 numArgs)
+ {
+ CHKHR(_OnSet());
+
+ CHKHR(_WriteString("pinterface("));
+ CHKHR(_WriteGuid(piid));
+
+
+ // Note the number of arguments. The SendArguments
+ // function will append the ')' after that number of
+ // arguments are consumed.
+
+ CHKHR(_buffer->_nestedArgs.Append(numArgs));
+
+ _Completed();
+ return S_OK;
+ }
+
+ inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetParameterizedDelegate(
+ GUID piid,
+ UINT32 numArgs)
+ {
+
+ // Parameterized interfaces and parameterized delegates use the same signature scheme.
+
+ return SetParameterizedInterface(piid, numArgs);
+ }
+
+}} // namespace Ro::detail
+
+#ifndef WINRT_PARAMINSTANCE_NOCRYPT_SHA1
+
+namespace Ro { namespace detail {
+
+ class Sha1
+ {
+ public:
+ Sha1()
+ : _hAlg(nullptr)
+ , _hHash(nullptr)
+ {
+ }
+
+ HRESULT Initialize()
+ {
+ DWORD dwcb;
+ DWORD dwcbResult;
+
+ CHKNT(BCryptOpenAlgorithmProvider(&_hAlg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0));
+
+ CHKNT(BCryptGetProperty(_hAlg, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PBYTE>(&dwcb), sizeof(dwcb), &dwcbResult, 0));
+
+ _ahBuf.Value() = new (std::nothrow) BYTE[dwcb];
+ if (nullptr == _ahBuf.Value())
+ {
+ CHKHR( E_OUTOFMEMORY );
+ }
+
+ CHKNT(BCryptCreateHash(_hAlg, &_hHash, _ahBuf.Value(), dwcb, NULL, 0, 0));
+ return S_OK;
+ }
+ HRESULT AppendData(size_t numBytes, __in_bcount(numBytes) const void* bytes)
+ {
+ CHKHR(Verify(numBytes <= DWORD(-1)));
+ CHKNT(BCryptHashData(_hHash, reinterpret_cast<UCHAR*>(const_cast<void*>(bytes)), DWORD(numBytes), 0));
+ return S_OK;;
+ }
+ HRESULT GetResult(__out BYTE (*hashValue)[20])
+ {
+
+ // Sha1 hash result is fixed size, at 20 bytes.
+
+ CHKNT(BCryptFinishHash(_hHash, reinterpret_cast<PUCHAR>(&hashValue[0]), _countof(*hashValue), 0));
+ return S_OK;
+ }
+ ~Sha1()
+ {
+ if (_hHash)
+ {
+ BCryptDestroyHash(_hHash);
+ }
+ if (_hAlg)
+ {
+ BCryptCloseAlgorithmProvider(_hAlg, 0);
+ }
+ }
+ private:
+
+ ArrayHolder<BYTE> _ahBuf;
+ BCRYPT_ALG_HANDLE _hAlg;
+ BCRYPT_HASH_HANDLE _hHash;
+ };
+}} // namespace Ro::detail
+
+extern "C"
+{
+
+inline HRESULT _RoSha1Create(
+ __out void** handle)
+{
+ *handle = nullptr;
+
+ Ro::detail::ElementHolder<Ro::detail::Sha1> sha1Instance;
+ sha1Instance.Value() = new (std::nothrow) Ro::detail::Sha1;
+ if (!sha1Instance.Value())
+ {
+ CHKHR(E_OUTOFMEMORY);
+ }
+ CHKHR(sha1Instance->Initialize());
+
+ *handle = sha1Instance.Detach();
+ return S_OK;
+}
+
+
+inline HRESULT _RoSha1AppendData(
+ __in void* handle,
+ __in size_t numBytes,
+ __in_bcount(numBytes) const void* data)
+{
+ Ro::detail::Sha1* sha1Instance = static_cast<Ro::detail::Sha1*>(handle);
+ CHKHR(sha1Instance->AppendData(numBytes, data));
+ return S_OK;
+}
+
+
+inline HRESULT _RoSha1Finish(
+ __in void* handle,
+ __out BYTE (*hashValue)[20])
+{
+ Ro::detail::Sha1* sha1Instance = static_cast<Ro::detail::Sha1*>(handle);
+ CHKHR(sha1Instance->GetResult(hashValue));
+ return S_OK;
+}
+
+inline void _RoSha1Release(__in void* handle)
+{
+ Ro::detail::Sha1* sha1Instance = static_cast<Ro::detail::Sha1*>(handle);
+ delete sha1Instance;
+}
+
+}
+
+#endif /* ifdef WINRT_PARAMINSTANCE_NOCRYPT_SHA1 */
+
+#ifdef _MSC_VER
+#pragma pop_macro("CHKNT")
+#pragma pop_macro("CHKHR")
+#pragma warning( pop )
+#endif
+
+#endif /* ifdef __cplusplus */
+#endif /* ifndef WINRT_PARAMINSTANCEAPI_H */