// Copyright (c) Microsoft Corporation
// All rights reserved. 
//
// Licensed under the Apache License, Version 2.0 (the ""License""); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
// THIS CODE IS PROVIDED ON AN  *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//
// See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.

#define NTDDI_VERSION 0x06010000

#include <v8.h>
#include <string>
#include <node_object_wrap.h>
#include <ppltasks.h>
#include "CollectionsConverter.h"
#include "CollectionsWrap.h"
#include "node-async.h"
#include "NodeRtUtils.h"
#include "OpaqueWrapper.h"
#include "WrapperBase.h"

#using <Windows.WinMD>

// this undefs fixes the issues of compiling Windows.Data.Json, Windows.Storag.FileProperties, and Windows.Stroage.Search
// Some of the node header files brings windows definitions with the same names as some of the WinRT methods
#undef DocumentProperties
#undef GetObject
#undef CreateEvent
#undef FindText
#undef SendMessage

const char* REGISTRATION_TOKEN_MAP_PROPERTY_NAME = "__registrationTokenMap__";

using namespace v8;
using namespace node;
using namespace concurrency;

namespace NodeRT { namespace Windows { namespace Security { namespace Cryptography { namespace Certificates { 
  v8::Handle<v8::Value> WrapCertificate(::Windows::Security::Cryptography::Certificates::Certificate^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::Certificate^ UnwrapCertificate(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCertificateRequestProperties(::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ UnwrapCertificateRequestProperties(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapUserCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ UnwrapUserCertificateEnrollmentManager(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ UnwrapCertificateEnrollmentManager(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapKeyAttestationHelper(::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ UnwrapKeyAttestationHelper(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCertificateQuery(::Windows::Security::Cryptography::Certificates::CertificateQuery^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CertificateQuery^ UnwrapCertificateQuery(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCertificateStore(::Windows::Security::Cryptography::Certificates::CertificateStore^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CertificateStore^ UnwrapCertificateStore(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCertificateStores(::Windows::Security::Cryptography::Certificates::CertificateStores^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CertificateStores^ UnwrapCertificateStores(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapKeyAlgorithmNames(::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ UnwrapKeyAlgorithmNames(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapKeyStorageProviderNames(::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ UnwrapKeyStorageProviderNames(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapChainBuildingParameters(::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ UnwrapChainBuildingParameters(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapChainValidationParameters(::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ UnwrapChainValidationParameters(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCertificateChain(::Windows::Security::Cryptography::Certificates::CertificateChain^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CertificateChain^ UnwrapCertificateChain(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCmsTimestampInfo(::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ UnwrapCmsTimestampInfo(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCmsSignerInfo(::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ UnwrapCmsSignerInfo(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCmsAttachedSignature(::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ UnwrapCmsAttachedSignature(Handle<Value> value);
  
  v8::Handle<v8::Value> WrapCmsDetachedSignature(::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ wintRtInstance);
  ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ UnwrapCmsDetachedSignature(Handle<Value> value);
  


  static v8::Handle<v8::Value> InitEnrollKeyUsagesEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("EnrollKeyUsages"), enumObject);

    enumObject->Set(String::NewSymbol("none"), Integer::New(0));
    enumObject->Set(String::NewSymbol("decryption"), Integer::New(1));
    enumObject->Set(String::NewSymbol("signing"), Integer::New(2));
    enumObject->Set(String::NewSymbol("keyAgreement"), Integer::New(3));
    enumObject->Set(String::NewSymbol("all"), Integer::New(4));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitKeyProtectionLevelEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("KeyProtectionLevel"), enumObject);

    enumObject->Set(String::NewSymbol("noConsent"), Integer::New(0));
    enumObject->Set(String::NewSymbol("consentOnly"), Integer::New(1));
    enumObject->Set(String::NewSymbol("consentWithPassword"), Integer::New(2));
    enumObject->Set(String::NewSymbol("consentWithFingerprint"), Integer::New(3));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitExportOptionEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("ExportOption"), enumObject);

    enumObject->Set(String::NewSymbol("notExportable"), Integer::New(0));
    enumObject->Set(String::NewSymbol("exportable"), Integer::New(1));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitKeySizeEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("KeySize"), enumObject);

    enumObject->Set(String::NewSymbol("invalid"), Integer::New(0));
    enumObject->Set(String::NewSymbol("rsa2048"), Integer::New(1));
    enumObject->Set(String::NewSymbol("rsa4096"), Integer::New(2));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitInstallOptionsEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("InstallOptions"), enumObject);

    enumObject->Set(String::NewSymbol("none"), Integer::New(0));
    enumObject->Set(String::NewSymbol("deleteExpired"), Integer::New(1));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitCertificateChainPolicyEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("CertificateChainPolicy"), enumObject);

    enumObject->Set(String::NewSymbol("base"), Integer::New(0));
    enumObject->Set(String::NewSymbol("ssl"), Integer::New(1));
    enumObject->Set(String::NewSymbol("nTAuthentication"), Integer::New(2));
    enumObject->Set(String::NewSymbol("microsoftRoot"), Integer::New(3));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitChainValidationResultEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("ChainValidationResult"), enumObject);

    enumObject->Set(String::NewSymbol("success"), Integer::New(0));
    enumObject->Set(String::NewSymbol("untrusted"), Integer::New(1));
    enumObject->Set(String::NewSymbol("revoked"), Integer::New(2));
    enumObject->Set(String::NewSymbol("expired"), Integer::New(3));
    enumObject->Set(String::NewSymbol("incompleteChain"), Integer::New(4));
    enumObject->Set(String::NewSymbol("invalidSignature"), Integer::New(5));
    enumObject->Set(String::NewSymbol("wrongUsage"), Integer::New(6));
    enumObject->Set(String::NewSymbol("invalidName"), Integer::New(7));
    enumObject->Set(String::NewSymbol("invalidCertificateAuthorityPolicy"), Integer::New(8));
    enumObject->Set(String::NewSymbol("basicConstraintsError"), Integer::New(9));
    enumObject->Set(String::NewSymbol("unknownCriticalExtension"), Integer::New(10));
    enumObject->Set(String::NewSymbol("revocationInformationMissing"), Integer::New(11));
    enumObject->Set(String::NewSymbol("revocationFailure"), Integer::New(12));
    enumObject->Set(String::NewSymbol("otherErrors"), Integer::New(13));

    return scope.Close(Undefined());
  }


  static v8::Handle<v8::Value> InitSignatureValidationResultEnum(const Handle<Object> exports)
  {
    HandleScope scope;
    
    Handle<Object> enumObject = Object::New();
    exports->Set(String::NewSymbol("SignatureValidationResult"), enumObject);

    enumObject->Set(String::NewSymbol("success"), Integer::New(0));
    enumObject->Set(String::NewSymbol("invalidParameter"), Integer::New(1));
    enumObject->Set(String::NewSymbol("badMessage"), Integer::New(2));
    enumObject->Set(String::NewSymbol("invalidSignature"), Integer::New(3));
    enumObject->Set(String::NewSymbol("otherErrors"), Integer::New(4));

    return scope.Close(Undefined());
  }



  
  class Certificate : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("Certificate"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
            
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("getHashValue"), FunctionTemplate::New(GetHashValue)->GetFunction());
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("getCertificateBlob"), FunctionTemplate::New(GetCertificateBlob)->GetFunction());
      
            
      func = FunctionTemplate::New(BuildChainAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("buildChainAsync"), func);
      
                  
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("friendlyName"), FriendlyNameGetter, FriendlyNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("enhancedKeyUsages"), EnhancedKeyUsagesGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("hasPrivateKey"), HasPrivateKeyGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("isStronglyProtected"), IsStronglyProtectedGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("issuer"), IssuerGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("serialNumber"), SerialNumberGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("subject"), SubjectGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("validFrom"), ValidFromGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("validTo"), ValidToGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("Certificate"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    Certificate(::Windows::Security::Cryptography::Certificates::Certificate^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::Certificate^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::Certificate^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Storage::Streams::IBuffer^>(args[0]))
      {
        try
        {
          ::Windows::Storage::Streams::IBuffer^ arg0 = dynamic_cast<::Windows::Storage::Streams::IBuffer^>(NodeRT::Utils::GetObjectInstance(args[0]));
          
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::Certificate(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      Certificate *wrapperInstance = new Certificate(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


    static Handle<Value> BuildChainAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(args.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Security::Cryptography::Certificates::CertificateChain^>^ op;
    

      if (args.Length() == 2
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(args[0]) || args[0]->IsArray()))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^ arg0 = 
            [] (v8::Handle<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::Security::Cryptography::Certificates::Certificate^>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
                 },
                 [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
                   return UnwrapCertificate(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (args[0]);
          
          op = wrapper->_instance->BuildChainAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 3
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(args[0]) || args[0]->IsArray())
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(args[1]))
      {
        try
        {
          ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^ arg0 = 
            [] (v8::Handle<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::Security::Cryptography::Certificates::Certificate^>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
                 },
                 [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
                   return UnwrapCertificate(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (args[0]);
          ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ arg1 = UnwrapChainBuildingParameters(args[1]);
          
          op = wrapper->_instance->BuildChainAsync(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Security::Cryptography::Certificates::CertificateChain^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = WrapCertificateChain(result);
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
  
    static Handle<Value> GetHashValue(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(args.This());

      if (args.Length() == 0)
      {
        try
        {
          ::Platform::Array<unsigned char>^ result;
          result = wrapper->_instance->GetHashValue();
          return scope.Close(NodeRT::Collections::ArrayWrapper<unsigned char>::CreateArrayWrapper(result, 
            [](unsigned char val) -> Handle<Value> {
              return Integer::New(val);
            },
            [](Handle<Value> value) -> bool {
              return value->IsInt32();
            },
            [](Handle<Value> value) -> unsigned char {
              return static_cast<unsigned char>(value->Int32Value());
            }
          ));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 1
        && args[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          
          ::Platform::Array<unsigned char>^ result;
          result = wrapper->_instance->GetHashValue(arg0);
          return scope.Close(NodeRT::Collections::ArrayWrapper<unsigned char>::CreateArrayWrapper(result, 
            [](unsigned char val) -> Handle<Value> {
              return Integer::New(val);
            },
            [](Handle<Value> value) -> bool {
              return value->IsInt32();
            },
            [](Handle<Value> value) -> unsigned char {
              return static_cast<unsigned char>(value->Int32Value());
            }
          ));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }
    static Handle<Value> GetCertificateBlob(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(args.This());

      if (args.Length() == 0)
      {
        try
        {
          ::Windows::Storage::Streams::IBuffer^ result;
          result = wrapper->_instance->GetCertificateBlob();
          return scope.Close(NodeRT::Utils::CreateExternalWinRTObject("Windows.Storage.Streams", "IBuffer", result));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }



    static Handle<Value> FriendlyNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->FriendlyName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void FriendlyNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return;
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->FriendlyName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> EnhancedKeyUsagesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVectorView<::Platform::String^>^ result = wrapper->_instance->EnhancedKeyUsages;
        return scope.Close(NodeRT::Collections::VectorViewWrapper<::Platform::String^>::CreateVectorViewWrapper(result, 
            [](::Platform::String^ val) -> Handle<Value> {
              return NodeRT::Utils::NewString(val->Data());
            },
            [](Handle<Value> value) -> bool {
              return value->IsString();
            },
            [](Handle<Value> value) -> ::Platform::String^ {
              return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> HasPrivateKeyGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        bool result = wrapper->_instance->HasPrivateKey;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> IsStronglyProtectedGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        bool result = wrapper->_instance->IsStronglyProtected;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> IssuerGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->Issuer;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SerialNumberGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        ::Platform::Array<unsigned char>^ result = wrapper->_instance->SerialNumber;
        return scope.Close(NodeRT::Collections::ArrayWrapper<unsigned char>::CreateArrayWrapper(result, 
            [](unsigned char val) -> Handle<Value> {
              return Integer::New(val);
            },
            [](Handle<Value> value) -> bool {
              return value->IsInt32();
            },
            [](Handle<Value> value) -> unsigned char {
              return static_cast<unsigned char>(value->Int32Value());
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SubjectGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->Subject;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> ValidFromGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->ValidFrom;
        return scope.Close(NodeRT::Utils::DateTimeToJS(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> ValidToGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      Certificate *wrapper = Certificate::Unwrap<Certificate>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->ValidTo;
        return scope.Close(NodeRT::Utils::DateTimeToJS(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::Certificate^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificate(::Windows::Security::Cryptography::Certificates::Certificate^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::Certificate^ UnwrapCertificate(Handle<Value> value);
    friend bool IsCertificateWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> Certificate::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificate(::Windows::Security::Cryptography::Certificates::Certificate^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(Certificate::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::Certificate^ UnwrapCertificate(Handle<Value> value)
  {
     return Certificate::Unwrap<Certificate>(value.As<Object>())->_instance;
  }

  void InitCertificate(Handle<Object> exports)
  {
    Certificate::Init(exports);
  }

  class CertificateRequestProperties : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CertificateRequestProperties"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("subject"), SubjectGetter, SubjectSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("keyUsages"), KeyUsagesGetter, KeyUsagesSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("keyStorageProviderName"), KeyStorageProviderNameGetter, KeyStorageProviderNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("keySize"), KeySizeGetter, KeySizeSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("keyProtectionLevel"), KeyProtectionLevelGetter, KeyProtectionLevelSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("keyAlgorithmName"), KeyAlgorithmNameGetter, KeyAlgorithmNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("hashAlgorithmName"), HashAlgorithmNameGetter, HashAlgorithmNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("friendlyName"), FriendlyNameGetter, FriendlyNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("exportable"), ExportableGetter, ExportableSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("smartcardReaderName"), SmartcardReaderNameGetter, SmartcardReaderNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("signingCertificate"), SigningCertificateGetter, SigningCertificateSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("attestationCredentialCertificate"), AttestationCredentialCertificateGetter, AttestationCredentialCertificateSetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("CertificateRequestProperties"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CertificateRequestProperties(::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CertificateRequestProperties *wrapperInstance = new CertificateRequestProperties(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  



    static Handle<Value> SubjectGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->Subject;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void SubjectSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->Subject = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> KeyUsagesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::EnrollKeyUsages result = wrapper->_instance->KeyUsages;
        return scope.Close(Integer::New(static_cast<int>(result)));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void KeyUsagesSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::EnrollKeyUsages winRtValue = static_cast<::Windows::Security::Cryptography::Certificates::EnrollKeyUsages>(value->Int32Value());

        wrapper->_instance->KeyUsages = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> KeyStorageProviderNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->KeyStorageProviderName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void KeyStorageProviderNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->KeyStorageProviderName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> KeySizeGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        unsigned int result = wrapper->_instance->KeySize;
        return scope.Close(Integer::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void KeySizeSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsUint32())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        unsigned int winRtValue = static_cast<unsigned int>(value->IntegerValue());

        wrapper->_instance->KeySize = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> KeyProtectionLevelGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::KeyProtectionLevel result = wrapper->_instance->KeyProtectionLevel;
        return scope.Close(Integer::New(static_cast<int>(result)));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void KeyProtectionLevelSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::KeyProtectionLevel winRtValue = static_cast<::Windows::Security::Cryptography::Certificates::KeyProtectionLevel>(value->Int32Value());

        wrapper->_instance->KeyProtectionLevel = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> KeyAlgorithmNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->KeyAlgorithmName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void KeyAlgorithmNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->KeyAlgorithmName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> HashAlgorithmNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->HashAlgorithmName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void HashAlgorithmNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->HashAlgorithmName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> FriendlyNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->FriendlyName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void FriendlyNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->FriendlyName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> ExportableGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::ExportOption result = wrapper->_instance->Exportable;
        return scope.Close(Integer::New(static_cast<int>(result)));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void ExportableSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::ExportOption winRtValue = static_cast<::Windows::Security::Cryptography::Certificates::ExportOption>(value->Int32Value());

        wrapper->_instance->Exportable = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> SmartcardReaderNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->SmartcardReaderName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void SmartcardReaderNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->SmartcardReaderName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> SigningCertificateGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::Certificate^ result = wrapper->_instance->SigningCertificate;
        return scope.Close(WrapCertificate(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void SigningCertificateSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value))
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::Certificate^ winRtValue = dynamic_cast<::Windows::Security::Cryptography::Certificates::Certificate^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->SigningCertificate = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> AttestationCredentialCertificateGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::Certificate^ result = wrapper->_instance->AttestationCredentialCertificate;
        return scope.Close(WrapCertificate(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void AttestationCredentialCertificateSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value))
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(info.This()))
      {
        return;
      }

      CertificateRequestProperties *wrapper = CertificateRequestProperties::Unwrap<CertificateRequestProperties>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::Certificate^ winRtValue = dynamic_cast<::Windows::Security::Cryptography::Certificates::Certificate^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->AttestationCredentialCertificate = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificateRequestProperties(::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ UnwrapCertificateRequestProperties(Handle<Value> value);
    friend bool IsCertificateRequestPropertiesWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CertificateRequestProperties::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificateRequestProperties(::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CertificateRequestProperties::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ UnwrapCertificateRequestProperties(Handle<Value> value)
  {
     return CertificateRequestProperties::Unwrap<CertificateRequestProperties>(value.As<Object>())->_instance;
  }

  void InitCertificateRequestProperties(Handle<Object> exports)
  {
    CertificateRequestProperties::Init(exports);
  }

  class UserCertificateEnrollmentManager : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("UserCertificateEnrollmentManager"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
                  
      func = FunctionTemplate::New(CreateRequestAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("createRequestAsync"), func);
      func = FunctionTemplate::New(InstallCertificateAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("installCertificateAsync"), func);
      func = FunctionTemplate::New(ImportPfxDataAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("importPfxDataAsync"), func);
      
                  
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("UserCertificateEnrollmentManager"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    UserCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      UserCertificateEnrollmentManager *wrapperInstance = new UserCertificateEnrollmentManager(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


    static Handle<Value> CreateRequestAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      UserCertificateEnrollmentManager *wrapper = UserCertificateEnrollmentManager::Unwrap<UserCertificateEnrollmentManager>(args.This());

      ::Windows::Foundation::IAsyncOperation<::Platform::String^>^ op;
    

      if (args.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(args[0]))
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ arg0 = UnwrapCertificateRequestProperties(args[0]);
          
          op = wrapper->_instance->CreateRequestAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Platform::String^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = NodeRT::Utils::NewString(result->Data());
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
    static Handle<Value> InstallCertificateAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      UserCertificateEnrollmentManager *wrapper = UserCertificateEnrollmentManager::Unwrap<UserCertificateEnrollmentManager>(args.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (args.Length() == 3
        && args[0]->IsString()
        && args[1]->IsInt32())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          ::Windows::Security::Cryptography::Certificates::InstallOptions arg1 = static_cast<::Windows::Security::Cryptography::Certificates::InstallOptions>(args[1]->Int32Value());
          
          op = wrapper->_instance->InstallCertificateAsync(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Handle<Value> args[] = {Undefined()};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
    static Handle<Value> ImportPfxDataAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      UserCertificateEnrollmentManager *wrapper = UserCertificateEnrollmentManager::Unwrap<UserCertificateEnrollmentManager>(args.This());

      ::Windows::Foundation::IAsyncAction^ op;
    

      if (args.Length() == 7
        && args[0]->IsString()
        && args[1]->IsString()
        && args[2]->IsInt32()
        && args[3]->IsInt32()
        && args[4]->IsInt32()
        && args[5]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[1])));
          ::Windows::Security::Cryptography::Certificates::ExportOption arg2 = static_cast<::Windows::Security::Cryptography::Certificates::ExportOption>(args[2]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::KeyProtectionLevel arg3 = static_cast<::Windows::Security::Cryptography::Certificates::KeyProtectionLevel>(args[3]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::InstallOptions arg4 = static_cast<::Windows::Security::Cryptography::Certificates::InstallOptions>(args[4]->Int32Value());
          Platform::String^ arg5 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[5])));
          
          op = wrapper->_instance->ImportPfxDataAsync(arg0,arg1,arg2,arg3,arg4,arg5);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 8
        && args[0]->IsString()
        && args[1]->IsString()
        && args[2]->IsInt32()
        && args[3]->IsInt32()
        && args[4]->IsInt32()
        && args[5]->IsString()
        && args[6]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[1])));
          ::Windows::Security::Cryptography::Certificates::ExportOption arg2 = static_cast<::Windows::Security::Cryptography::Certificates::ExportOption>(args[2]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::KeyProtectionLevel arg3 = static_cast<::Windows::Security::Cryptography::Certificates::KeyProtectionLevel>(args[3]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::InstallOptions arg4 = static_cast<::Windows::Security::Cryptography::Certificates::InstallOptions>(args[4]->Int32Value());
          Platform::String^ arg5 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[5])));
          Platform::String^ arg6 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[6])));
          
          op = wrapper->_instance->ImportPfxDataAsync(arg0,arg1,arg2,arg3,arg4,arg5,arg6);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            Handle<Value> args[] = {Undefined()};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
  





  private:
    ::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapUserCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ UnwrapUserCertificateEnrollmentManager(Handle<Value> value);
    friend bool IsUserCertificateEnrollmentManagerWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> UserCertificateEnrollmentManager::s_constructorTemplate;

  v8::Handle<v8::Value> WrapUserCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(UserCertificateEnrollmentManager::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ UnwrapUserCertificateEnrollmentManager(Handle<Value> value)
  {
     return UserCertificateEnrollmentManager::Unwrap<UserCertificateEnrollmentManager>(value.As<Object>())->_instance;
  }

  void InitUserCertificateEnrollmentManager(Handle<Object> exports)
  {
    UserCertificateEnrollmentManager::Init(exports);
  }

  class CertificateEnrollmentManager : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CertificateEnrollmentManager"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
                              
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      func = FunctionTemplate::New(ImportPfxDataAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("importPfxDataAsync"), func);
      func = FunctionTemplate::New(CreateRequestAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("createRequestAsync"), func);
      func = FunctionTemplate::New(InstallCertificateAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("installCertificateAsync"), func);
      constructor->SetAccessor(String::NewSymbol("userCertificateEnrollmentManager"), UserCertificateEnrollmentManagerGetter);

      exports->Set(String::NewSymbol("CertificateEnrollmentManager"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CertificateEnrollmentManager *wrapperInstance = new CertificateEnrollmentManager(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  

    static Handle<Value> ImportPfxDataAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncAction^ op;
      

      if (args.Length() == 8
        && args[0]->IsString()
        && args[1]->IsString()
        && args[2]->IsInt32()
        && args[3]->IsInt32()
        && args[4]->IsInt32()
        && args[5]->IsString()
        && args[6]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[1])));
          ::Windows::Security::Cryptography::Certificates::ExportOption arg2 = static_cast<::Windows::Security::Cryptography::Certificates::ExportOption>(args[2]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::KeyProtectionLevel arg3 = static_cast<::Windows::Security::Cryptography::Certificates::KeyProtectionLevel>(args[3]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::InstallOptions arg4 = static_cast<::Windows::Security::Cryptography::Certificates::InstallOptions>(args[4]->Int32Value());
          Platform::String^ arg5 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[5])));
          Platform::String^ arg6 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[6])));
          
          op = ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager::ImportPfxDataAsync(arg0,arg1,arg2,arg3,arg4,arg5,arg6);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 7
        && args[0]->IsString()
        && args[1]->IsString()
        && args[2]->IsInt32()
        && args[3]->IsInt32()
        && args[4]->IsInt32()
        && args[5]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          Platform::String^ arg1 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[1])));
          ::Windows::Security::Cryptography::Certificates::ExportOption arg2 = static_cast<::Windows::Security::Cryptography::Certificates::ExportOption>(args[2]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::KeyProtectionLevel arg3 = static_cast<::Windows::Security::Cryptography::Certificates::KeyProtectionLevel>(args[3]->Int32Value());
          ::Windows::Security::Cryptography::Certificates::InstallOptions arg4 = static_cast<::Windows::Security::Cryptography::Certificates::InstallOptions>(args[4]->Int32Value());
          Platform::String^ arg5 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[5])));
          
          op = ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager::ImportPfxDataAsync(arg0,arg1,arg2,arg3,arg4,arg5);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            Handle<Value> args[] = {Undefined()};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
    static Handle<Value> CreateRequestAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncOperation<::Platform::String^>^ op;
      

      if (args.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^>(args[0]))
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::CertificateRequestProperties^ arg0 = UnwrapCertificateRequestProperties(args[0]);
          
          op = ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager::CreateRequestAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Platform::String^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = NodeRT::Utils::NewString(result->Data());
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
    static Handle<Value> InstallCertificateAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncAction^ op;
      

      if (args.Length() == 3
        && args[0]->IsString()
        && args[1]->IsInt32())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          ::Windows::Security::Cryptography::Certificates::InstallOptions arg1 = static_cast<::Windows::Security::Cryptography::Certificates::InstallOptions>(args[1]->Int32Value());
          
          op = ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager::InstallCertificateAsync(arg0,arg1);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<void> t) 
      {	
        try
        {
          t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            Handle<Value> args[] = {Undefined()};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }



    static Handle<Value> UserCertificateEnrollmentManagerGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        ::Windows::Security::Cryptography::Certificates::UserCertificateEnrollmentManager^ result = ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager::UserCertificateEnrollmentManager;
        return scope.Close(WrapUserCertificateEnrollmentManager(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    

  private:
    ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ UnwrapCertificateEnrollmentManager(Handle<Value> value);
    friend bool IsCertificateEnrollmentManagerWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CertificateEnrollmentManager::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificateEnrollmentManager(::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CertificateEnrollmentManager::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CertificateEnrollmentManager^ UnwrapCertificateEnrollmentManager(Handle<Value> value)
  {
     return CertificateEnrollmentManager::Unwrap<CertificateEnrollmentManager>(value.As<Object>())->_instance;
  }

  void InitCertificateEnrollmentManager(Handle<Object> exports)
  {
    CertificateEnrollmentManager::Init(exports);
  }

  class KeyAttestationHelper : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("KeyAttestationHelper"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
                              
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      constructor->Set(String::NewSymbol("getTpmAttestationCredentialId"), FunctionTemplate::New(GetTpmAttestationCredentialId)->GetFunction());
      func = FunctionTemplate::New(DecryptTpmAttestationCredentialAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("decryptTpmAttestationCredentialAsync"), func);

      exports->Set(String::NewSymbol("KeyAttestationHelper"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    KeyAttestationHelper(::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      KeyAttestationHelper *wrapperInstance = new KeyAttestationHelper(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  

    static Handle<Value> DecryptTpmAttestationCredentialAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncOperation<::Platform::String^>^ op;
      

      if (args.Length() == 2
        && args[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          
          op = ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper::DecryptTpmAttestationCredentialAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Platform::String^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = NodeRT::Utils::NewString(result->Data());
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }

    static Handle<Value> GetTpmAttestationCredentialId(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 1
        && args[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          
          Platform::String^ result;
          result = ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper::GetTpmAttestationCredentialId(arg0);
          return scope.Close(NodeRT::Utils::NewString(result->Data()));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }



  private:
    ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapKeyAttestationHelper(::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ UnwrapKeyAttestationHelper(Handle<Value> value);
    friend bool IsKeyAttestationHelperWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> KeyAttestationHelper::s_constructorTemplate;

  v8::Handle<v8::Value> WrapKeyAttestationHelper(::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(KeyAttestationHelper::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::KeyAttestationHelper^ UnwrapKeyAttestationHelper(Handle<Value> value)
  {
     return KeyAttestationHelper::Unwrap<KeyAttestationHelper>(value.As<Object>())->_instance;
  }

  void InitKeyAttestationHelper(Handle<Object> exports)
  {
    KeyAttestationHelper::Init(exports);
  }

  class CertificateQuery : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CertificateQuery"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("thumbprint"), ThumbprintGetter, ThumbprintSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("issuerName"), IssuerNameGetter, IssuerNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("hardwareOnly"), HardwareOnlyGetter, HardwareOnlySetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("friendlyName"), FriendlyNameGetter, FriendlyNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("enhancedKeyUsages"), EnhancedKeyUsagesGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("CertificateQuery"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CertificateQuery(::Windows::Security::Cryptography::Certificates::CertificateQuery^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CertificateQuery^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CertificateQuery^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::CertificateQuery();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CertificateQuery *wrapperInstance = new CertificateQuery(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  



    static Handle<Value> ThumbprintGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        ::Platform::Array<unsigned char>^ result = wrapper->_instance->Thumbprint;
        return scope.Close(NodeRT::Collections::ArrayWrapper<unsigned char>::CreateArrayWrapper(result, 
            [](unsigned char val) -> Handle<Value> {
              return Integer::New(val);
            },
            [](Handle<Value> value) -> bool {
              return value->IsInt32();
            },
            [](Handle<Value> value) -> unsigned char {
              return static_cast<unsigned char>(value->Int32Value());
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void ThumbprintSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!(NodeRT::Utils::IsWinRtWrapperOf<::Platform::Array<unsigned char>^>(value) || value->IsArray()))
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return;
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        
        ::Platform::Array<unsigned char>^ winRtValue = 
            [] (v8::Handle<v8::Value> value) -> ::Platform::Array<unsigned char>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtArray<unsigned char>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return value->IsInt32();
                 },
                 [](Handle<Value> value) -> unsigned char {
                   return static_cast<unsigned char>(value->Int32Value());
                 }
                );
              }
              else
              {
                return dynamic_cast<::Platform::Array<unsigned char>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (value);

        wrapper->_instance->Thumbprint = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> IssuerNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->IssuerName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void IssuerNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return;
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->IssuerName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> HardwareOnlyGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        bool result = wrapper->_instance->HardwareOnly;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void HardwareOnlySetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return;
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        
        bool winRtValue = value->BooleanValue();

        wrapper->_instance->HardwareOnly = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> FriendlyNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->FriendlyName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void FriendlyNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return;
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->FriendlyName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> EnhancedKeyUsagesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateQuery *wrapper = CertificateQuery::Unwrap<CertificateQuery>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVector<::Platform::String^>^ result = wrapper->_instance->EnhancedKeyUsages;
        return scope.Close(NodeRT::Collections::VectorWrapper<::Platform::String^>::CreateVectorWrapper(result, 
            [](::Platform::String^ val) -> Handle<Value> {
              return NodeRT::Utils::NewString(val->Data());
            },
            [](Handle<Value> value) -> bool {
              return value->IsString();
            },
            [](Handle<Value> value) -> ::Platform::String^ {
              return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::CertificateQuery^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificateQuery(::Windows::Security::Cryptography::Certificates::CertificateQuery^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CertificateQuery^ UnwrapCertificateQuery(Handle<Value> value);
    friend bool IsCertificateQueryWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CertificateQuery::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificateQuery(::Windows::Security::Cryptography::Certificates::CertificateQuery^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CertificateQuery::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CertificateQuery^ UnwrapCertificateQuery(Handle<Value> value)
  {
     return CertificateQuery::Unwrap<CertificateQuery>(value.As<Object>())->_instance;
  }

  void InitCertificateQuery(Handle<Object> exports)
  {
    CertificateQuery::Init(exports);
  }

  class CertificateStore : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CertificateStore"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("add"), FunctionTemplate::New(Add)->GetFunction());
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("delete"), FunctionTemplate::New(Delete)->GetFunction());
      
                        
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("CertificateStore"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CertificateStore(::Windows::Security::Cryptography::Certificates::CertificateStore^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CertificateStore^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateStore^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CertificateStore^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CertificateStore *wrapperInstance = new CertificateStore(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  
    static Handle<Value> Add(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateStore^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateStore *wrapper = CertificateStore::Unwrap<CertificateStore>(args.This());

      if (args.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(args[0]))
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::Certificate^ arg0 = UnwrapCertificate(args[0]);
          
          wrapper->_instance->Add(arg0);
          return scope.Close(Undefined());   
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }
    static Handle<Value> Delete(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateStore^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateStore *wrapper = CertificateStore::Unwrap<CertificateStore>(args.This());

      if (args.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(args[0]))
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::Certificate^ arg0 = UnwrapCertificate(args[0]);
          
          wrapper->_instance->Delete(arg0);
          return scope.Close(Undefined());   
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }





  private:
    ::Windows::Security::Cryptography::Certificates::CertificateStore^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificateStore(::Windows::Security::Cryptography::Certificates::CertificateStore^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CertificateStore^ UnwrapCertificateStore(Handle<Value> value);
    friend bool IsCertificateStoreWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CertificateStore::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificateStore(::Windows::Security::Cryptography::Certificates::CertificateStore^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CertificateStore::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CertificateStore^ UnwrapCertificateStore(Handle<Value> value)
  {
     return CertificateStore::Unwrap<CertificateStore>(value.As<Object>())->_instance;
  }

  void InitCertificateStore(Handle<Object> exports)
  {
    CertificateStore::Init(exports);
  }

  class CertificateStores : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CertificateStores"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
                              
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      constructor->Set(String::NewSymbol("getStoreByName"), FunctionTemplate::New(GetStoreByName)->GetFunction());
      func = FunctionTemplate::New(FindAllAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("findAllAsync"), func);
      constructor->SetAccessor(String::NewSymbol("intermediateCertificationAuthorities"), IntermediateCertificationAuthoritiesGetter);
      constructor->SetAccessor(String::NewSymbol("trustedRootCertificationAuthorities"), TrustedRootCertificationAuthoritiesGetter);

      exports->Set(String::NewSymbol("CertificateStores"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CertificateStores(::Windows::Security::Cryptography::Certificates::CertificateStores^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CertificateStores^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateStores^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CertificateStores^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CertificateStores *wrapperInstance = new CertificateStores(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  

    static Handle<Value> FindAllAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::Certificate^>^>^ op;
      

      if (args.Length() == 1)
      {
        try
        {
          op = ::Windows::Security::Cryptography::Certificates::CertificateStores::FindAllAsync();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateQuery^>(args[0]))
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::CertificateQuery^ arg0 = UnwrapCertificateQuery(args[0]);
          
          op = ::Windows::Security::Cryptography::Certificates::CertificateStores::FindAllAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::Certificate^>^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::Certificate^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::Certificate^ val) -> Handle<Value> {
              return WrapCertificate(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
              return UnwrapCertificate(value);
            }
          );
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }

    static Handle<Value> GetStoreByName(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 1
        && args[0]->IsString())
      {
        try
        {
          Platform::String^ arg0 = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(args[0])));
          
          ::Windows::Security::Cryptography::Certificates::CertificateStore^ result;
          result = ::Windows::Security::Cryptography::Certificates::CertificateStores::GetStoreByName(arg0);
          return scope.Close(WrapCertificateStore(result));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }


    static Handle<Value> IntermediateCertificationAuthoritiesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        ::Windows::Security::Cryptography::Certificates::CertificateStore^ result = ::Windows::Security::Cryptography::Certificates::CertificateStores::IntermediateCertificationAuthorities;
        return scope.Close(WrapCertificateStore(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> TrustedRootCertificationAuthoritiesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        ::Windows::Security::Cryptography::Certificates::CertificateStore^ result = ::Windows::Security::Cryptography::Certificates::CertificateStores::TrustedRootCertificationAuthorities;
        return scope.Close(WrapCertificateStore(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    

  private:
    ::Windows::Security::Cryptography::Certificates::CertificateStores^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificateStores(::Windows::Security::Cryptography::Certificates::CertificateStores^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CertificateStores^ UnwrapCertificateStores(Handle<Value> value);
    friend bool IsCertificateStoresWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CertificateStores::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificateStores(::Windows::Security::Cryptography::Certificates::CertificateStores^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CertificateStores::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CertificateStores^ UnwrapCertificateStores(Handle<Value> value)
  {
     return CertificateStores::Unwrap<CertificateStores>(value.As<Object>())->_instance;
  }

  void InitCertificateStores(Handle<Object> exports)
  {
    CertificateStores::Init(exports);
  }

  class KeyAlgorithmNames : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("KeyAlgorithmNames"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      constructor->SetAccessor(String::NewSymbol("dsa"), DsaGetter);
      constructor->SetAccessor(String::NewSymbol("ecdh256"), Ecdh256Getter);
      constructor->SetAccessor(String::NewSymbol("ecdh384"), Ecdh384Getter);
      constructor->SetAccessor(String::NewSymbol("ecdh521"), Ecdh521Getter);
      constructor->SetAccessor(String::NewSymbol("ecdsa256"), Ecdsa256Getter);
      constructor->SetAccessor(String::NewSymbol("ecdsa384"), Ecdsa384Getter);
      constructor->SetAccessor(String::NewSymbol("ecdsa521"), Ecdsa521Getter);
      constructor->SetAccessor(String::NewSymbol("rsa"), RsaGetter);

      exports->Set(String::NewSymbol("KeyAlgorithmNames"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    KeyAlgorithmNames(::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      KeyAlgorithmNames *wrapperInstance = new KeyAlgorithmNames(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  




    static Handle<Value> DsaGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Dsa;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> Ecdh256Getter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Ecdh256;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> Ecdh384Getter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Ecdh384;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> Ecdh521Getter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Ecdh521;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> Ecdsa256Getter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Ecdsa256;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> Ecdsa384Getter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Ecdsa384;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> Ecdsa521Getter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Ecdsa521;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> RsaGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames::Rsa;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    

  private:
    ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapKeyAlgorithmNames(::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ UnwrapKeyAlgorithmNames(Handle<Value> value);
    friend bool IsKeyAlgorithmNamesWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> KeyAlgorithmNames::s_constructorTemplate;

  v8::Handle<v8::Value> WrapKeyAlgorithmNames(::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(KeyAlgorithmNames::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::KeyAlgorithmNames^ UnwrapKeyAlgorithmNames(Handle<Value> value)
  {
     return KeyAlgorithmNames::Unwrap<KeyAlgorithmNames>(value.As<Object>())->_instance;
  }

  void InitKeyAlgorithmNames(Handle<Object> exports)
  {
    KeyAlgorithmNames::Init(exports);
  }

  class KeyStorageProviderNames : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("KeyStorageProviderNames"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      constructor->SetAccessor(String::NewSymbol("platformKeyStorageProvider"), PlatformKeyStorageProviderGetter);
      constructor->SetAccessor(String::NewSymbol("smartcardKeyStorageProvider"), SmartcardKeyStorageProviderGetter);
      constructor->SetAccessor(String::NewSymbol("softwareKeyStorageProvider"), SoftwareKeyStorageProviderGetter);

      exports->Set(String::NewSymbol("KeyStorageProviderNames"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    KeyStorageProviderNames(::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      KeyStorageProviderNames *wrapperInstance = new KeyStorageProviderNames(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  




    static Handle<Value> PlatformKeyStorageProviderGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames::PlatformKeyStorageProvider;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SmartcardKeyStorageProviderGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames::SmartcardKeyStorageProvider;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SoftwareKeyStorageProviderGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;

      try 
      {
        Platform::String^ result = ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames::SoftwareKeyStorageProvider;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    

  private:
    ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapKeyStorageProviderNames(::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ UnwrapKeyStorageProviderNames(Handle<Value> value);
    friend bool IsKeyStorageProviderNamesWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> KeyStorageProviderNames::s_constructorTemplate;

  v8::Handle<v8::Value> WrapKeyStorageProviderNames(::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(KeyStorageProviderNames::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::KeyStorageProviderNames^ UnwrapKeyStorageProviderNames(Handle<Value> value)
  {
     return KeyStorageProviderNames::Unwrap<KeyStorageProviderNames>(value.As<Object>())->_instance;
  }

  void InitKeyStorageProviderNames(Handle<Object> exports)
  {
    KeyStorageProviderNames::Init(exports);
  }

  class ChainBuildingParameters : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("ChainBuildingParameters"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("validationTimestamp"), ValidationTimestampGetter, ValidationTimestampSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("revocationCheckEnabled"), RevocationCheckEnabledGetter, RevocationCheckEnabledSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("networkRetrievalEnabled"), NetworkRetrievalEnabledGetter, NetworkRetrievalEnabledSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("currentTimeValidationEnabled"), CurrentTimeValidationEnabledGetter, CurrentTimeValidationEnabledSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("authorityInformationAccessEnabled"), AuthorityInformationAccessEnabledGetter, AuthorityInformationAccessEnabledSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("enhancedKeyUsages"), EnhancedKeyUsagesGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("exclusiveTrustRoots"), ExclusiveTrustRootsGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("ChainBuildingParameters"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    ChainBuildingParameters(::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      ChainBuildingParameters *wrapperInstance = new ChainBuildingParameters(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  



    static Handle<Value> ValidationTimestampGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->ValidationTimestamp;
        return scope.Close(NodeRT::Utils::DateTimeToJS(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void ValidationTimestampSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsDate())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return;
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        
        ::Windows::Foundation::DateTime winRtValue = NodeRT::Utils::DateTimeFromJSDate(value);

        wrapper->_instance->ValidationTimestamp = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> RevocationCheckEnabledGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        bool result = wrapper->_instance->RevocationCheckEnabled;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void RevocationCheckEnabledSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return;
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        
        bool winRtValue = value->BooleanValue();

        wrapper->_instance->RevocationCheckEnabled = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> NetworkRetrievalEnabledGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        bool result = wrapper->_instance->NetworkRetrievalEnabled;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void NetworkRetrievalEnabledSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return;
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        
        bool winRtValue = value->BooleanValue();

        wrapper->_instance->NetworkRetrievalEnabled = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> CurrentTimeValidationEnabledGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        bool result = wrapper->_instance->CurrentTimeValidationEnabled;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void CurrentTimeValidationEnabledSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return;
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        
        bool winRtValue = value->BooleanValue();

        wrapper->_instance->CurrentTimeValidationEnabled = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> AuthorityInformationAccessEnabledGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        bool result = wrapper->_instance->AuthorityInformationAccessEnabled;
        return scope.Close(Boolean::New(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void AuthorityInformationAccessEnabledSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsBoolean())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return;
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        
        bool winRtValue = value->BooleanValue();

        wrapper->_instance->AuthorityInformationAccessEnabled = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> EnhancedKeyUsagesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVector<::Platform::String^>^ result = wrapper->_instance->EnhancedKeyUsages;
        return scope.Close(NodeRT::Collections::VectorWrapper<::Platform::String^>::CreateVectorWrapper(result, 
            [](::Platform::String^ val) -> Handle<Value> {
              return NodeRT::Utils::NewString(val->Data());
            },
            [](Handle<Value> value) -> bool {
              return value->IsString();
            },
            [](Handle<Value> value) -> ::Platform::String^ {
              return ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> ExclusiveTrustRootsGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainBuildingParameters *wrapper = ChainBuildingParameters::Unwrap<ChainBuildingParameters>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVector<::Windows::Security::Cryptography::Certificates::Certificate^>^ result = wrapper->_instance->ExclusiveTrustRoots;
        return scope.Close(NodeRT::Collections::VectorWrapper<::Windows::Security::Cryptography::Certificates::Certificate^>::CreateVectorWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::Certificate^ val) -> Handle<Value> {
              return WrapCertificate(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
              return UnwrapCertificate(value);
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapChainBuildingParameters(::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ UnwrapChainBuildingParameters(Handle<Value> value);
    friend bool IsChainBuildingParametersWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> ChainBuildingParameters::s_constructorTemplate;

  v8::Handle<v8::Value> WrapChainBuildingParameters(::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(ChainBuildingParameters::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::ChainBuildingParameters^ UnwrapChainBuildingParameters(Handle<Value> value)
  {
     return ChainBuildingParameters::Unwrap<ChainBuildingParameters>(value.As<Object>())->_instance;
  }

  void InitChainBuildingParameters(Handle<Object> exports)
  {
    ChainBuildingParameters::Init(exports);
  }

  class ChainValidationParameters : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("ChainValidationParameters"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("serverDnsName"), ServerDnsNameGetter, ServerDnsNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("certificateChainPolicy"), CertificateChainPolicyGetter, CertificateChainPolicySetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("ChainValidationParameters"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    ChainValidationParameters(::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainValidationParameters^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::ChainValidationParameters^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::ChainValidationParameters();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      ChainValidationParameters *wrapperInstance = new ChainValidationParameters(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  



    static Handle<Value> ServerDnsNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainValidationParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainValidationParameters *wrapper = ChainValidationParameters::Unwrap<ChainValidationParameters>(info.This());

      try 
      {
        ::Windows::Networking::HostName^ result = wrapper->_instance->ServerDnsName;
        return scope.Close(NodeRT::Utils::CreateExternalWinRTObject("Windows.Networking", "HostName", result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void ServerDnsNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Networking::HostName^>(value))
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainValidationParameters^>(info.This()))
      {
        return;
      }

      ChainValidationParameters *wrapper = ChainValidationParameters::Unwrap<ChainValidationParameters>(info.This());

      try 
      {
        
        ::Windows::Networking::HostName^ winRtValue = dynamic_cast<::Windows::Networking::HostName^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->ServerDnsName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> CertificateChainPolicyGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainValidationParameters^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      ChainValidationParameters *wrapper = ChainValidationParameters::Unwrap<ChainValidationParameters>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::CertificateChainPolicy result = wrapper->_instance->CertificateChainPolicy;
        return scope.Close(Integer::New(static_cast<int>(result)));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void CertificateChainPolicySetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsInt32())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainValidationParameters^>(info.This()))
      {
        return;
      }

      ChainValidationParameters *wrapper = ChainValidationParameters::Unwrap<ChainValidationParameters>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::CertificateChainPolicy winRtValue = static_cast<::Windows::Security::Cryptography::Certificates::CertificateChainPolicy>(value->Int32Value());

        wrapper->_instance->CertificateChainPolicy = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapChainValidationParameters(::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ UnwrapChainValidationParameters(Handle<Value> value);
    friend bool IsChainValidationParametersWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> ChainValidationParameters::s_constructorTemplate;

  v8::Handle<v8::Value> WrapChainValidationParameters(::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(ChainValidationParameters::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ UnwrapChainValidationParameters(Handle<Value> value)
  {
     return ChainValidationParameters::Unwrap<ChainValidationParameters>(value.As<Object>())->_instance;
  }

  void InitChainValidationParameters(Handle<Object> exports)
  {
    ChainValidationParameters::Init(exports);
  }

  class CertificateChain : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CertificateChain"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
            
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("validate"), FunctionTemplate::New(Validate)->GetFunction());
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("getCertificates"), FunctionTemplate::New(GetCertificates)->GetFunction());
      
                        
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("CertificateChain"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CertificateChain(::Windows::Security::Cryptography::Certificates::CertificateChain^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CertificateChain^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateChain^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CertificateChain^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CertificateChain *wrapperInstance = new CertificateChain(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  
    static Handle<Value> Validate(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateChain^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateChain *wrapper = CertificateChain::Unwrap<CertificateChain>(args.This());

      if (args.Length() == 0)
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::ChainValidationResult result;
          result = wrapper->_instance->Validate();
          return scope.Close(Integer::New(static_cast<int>(result)));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::ChainValidationParameters^>(args[0]))
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::ChainValidationParameters^ arg0 = UnwrapChainValidationParameters(args[0]);
          
          ::Windows::Security::Cryptography::Certificates::ChainValidationResult result;
          result = wrapper->_instance->Validate(arg0);
          return scope.Close(Integer::New(static_cast<int>(result)));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }
    static Handle<Value> GetCertificates(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CertificateChain^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      CertificateChain *wrapper = CertificateChain::Unwrap<CertificateChain>(args.This());

      if (args.Length() == 1
        && args[0]->IsBoolean())
      {
        try
        {
          bool arg0 = args[0]->BooleanValue();
          
          ::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::Certificate^>^ result;
          result = wrapper->_instance->GetCertificates(arg0);
          return scope.Close(NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::Certificate^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::Certificate^ val) -> Handle<Value> {
              return WrapCertificate(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
              return UnwrapCertificate(value);
            }
          ));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }





  private:
    ::Windows::Security::Cryptography::Certificates::CertificateChain^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCertificateChain(::Windows::Security::Cryptography::Certificates::CertificateChain^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CertificateChain^ UnwrapCertificateChain(Handle<Value> value);
    friend bool IsCertificateChainWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CertificateChain::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCertificateChain(::Windows::Security::Cryptography::Certificates::CertificateChain^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CertificateChain::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CertificateChain^ UnwrapCertificateChain(Handle<Value> value)
  {
     return CertificateChain::Unwrap<CertificateChain>(value.As<Object>())->_instance;
  }

  void InitCertificateChain(Handle<Object> exports)
  {
    CertificateChain::Init(exports);
  }

  class CmsTimestampInfo : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CmsTimestampInfo"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("certificates"), CertificatesGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("signingCertificate"), SigningCertificateGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("timestamp"), TimestampGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("CmsTimestampInfo"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CmsTimestampInfo(::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CmsTimestampInfo *wrapperInstance = new CmsTimestampInfo(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  



    static Handle<Value> CertificatesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsTimestampInfo *wrapper = CmsTimestampInfo::Unwrap<CmsTimestampInfo>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::Certificate^>^ result = wrapper->_instance->Certificates;
        return scope.Close(NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::Certificate^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::Certificate^ val) -> Handle<Value> {
              return WrapCertificate(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
              return UnwrapCertificate(value);
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SigningCertificateGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsTimestampInfo *wrapper = CmsTimestampInfo::Unwrap<CmsTimestampInfo>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::Certificate^ result = wrapper->_instance->SigningCertificate;
        return scope.Close(WrapCertificate(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> TimestampGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsTimestampInfo *wrapper = CmsTimestampInfo::Unwrap<CmsTimestampInfo>(info.This());

      try 
      {
        ::Windows::Foundation::DateTime result = wrapper->_instance->Timestamp;
        return scope.Close(NodeRT::Utils::DateTimeToJS(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCmsTimestampInfo(::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ UnwrapCmsTimestampInfo(Handle<Value> value);
    friend bool IsCmsTimestampInfoWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CmsTimestampInfo::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCmsTimestampInfo(::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CmsTimestampInfo::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ UnwrapCmsTimestampInfo(Handle<Value> value)
  {
     return CmsTimestampInfo::Unwrap<CmsTimestampInfo>(value.As<Object>())->_instance;
  }

  void InitCmsTimestampInfo(Handle<Object> exports)
  {
    CmsTimestampInfo::Init(exports);
  }

  class CmsSignerInfo : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CmsSignerInfo"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
                              
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("hashAlgorithmName"), HashAlgorithmNameGetter, HashAlgorithmNameSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("certificate"), CertificateGetter, CertificateSetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("timestampInfo"), TimestampInfoGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();


      exports->Set(String::NewSymbol("CmsSignerInfo"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CmsSignerInfo(::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CmsSignerInfo^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 0)
      {
        try
        {
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::CmsSignerInfo();
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CmsSignerInfo *wrapperInstance = new CmsSignerInfo(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  



    static Handle<Value> HashAlgorithmNameGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsSignerInfo *wrapper = CmsSignerInfo::Unwrap<CmsSignerInfo>(info.This());

      try 
      {
        Platform::String^ result = wrapper->_instance->HashAlgorithmName;
        return scope.Close(NodeRT::Utils::NewString(result->Data()));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void HashAlgorithmNameSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!value->IsString())
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(info.This()))
      {
        return;
      }

      CmsSignerInfo *wrapper = CmsSignerInfo::Unwrap<CmsSignerInfo>(info.This());

      try 
      {
        
        Platform::String^ winRtValue = ref new Platform::String(NodeRT::Utils::StringToWchar(v8::String::Value(value)));

        wrapper->_instance->HashAlgorithmName = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> CertificateGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsSignerInfo *wrapper = CmsSignerInfo::Unwrap<CmsSignerInfo>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::Certificate^ result = wrapper->_instance->Certificate;
        return scope.Close(WrapCertificate(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static void CertificateSetter(Local<String> property, Local<Value> value, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value))
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Value to set is of unexpected type")));
        return;
      }

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(info.This()))
      {
        return;
      }

      CmsSignerInfo *wrapper = CmsSignerInfo::Unwrap<CmsSignerInfo>(info.This());

      try 
      {
        
        ::Windows::Security::Cryptography::Certificates::Certificate^ winRtValue = dynamic_cast<::Windows::Security::Cryptography::Certificates::Certificate^>(NodeRT::Utils::GetObjectInstance(value));

        wrapper->_instance->Certificate = winRtValue;
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
      }
    }
    
    static Handle<Value> TimestampInfoGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsSignerInfo *wrapper = CmsSignerInfo::Unwrap<CmsSignerInfo>(info.This());

      try 
      {
        ::Windows::Security::Cryptography::Certificates::CmsTimestampInfo^ result = wrapper->_instance->TimestampInfo;
        return scope.Close(WrapCmsTimestampInfo(result));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCmsSignerInfo(::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ UnwrapCmsSignerInfo(Handle<Value> value);
    friend bool IsCmsSignerInfoWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CmsSignerInfo::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCmsSignerInfo(::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CmsSignerInfo::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ UnwrapCmsSignerInfo(Handle<Value> value)
  {
     return CmsSignerInfo::Unwrap<CmsSignerInfo>(value.As<Object>())->_instance;
  }

  void InitCmsSignerInfo(Handle<Object> exports)
  {
    CmsSignerInfo::Init(exports);
  }

  class CmsAttachedSignature : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CmsAttachedSignature"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
            
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("verifySignature"), FunctionTemplate::New(VerifySignature)->GetFunction());
      
                        
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("certificates"), CertificatesGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("content"), ContentGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("signers"), SignersGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      func = FunctionTemplate::New(GenerateSignatureAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("generateSignatureAsync"), func);

      exports->Set(String::NewSymbol("CmsAttachedSignature"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CmsAttachedSignature(::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Storage::Streams::IBuffer^>(args[0]))
      {
        try
        {
          ::Windows::Storage::Streams::IBuffer^ arg0 = dynamic_cast<::Windows::Storage::Streams::IBuffer^>(NodeRT::Utils::GetObjectInstance(args[0]));
          
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CmsAttachedSignature *wrapperInstance = new CmsAttachedSignature(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


  
    static Handle<Value> VerifySignature(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      CmsAttachedSignature *wrapper = CmsAttachedSignature::Unwrap<CmsAttachedSignature>(args.This());

      if (args.Length() == 0)
      {
        try
        {
          ::Windows::Security::Cryptography::Certificates::SignatureValidationResult result;
          result = wrapper->_instance->VerifySignature();
          return scope.Close(Integer::New(static_cast<int>(result)));
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }

      return scope.Close(Undefined());
    }

    static Handle<Value> GenerateSignatureAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::Storage::Streams::IBuffer^>^ op;
      

      if (args.Length() == 4
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Storage::Streams::IBuffer^>(args[0])
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^>(args[1]) || args[1]->IsArray())
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(args[2]) || args[2]->IsArray()))
      {
        try
        {
          ::Windows::Storage::Streams::IBuffer^ arg0 = dynamic_cast<::Windows::Storage::Streams::IBuffer^>(NodeRT::Utils::GetObjectInstance(args[0]));
          ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^ arg1 = 
            [] (v8::Handle<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(value);
                 },
                 [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ {
                   return UnwrapCmsSignerInfo(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (args[1]);
          ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^ arg2 = 
            [] (v8::Handle<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::Security::Cryptography::Certificates::Certificate^>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
                 },
                 [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
                   return UnwrapCertificate(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (args[2]);
          
          op = ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature::GenerateSignatureAsync(arg0,arg1,arg2);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Storage::Streams::IBuffer^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.Storage.Streams", "IBuffer", result);
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }


    static Handle<Value> CertificatesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsAttachedSignature *wrapper = CmsAttachedSignature::Unwrap<CmsAttachedSignature>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::Certificate^>^ result = wrapper->_instance->Certificates;
        return scope.Close(NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::Certificate^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::Certificate^ val) -> Handle<Value> {
              return WrapCertificate(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
              return UnwrapCertificate(value);
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> ContentGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsAttachedSignature *wrapper = CmsAttachedSignature::Unwrap<CmsAttachedSignature>(info.This());

      try 
      {
        ::Platform::Array<unsigned char>^ result = wrapper->_instance->Content;
        return scope.Close(NodeRT::Collections::ArrayWrapper<unsigned char>::CreateArrayWrapper(result, 
            [](unsigned char val) -> Handle<Value> {
              return Integer::New(val);
            },
            [](Handle<Value> value) -> bool {
              return value->IsInt32();
            },
            [](Handle<Value> value) -> unsigned char {
              return static_cast<unsigned char>(value->Int32Value());
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SignersGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsAttachedSignature *wrapper = CmsAttachedSignature::Unwrap<CmsAttachedSignature>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^ result = wrapper->_instance->Signers;
        return scope.Close(NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ val) -> Handle<Value> {
              return WrapCmsSignerInfo(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ {
              return UnwrapCmsSignerInfo(value);
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCmsAttachedSignature(::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ UnwrapCmsAttachedSignature(Handle<Value> value);
    friend bool IsCmsAttachedSignatureWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CmsAttachedSignature::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCmsAttachedSignature(::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CmsAttachedSignature::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CmsAttachedSignature^ UnwrapCmsAttachedSignature(Handle<Value> value)
  {
     return CmsAttachedSignature::Unwrap<CmsAttachedSignature>(value.As<Object>())->_instance;
  }

  void InitCmsAttachedSignature(Handle<Object> exports)
  {
    CmsAttachedSignature::Init(exports);
  }

  class CmsDetachedSignature : public WrapperBase
  {
  public:    
    static v8::Handle<v8::Value> Init(const Handle<Object> exports)
    {
      HandleScope scope;
      
      s_constructorTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(New));
      s_constructorTemplate->SetClassName(String::NewSymbol("CmsDetachedSignature"));
      s_constructorTemplate->InstanceTemplate()->SetInternalFieldCount(1);
      
      Handle<Value> asyncSymbol = String::NewSymbol("__winRtAsync__");
      Handle<Function> func;
                  
      func = FunctionTemplate::New(VerifySignatureAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      s_constructorTemplate->PrototypeTemplate()->Set(String::NewSymbol("verifySignatureAsync"), func);
      
                  
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("certificates"), CertificatesGetter);
      s_constructorTemplate->PrototypeTemplate()->SetAccessor(String::NewSymbol("signers"), SignersGetter);
      
      Local<Function> constructor = s_constructorTemplate->GetFunction();

      func = FunctionTemplate::New(GenerateSignatureAsync)->GetFunction();
      func->Set(asyncSymbol, True(), PropertyAttribute::DontEnum);
      constructor->Set(String::NewSymbol("generateSignatureAsync"), func);

      exports->Set(String::NewSymbol("CmsDetachedSignature"), constructor);
      return scope.Close(Undefined());
    }


    virtual ::Platform::Object^ GetObjectInstance() const override
    {
      return _instance;
    }

  private:
    
    CmsDetachedSignature(::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ instance)
    {
      _instance = instance;
    }
    
    
    static v8::Handle<v8::Value> New(const v8::Arguments& args)
    {
      HandleScope scope;

      // in case the constructor was called without the new operator
      if (!s_constructorTemplate->HasInstance(args.This()))
      {
        if (args.Length() > 0)
        {
          std::unique_ptr<Handle<Value> []> constructorArgs(new Handle<Value>[args.Length()]);

          Handle<Value> *argsPtr = constructorArgs.get();
          for (int i = 0; i < args.Length(); i++)
          {
            argsPtr[i] = args[i];
          }

          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), constructorArgs.get());
        }
        else
        {
          return s_constructorTemplate->GetFunction()->CallAsConstructor(args.Length(), nullptr);
        }
      }
      
      ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ winRtInstance;


      if (args.Length() == 1 && OpaqueWrapper::IsOpaqueWrapper(args[0]) &&
        NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^>(args[0]))
      {
        try 
        {
          winRtInstance = (::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^) NodeRT::Utils::GetObjectInstance(args[0]);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else if (args.Length() == 1
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Storage::Streams::IBuffer^>(args[0]))
      {
        try
        {
          ::Windows::Storage::Streams::IBuffer^ arg0 = dynamic_cast<::Windows::Storage::Streams::IBuffer^>(NodeRT::Utils::GetObjectInstance(args[0]));
          
          winRtInstance = ref new ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Invalid arguments, no suitable constructor found")));
        return scope.Close(Undefined());
      }

      args.This()->SetHiddenValue(String::NewSymbol("__winRtInstance__"), True());

      CmsDetachedSignature *wrapperInstance = new CmsDetachedSignature(winRtInstance);
      wrapperInstance->Wrap(args.This());

      return args.This();
    }


    static Handle<Value> VerifySignatureAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^>(args.This()))
      {
        return scope.Close(Undefined());
      }

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      CmsDetachedSignature *wrapper = CmsDetachedSignature::Unwrap<CmsDetachedSignature>(args.This());

      ::Windows::Foundation::IAsyncOperation<::Windows::Security::Cryptography::Certificates::SignatureValidationResult>^ op;
    

      if (args.Length() == 2
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Storage::Streams::IInputStream^>(args[0]))
      {
        try
        {
          ::Windows::Storage::Streams::IInputStream^ arg0 = dynamic_cast<::Windows::Storage::Streams::IInputStream^>(NodeRT::Utils::GetObjectInstance(args[0]));
          
          op = wrapper->_instance->VerifySignatureAsync(arg0);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Security::Cryptography::Certificates::SignatureValidationResult> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {


            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = Integer::New(static_cast<int>(result));
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
             
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }
  

    static Handle<Value> GenerateSignatureAsync(const v8::Arguments& args)
    {
      HandleScope scope;

      if (args.Length() == 0 || !args[args.Length() -1]->IsFunction())
      {
          ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: No callback was given")));
          return scope.Close(Undefined());
      }

      ::Windows::Foundation::IAsyncOperation<::Windows::Storage::Streams::IBuffer^>^ op;
      

      if (args.Length() == 4
        && NodeRT::Utils::IsWinRtWrapperOf<::Windows::Storage::Streams::IInputStream^>(args[0])
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^>(args[1]) || args[1]->IsArray())
        && (NodeRT::Utils::IsWinRtWrapperOf<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(args[2]) || args[2]->IsArray()))
      {
        try
        {
          ::Windows::Storage::Streams::IInputStream^ arg0 = dynamic_cast<::Windows::Storage::Streams::IInputStream^>(NodeRT::Utils::GetObjectInstance(args[0]));
          ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^ arg1 = 
            [] (v8::Handle<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(value);
                 },
                 [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ {
                   return UnwrapCmsSignerInfo(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (args[1]);
          ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^ arg2 = 
            [] (v8::Handle<v8::Value> value) -> ::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^
            {
              if (value->IsArray())
              {
                return NodeRT::Collections::JsArrayToWinrtVector<::Windows::Security::Cryptography::Certificates::Certificate^>(value.As<Array>(), 
                 [](Handle<Value> value) -> bool {
                   return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
                 },
                 [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
                   return UnwrapCertificate(value);
                 }
                );
              }
              else
              {
                return dynamic_cast<::Windows::Foundation::Collections::IIterable<::Windows::Security::Cryptography::Certificates::Certificate^>^>(NodeRT::Utils::GetObjectInstance(value));
              }
            } (args[2]);
          
          op = ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature::GenerateSignatureAsync(arg0,arg1,arg2);
        }
        catch (Platform::Exception ^exception)
        {
          NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
          return scope.Close(Undefined());
        }
      }
      else 
      {
        ThrowException(Exception::Error(NodeRT::Utils::NewString(L"Bad arguments: no suitable overload found")));
        return scope.Close(Undefined());
      }
    
      auto opTask = create_task(op);
      uv_async_t* asyncToken = NodeUtils::Async::GetAsyncToken(args[args.Length() -1].As<Function>());

      opTask.then( [asyncToken] (task<::Windows::Storage::Streams::IBuffer^> t) 
      {	
        try
        {
          auto result = t.get();
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [result](NodeUtils::InvokeCallbackDelegate invokeCallback) {

            
            TryCatch tryCatch;
            Handle<Value> error; 
            Handle<Value> arg1 = NodeRT::Utils::CreateExternalWinRTObject("Windows.Storage.Streams", "IBuffer", result);
            if (tryCatch.HasCaught())
            {
              error = tryCatch.Exception()->ToObject();
            }
            else 
            {
              error = Undefined();
            }
            if (arg1.IsEmpty()) arg1 = Undefined();
            Handle<Value> args[] = {error, arg1};

            invokeCallback(_countof(args), args);
          });
        }
        catch (Platform::Exception^ exception)
        {
          NodeUtils::Async::RunCallbackOnMain(asyncToken, [exception](NodeUtils::InvokeCallbackDelegate invokeCallback) {
          
            Handle<Value> error = NodeRT::Utils::WinRtExceptionToJsError(exception);
        
            Handle<Value> args[] = {error};
            invokeCallback(_countof(args), args);
          });
        }  		
      });

      return scope.Close(Undefined());
    }


    static Handle<Value> CertificatesGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsDetachedSignature *wrapper = CmsDetachedSignature::Unwrap<CmsDetachedSignature>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::Certificate^>^ result = wrapper->_instance->Certificates;
        return scope.Close(NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::Certificate^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::Certificate^ val) -> Handle<Value> {
              return WrapCertificate(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::Certificate^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::Certificate^ {
              return UnwrapCertificate(value);
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    
    static Handle<Value> SignersGetter(Local<String> property, const AccessorInfo &info)
    {
      HandleScope scope;
      
      if (!NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^>(info.This()))
      {
        return scope.Close(Undefined());
      }

      CmsDetachedSignature *wrapper = CmsDetachedSignature::Unwrap<CmsDetachedSignature>(info.This());

      try 
      {
        ::Windows::Foundation::Collections::IVectorView<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>^ result = wrapper->_instance->Signers;
        return scope.Close(NodeRT::Collections::VectorViewWrapper<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>::CreateVectorViewWrapper(result, 
            [](::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ val) -> Handle<Value> {
              return WrapCmsSignerInfo(val);
            },
            [](Handle<Value> value) -> bool {
              return NodeRT::Utils::IsWinRtWrapperOf<::Windows::Security::Cryptography::Certificates::CmsSignerInfo^>(value);
            },
            [](Handle<Value> value) -> ::Windows::Security::Cryptography::Certificates::CmsSignerInfo^ {
              return UnwrapCmsSignerInfo(value);
            }
          ));
      }
      catch (Platform::Exception ^exception)
      {
        NodeRT::Utils::ThrowWinRtExceptionInJs(exception);
        return scope.Close(Undefined());
      }
    }
    


  private:
    ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ _instance;
    static Persistent<FunctionTemplate> s_constructorTemplate;

    friend v8::Handle<v8::Value> WrapCmsDetachedSignature(::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ wintRtInstance);
    friend ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ UnwrapCmsDetachedSignature(Handle<Value> value);
    friend bool IsCmsDetachedSignatureWrapper(Handle<Value> value);
  };
  Persistent<FunctionTemplate> CmsDetachedSignature::s_constructorTemplate;

  v8::Handle<v8::Value> WrapCmsDetachedSignature(::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ winRtInstance)
  {
    HandleScope scope;

    if (winRtInstance == nullptr)
    {
      return scope.Close(Undefined());
    }

    Handle<Object> opaqueWrapper = CreateOpaqueWrapper(winRtInstance);
    Handle<Value> args[] = {opaqueWrapper};
    return scope.Close(CmsDetachedSignature::s_constructorTemplate->GetFunction()->NewInstance(_countof(args), args));
  }

  ::Windows::Security::Cryptography::Certificates::CmsDetachedSignature^ UnwrapCmsDetachedSignature(Handle<Value> value)
  {
     return CmsDetachedSignature::Unwrap<CmsDetachedSignature>(value.As<Object>())->_instance;
  }

  void InitCmsDetachedSignature(Handle<Object> exports)
  {
    CmsDetachedSignature::Init(exports);
  }

} } } } } 

void init(Handle<Object> exports)
{
  if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)))
  {
    ThrowException(v8::Exception::Error(NodeRT::Utils::NewString(L"error in CoInitializeEx()")));
    return;
  }
  
  NodeRT::Windows::Security::Cryptography::Certificates::InitEnrollKeyUsagesEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitKeyProtectionLevelEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitExportOptionEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitKeySizeEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitInstallOptionsEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateChainPolicyEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitChainValidationResultEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitSignatureValidationResultEnum(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificate(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateRequestProperties(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitUserCertificateEnrollmentManager(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateEnrollmentManager(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitKeyAttestationHelper(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateQuery(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateStore(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateStores(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitKeyAlgorithmNames(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitKeyStorageProviderNames(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitChainBuildingParameters(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitChainValidationParameters(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCertificateChain(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCmsTimestampInfo(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCmsSignerInfo(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCmsAttachedSignature(exports);
  NodeRT::Windows::Security::Cryptography::Certificates::InitCmsDetachedSignature(exports);

  NodeRT::Utils::RegisterNameSpace("Windows.Security.Cryptography.Certificates", exports);
}


NODE_MODULE(binding, init)