diff --git a/EAPMethods/build/EAPTTLS.vcxproj b/EAPMethods/build/EAPTTLS.vcxproj
index 2b4778e..cde66e1 100644
--- a/EAPMethods/build/EAPTTLS.vcxproj
+++ b/EAPMethods/build/EAPTTLS.vcxproj
@@ -79,9 +79,13 @@
+
+
+
+
Create
diff --git a/EAPMethods/build/EAPTTLS.vcxproj.filters b/EAPMethods/build/EAPTTLS.vcxproj.filters
index 1c80dcd..be1489a 100644
--- a/EAPMethods/build/EAPTTLS.vcxproj.filters
+++ b/EAPMethods/build/EAPTTLS.vcxproj.filters
@@ -18,6 +18,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
@@ -26,6 +32,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
diff --git a/EAPMethods/include/EAPMethods.h b/EAPMethods/include/EAPMethods.h
new file mode 100644
index 0000000..bf821d2
--- /dev/null
+++ b/EAPMethods/include/EAPMethods.h
@@ -0,0 +1,454 @@
+/*
+ Copyright 2015-2016 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of GEANTLink.
+
+ GEANTLink is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ GEANTLink is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GEANTLink. If not, see .
+*/
+
+#include
+#include
+
+#include
+extern "C" {
+#include
+}
+
+#include
+
+#include
+
+
+namespace eap
+{
+ class session_base;
+ template class peer;
+};
+
+#pragma once
+
+
+#define ETW_ERROR(kw, f, ...) m_ep.write(TRACE_LEVEL_ERROR , kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__)
+#define ETW_WARNING(kw, f, ...) m_ep.write(TRACE_LEVEL_WARNING , kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__)
+#define ETW_INFO(kw, f, ...) m_ep.write(TRACE_LEVEL_INFORMATION, kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__)
+#define ETW_VERBOSE(kw, f, ...) m_ep.write(TRACE_LEVEL_VERBOSE , kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__)
+#define ETW_FN_VOID winstd::event_fn_auto < &EAPMETHOD_TRACE_EVT_FN_CALL, &EAPMETHOD_TRACE_EVT_FN_RETURN > _event_auto(m_ep, __FUNCTION__)
+#define ETW_FN_DWORD(res) winstd::event_fn_auto_ret _event_auto(m_ep, __FUNCTION__, res)
+#define ETW_FN_HRESULT(res) winstd::event_fn_auto_ret _event_auto(m_ep, __FUNCTION__, res)
+
+
+namespace eap
+{
+ ///
+ /// EAP session
+ ///
+ class session_base
+ {
+ public:
+ ///
+ /// Constructor
+ ///
+ session_base();
+
+ ///
+ /// Starts an EAP authentication session on the peer EAPHost using the EAP method.
+ ///
+ /// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx)
+ ///
+ virtual DWORD begin(_In_ DWORD dwFlags, _In_ const EapAttributes *pAttributeArray, _In_ HANDLE hTokenImpersonateUser, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) BYTE *pUserData, _In_ DWORD dwMaxSendPacketSize, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Ends an EAP authentication session for the EAP method.
+ ///
+ /// \sa [EapPeerEndSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363604.aspx)
+ ///
+ virtual DWORD end(_Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Processes a packet received by EAPHost from a supplicant.
+ ///
+ /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
+ ///
+ virtual DWORD process_request_packet(_In_ DWORD dwSizeofReceivePacket, _In_bytecount_(dwSizeofReceivePacket) EapPacket *pReceivePacket, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Obtains a response packet from the EAP method.
+ ///
+ /// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx)
+ ///
+ virtual DWORD get_response_packet(_Inout_ DWORD *pcbSendPacket, _Out_cap_(*pcbSendPacket) EapPacket *pSendPacket, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Obtains the result of an authentication session from the EAP method.
+ ///
+ /// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx)
+ ///
+ virtual DWORD get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Obtains the user interface context from the EAP method.
+ ///
+ /// \note This function is always followed by the `EapPeerInvokeInteractiveUI()` function, which is followed by the `EapPeerSetUIContext()` function.
+ ///
+ /// \sa [EapPeerGetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363612.aspx)
+ ///
+ virtual DWORD get_ui_context(_Out_ DWORD *dwSizeOfUIContextData, _Out_cap_(*dwSizeOfUIContextData) BYTE **pUIContextData, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Provides a user interface context to the EAP method.
+ ///
+ /// \note This function is called after the UI has been raised through the `EapPeerGetUIContext()` function.
+ ///
+ /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx)
+ ///
+ virtual DWORD set_ui_context(_In_ DWORD dwSizeOfUIContextData, _In_count_(dwSizeOfUIContextData) const BYTE *pUIContextData, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Obtains an array of EAP response attributes from the EAP method.
+ ///
+ /// \sa [EapPeerGetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363609.aspx)
+ ///
+ virtual DWORD get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError);
+
+ ///
+ /// Provides an updated array of EAP response attributes to the EAP method.
+ ///
+ /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx)
+ ///
+ virtual DWORD set_response_attributes(_In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError);
+ };
+
+
+ ///
+ /// EAP peer base class
+ ///
+ template
+ class peer
+ {
+ public:
+ inline DWORD create()
+ {
+ m_ep.create(&EAPMETHOD_TRACE_EVENT_PROVIDER);
+ m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, winstd::event_data((BYTE)EAPMETHOD_TYPE), winstd::event_data::blank);
+
+ if (!m_heap.create(0, 0, 0))
+ return ERROR_OUTOFMEMORY;
+
+ return ERROR_SUCCESS;
+ }
+
+
+ virtual ~peer()
+ {
+ m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, winstd::event_data((BYTE)EAPMETHOD_TYPE), winstd::event_data::blank);
+ }
+
+
+ ///
+ /// Obtains a set of function pointers for an implementation of the EAP peer method currently loaded on the EAPHost service
+ ///
+ /// \sa [EapPeerGetInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363608.aspx)
+ ///
+ inline void get_info(_Out_ EAP_PEER_METHOD_ROUTINES *pEapPeerMethodRoutines) const
+ {
+ ETW_FN_VOID;
+
+ assert(pEapPeerMethodRoutines);
+
+ pEapPeerMethodRoutines->dwVersion = PRODUCT_VERSION;
+ pEapPeerMethodRoutines->pEapType = NULL;
+
+ pEapPeerMethodRoutines->EapPeerInitialize = initialize;
+ pEapPeerMethodRoutines->EapPeerShutdown = shutdown;
+ pEapPeerMethodRoutines->EapPeerBeginSession = begin_session;
+ pEapPeerMethodRoutines->EapPeerEndSession = end_session;
+ pEapPeerMethodRoutines->EapPeerSetCredentials = NULL; // Always NULL unless we want to use generic credential UI
+ pEapPeerMethodRoutines->EapPeerGetIdentity = get_identity;
+ pEapPeerMethodRoutines->EapPeerProcessRequestPacket = process_request_packet;
+ pEapPeerMethodRoutines->EapPeerGetResponsePacket = get_response_packet;
+ pEapPeerMethodRoutines->EapPeerGetResult = get_result;
+ pEapPeerMethodRoutines->EapPeerGetUIContext = get_ui_context;
+ pEapPeerMethodRoutines->EapPeerSetUIContext = set_ui_context;
+ pEapPeerMethodRoutines->EapPeerGetResponseAttributes = get_response_attributes;
+ pEapPeerMethodRoutines->EapPeerSetResponseAttributes = set_response_attributes;
+ }
+
+
+ ///
+ /// Free BLOB allocated with this peer
+ ///
+ inline void free_memory(_In_ void *ptr)
+ {
+ ETW_FN_VOID;
+
+ if (ptr) {
+ // Since we do security here and some of the BLOBs contain credentials, sanitize every memory block before freeing.
+ SecureZeroMemory(ptr, HeapSize(m_heap, 0, ptr));
+ HeapFree(m_heap, 0, ptr);
+ }
+ }
+
+
+ ///
+ /// Allocate a EAP_ERROR and fill it according to dwErrorCode
+ ///
+ EAP_ERROR *make_error(_In_ DWORD dwErrorCode, _In_ DWORD dwReasonCode, _In_ LPCGUID pRootCauseGuid, _In_ LPCGUID pRepairGuid, _In_ LPCGUID pHelpLinkGuid, _In_z_ LPCWSTR pszRootCauseString, _In_z_ LPCWSTR pszRepairString) const
+ {
+ // Calculate memory size requirement.
+ SIZE_T
+ nRootCauseSize = pszRootCauseString != NULL && pszRootCauseString[0] ? (wcslen(pszRootCauseString) + 1)*sizeof(WCHAR) : 0,
+ nRepairStringSize = pszRepairString != NULL && pszRepairString [0] ? (wcslen(pszRepairString ) + 1)*sizeof(WCHAR) : 0,
+ nEapErrorSize = sizeof(EAP_ERROR) + nRootCauseSize + nRepairStringSize;
+
+ EAP_ERROR *pError = (EAP_ERROR*)HeapAlloc(m_heap, 0, nEapErrorSize);
+ if (!pError)
+ return NULL;
+ BYTE *p = (BYTE*)(pError + 1);
+
+ // Fill the error descriptor.
+ pError->dwWinError = dwErrorCode;
+ pError->type.eapType.type = EAPMETHOD_TYPE;
+ pError->type.eapType.dwVendorId = 0;
+ pError->type.eapType.dwVendorType = 0;
+ pError->type.dwAuthorId = 67532;
+ pError->dwReasonCode = dwReasonCode;
+ pError->rootCauseGuid = pRootCauseGuid != NULL ? *pRootCauseGuid : GUID_NULL;
+ pError->repairGuid = pRepairGuid != NULL ? *pRepairGuid : GUID_NULL;
+ pError->helpLinkGuid = pHelpLinkGuid != NULL ? *pHelpLinkGuid : GUID_NULL;
+ if (nRootCauseSize) {
+ pError->pRootCauseString = (LPWSTR)p;
+ memcpy(pError->pRootCauseString, pszRootCauseString, nRootCauseSize);
+ p += nRootCauseSize;
+ } else
+ pError->pRootCauseString = NULL;
+ if (nRepairStringSize) {
+ pError->pRepairString = (LPWSTR)p;
+ memcpy(pError->pRepairString, pszRepairString, nRepairStringSize);
+ p += nRepairStringSize;
+ } else
+ pError->pRepairString = NULL;
+
+ // Write trace event.
+ std::vector evt_desc;
+ evt_desc.reserve(8);
+ evt_desc.push_back(winstd::event_data(pError->dwWinError));
+ evt_desc.push_back(winstd::event_data(pError->type.eapType.type));
+ evt_desc.push_back(winstd::event_data(pError->dwReasonCode));
+ evt_desc.push_back(winstd::event_data(&(pError->rootCauseGuid), sizeof(GUID)));
+ evt_desc.push_back(winstd::event_data(&(pError->repairGuid), sizeof(GUID)));
+ evt_desc.push_back(winstd::event_data(&(pError->helpLinkGuid), sizeof(GUID)));
+ evt_desc.push_back(winstd::event_data(pError->pRootCauseString));
+ evt_desc.push_back(winstd::event_data(pError->pRepairString));
+ m_ep.write(&EAPMETHOD_TRACE_EAP_ERROR, (ULONG)evt_desc.size(), evt_desc.data());
+
+ return pError;
+ }
+
+
+ ///
+ /// Free EAP_ERROR allocated with `make_error()` method
+ ///
+ void free_error_memory(_In_ EAP_ERROR *err)
+ {
+ ETW_FN_VOID;
+
+ if (err) {
+ // pRootCauseString and pRepairString always trail the ppEapError to reduce number of (de)allocations.
+ HeapFree(m_heap, 0, err);
+ }
+ }
+
+ protected:
+ ///
+ /// Initializes an EAP peer method for EAPHost.
+ ///
+ /// \sa [EapPeerGetInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363613.aspx)
+ ///
+ static DWORD APIENTRY initialize(_Out_ EAP_ERROR **ppEapError)
+ {
+ UNREFERENCED_PARAMETER(ppEapError);
+ return ERROR_SUCCESS;
+ }
+
+
+ ///
+ /// Shuts down the EAP method and prepares to unload its corresponding DLL.
+ ///
+ /// \sa [EapPeerShutdown function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363627.aspx)
+ ///
+ static DWORD APIENTRY shutdown(_Out_ EAP_ERROR **ppEapError)
+ {
+ UNREFERENCED_PARAMETER(ppEapError);
+ return ERROR_SUCCESS;
+ }
+
+
+ ///
+ /// Returns the user data and user identity after being called by EAPHost.
+ ///
+ /// \sa [EapPeerGetIdentity function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363607.aspx)
+ ///
+ static DWORD APIENTRY get_identity(_In_ DWORD dwFlags, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) const BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) const BYTE *pUserData, _In_ HANDLE hTokenImpersonateUser, _Out_ BOOL *pfInvokeUI, _Inout_ DWORD *pdwSizeOfUserDataOut, _Out_cap_(*pdwSizeOfUserDataOut) BYTE **ppUserDataOut, _Out_ WCHAR **ppwszIdentity, _Out_ EAP_ERROR **ppEapError)
+ {
+ UNREFERENCED_PARAMETER(dwFlags);
+ UNREFERENCED_PARAMETER(dwSizeofConnectionData);
+ UNREFERENCED_PARAMETER(pConnectionData);
+ UNREFERENCED_PARAMETER(dwSizeofUserData);
+ UNREFERENCED_PARAMETER(pUserData);
+ UNREFERENCED_PARAMETER(hTokenImpersonateUser);
+ UNREFERENCED_PARAMETER(pfInvokeUI);
+ UNREFERENCED_PARAMETER(pdwSizeOfUserDataOut);
+ UNREFERENCED_PARAMETER(ppUserDataOut);
+ UNREFERENCED_PARAMETER(ppwszIdentity);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_NOT_SUPPORTED;
+ }
+
+
+ ///
+ /// Starts an EAP authentication session on the peer EAPHost using the EAP method.
+ ///
+ /// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx)
+ ///
+ static DWORD APIENTRY begin_session(_In_ DWORD dwFlags, _In_ const EapAttributes *pAttributeArray, _In_ HANDLE hTokenImpersonateUser, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) BYTE *pUserData, _In_ DWORD dwMaxSendPacketSize, _Out_ EAP_SESSION_HANDLE *phSession, _Out_ EAP_ERROR **ppEapError)
+ {
+ // Allocate new session.
+ Ts *session = new Ts();
+ if (!session)
+ return ERROR_OUTOFMEMORY;
+
+ // Begin the session.
+ DWORD dwResult = session->begin(dwFlags, pAttributeArray, hTokenImpersonateUser, dwSizeofConnectionData, pConnectionData, dwSizeofUserData, pUserData, dwMaxSendPacketSize, ppEapError);
+ if (dwResult == ERROR_SUCCESS) {
+ assert(phSession);
+ *phSession = session;
+ return ERROR_SUCCESS;
+ }
+
+ // Cleanup.
+ delete session;
+ return dwResult;
+ }
+
+
+ ///
+ /// Ends an EAP authentication session for the EAP method.
+ ///
+ /// \sa [EapPeerEndSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363604.aspx)
+ ///
+ static DWORD APIENTRY end_session(_In_ EAP_SESSION_HANDLE hSession, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+
+ DWORD dwResult = static_cast(hSession)->end(ppEapError);
+ delete static_cast(hSession);
+
+ return dwResult;
+ }
+
+
+ ///
+ /// Processes a packet received by EAPHost from a supplicant.
+ ///
+ /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx)
+ ///
+ static DWORD APIENTRY process_request_packet(_In_ EAP_SESSION_HANDLE hSession, _In_ DWORD dwSizeofReceivePacket, _In_bytecount_(dwSizeofReceivePacket) EapPacket *pReceivePacket, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->process_request_packet(dwSizeofReceivePacket, pReceivePacket, pEapOutput, ppEapError);
+ }
+
+
+ ///
+ /// Obtains a response packet from the EAP method.
+ ///
+ /// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx)
+ ///
+ static DWORD APIENTRY get_response_packet(_In_ EAP_SESSION_HANDLE hSession, _Inout_ DWORD *pcbSendPacket, _Out_cap_(*pcbSendPacket) EapPacket *pSendPacket, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->get_response_packet(pcbSendPacket, pSendPacket, ppEapError);
+ }
+
+
+ ///
+ /// Obtains the result of an authentication session from the EAP method.
+ ///
+ /// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx)
+ ///
+ static DWORD APIENTRY get_result(_In_ EAP_SESSION_HANDLE hSession, _In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->get_result(reason, ppResult, ppEapError);
+ }
+
+
+ ///
+ /// Obtains the user interface context from the EAP method.
+ ///
+ /// \note This function is always followed by the `EapPeerInvokeInteractiveUI()` function, which is followed by the `EapPeerSetUIContext()` function.
+ ///
+ /// \sa [EapPeerGetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363612.aspx)
+ ///
+ static DWORD APIENTRY get_ui_context(_In_ EAP_SESSION_HANDLE hSession, _Out_ DWORD *dwSizeOfUIContextData, _Out_cap_(*dwSizeOfUIContextData) BYTE **pUIContextData, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->get_ui_context(dwSizeOfUIContextData, pUIContextData, ppEapError);
+ }
+
+
+ ///
+ /// Provides a user interface context to the EAP method.
+ ///
+ /// \note This function is called after the UI has been raised through the `EapPeerGetUIContext()` function.
+ ///
+ /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx)
+ ///
+ static DWORD APIENTRY set_ui_context(_In_ EAP_SESSION_HANDLE hSession, _In_ DWORD dwSizeOfUIContextData, _In_count_(dwSizeOfUIContextData) const BYTE *pUIContextData, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->set_ui_context(dwSizeOfUIContextData, pUIContextData, pEapOutput, ppEapError);
+ }
+
+
+ ///
+ /// Obtains an array of EAP response attributes from the EAP method.
+ ///
+ /// \sa [EapPeerGetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363609.aspx)
+ ///
+ static DWORD APIENTRY get_response_attributes(_In_ EAP_SESSION_HANDLE hSession, _Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->get_response_attributes(pAttribs, ppEapError);
+ }
+
+
+ ///
+ /// Provides an updated array of EAP response attributes to the EAP method.
+ ///
+ /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx)
+ ///
+ static DWORD APIENTRY set_response_attributes(_In_ EAP_SESSION_HANDLE hSession, _In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
+ {
+ assert(hSession);
+ return static_cast(hSession)->set_response_attributes(pAttribs, pEapOutput, ppEapError);
+ }
+
+ protected:
+ winstd::heap m_heap; ///< Heap
+ mutable winstd::event_provider m_ep; ///< Event Provider
+ };
+};
diff --git a/EAPMethods/include/EAPTTLS.h b/EAPMethods/include/EAPTTLS.h
new file mode 100644
index 0000000..7bce9b7
--- /dev/null
+++ b/EAPMethods/include/EAPTTLS.h
@@ -0,0 +1,47 @@
+/*
+ Copyright 2015-2016 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of GEANTLink.
+
+ GEANTLink is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ GEANTLink is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GEANTLink. If not, see .
+*/
+
+#include "EAPMethods.h"
+
+namespace eap
+{
+ class session_ttls;
+ class peer_ttls;
+}
+
+#pragma once
+
+
+namespace eap
+{
+ class session_ttls : public session_base
+ {
+ public:
+ ///
+ /// Constructor
+ ///
+ session_ttls();
+ };
+
+
+ class peer_ttls : public peer
+ {
+ };
+}
diff --git a/EAPMethods/include/StdAfx.h b/EAPMethods/include/StdAfx.h
index 773bd73..30139ff 100644
--- a/EAPMethods/include/StdAfx.h
+++ b/EAPMethods/include/StdAfx.h
@@ -20,12 +20,21 @@
#pragma once
+#include "../../include/Version.h"
+
+#include "../include/EAPTTLS.h"
+
#include
#include
#include
+extern "C" {
+#include
+}
+#include
#include
+#include
#include
#include
diff --git a/EAPMethods/res/EAPMethodETW.man b/EAPMethods/res/EAPMethodETW.man
index 4b9df02..0bff491 100644
Binary files a/EAPMethods/res/EAPMethodETW.man and b/EAPMethods/res/EAPMethodETW.man differ
diff --git a/EAPMethods/src/EAPMethods.cpp b/EAPMethods/src/EAPMethods.cpp
new file mode 100644
index 0000000..3c46fc6
--- /dev/null
+++ b/EAPMethods/src/EAPMethods.cpp
@@ -0,0 +1,132 @@
+/*
+ Copyright 2015-2016 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of GEANTLink.
+
+ GEANTLink is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ GEANTLink is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GEANTLink. If not, see .
+*/
+
+#include
+
+
+//////////////////////////////////////////////////////////////////////
+// eap::session_base
+//////////////////////////////////////////////////////////////////////
+
+eap::session_base::session_base()
+{
+}
+
+
+DWORD eap::session_base::begin(_In_ DWORD dwFlags, _In_ const EapAttributes *pAttributeArray, _In_ HANDLE hTokenImpersonateUser, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) BYTE *pUserData, _In_ DWORD dwMaxSendPacketSize, _Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(dwFlags);
+ UNREFERENCED_PARAMETER(pAttributeArray);
+ UNREFERENCED_PARAMETER(hTokenImpersonateUser);
+ UNREFERENCED_PARAMETER(dwSizeofConnectionData);
+ UNREFERENCED_PARAMETER(pConnectionData);
+ UNREFERENCED_PARAMETER(dwSizeofUserData);
+ UNREFERENCED_PARAMETER(pUserData);
+ UNREFERENCED_PARAMETER(dwMaxSendPacketSize);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_SUCCESS;
+}
+
+
+DWORD eap::session_base::end(_Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_SUCCESS;
+}
+
+
+DWORD eap::session_base::process_request_packet(_In_ DWORD dwSizeofReceivePacket, _In_bytecount_(dwSizeofReceivePacket) EapPacket *pReceivePacket, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(dwSizeofReceivePacket);
+ UNREFERENCED_PARAMETER(pReceivePacket);
+ UNREFERENCED_PARAMETER(pEapOutput);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_NOT_SUPPORTED;
+}
+
+
+DWORD eap::session_base::get_response_packet(_Inout_ DWORD *pcbSendPacket, _Out_cap_(*pcbSendPacket) EapPacket *pSendPacket, _Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(pcbSendPacket);
+ UNREFERENCED_PARAMETER(pSendPacket);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_NOT_SUPPORTED;
+}
+
+
+DWORD eap::session_base::get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(reason);
+ UNREFERENCED_PARAMETER(ppResult);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_NOT_SUPPORTED;
+}
+
+
+DWORD eap::session_base::get_ui_context(_Out_ DWORD *dwSizeOfUIContextData, _Out_cap_(*dwSizeOfUIContextData) BYTE **pUIContextData, _Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(dwSizeOfUIContextData);
+ UNREFERENCED_PARAMETER(pUIContextData);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_NOT_SUPPORTED;
+}
+
+
+DWORD eap::session_base::set_ui_context(_In_ DWORD dwSizeOfUIContextData, _In_count_(dwSizeOfUIContextData) const BYTE *pUIContextData, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
+{
+ UNREFERENCED_PARAMETER(dwSizeOfUIContextData);
+ UNREFERENCED_PARAMETER(pUIContextData);
+ UNREFERENCED_PARAMETER(pEapOutput);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ return ERROR_NOT_SUPPORTED;
+}
+
+
+DWORD eap::session_base::get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError)
+{
+ assert(pAttribs);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ pAttribs->dwNumberOfAttributes = 0;
+ pAttribs->pAttribs = NULL;
+
+ return ERROR_SUCCESS;
+}
+
+
+DWORD eap::session_base::set_response_attributes(_In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
+{
+ assert(pAttribs);
+ assert(pEapOutput);
+ UNREFERENCED_PARAMETER(ppEapError);
+
+ pEapOutput->action = EapPeerMethodResponseActionNone;
+ pAttribs->dwNumberOfAttributes = 0;
+ pAttribs->pAttribs = NULL;
+
+ return ERROR_SUCCESS;
+}
diff --git a/EAPMethods/src/EAPTTLS.cpp b/EAPMethods/src/EAPTTLS.cpp
new file mode 100644
index 0000000..711444d
--- /dev/null
+++ b/EAPMethods/src/EAPTTLS.cpp
@@ -0,0 +1,30 @@
+/*
+ Copyright 2015-2016 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of GEANTLink.
+
+ GEANTLink is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ GEANTLink is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GEANTLink. If not, see .
+*/
+
+#include
+
+
+//////////////////////////////////////////////////////////////////////
+// eap::session_ttls
+//////////////////////////////////////////////////////////////////////
+
+eap::session_ttls::session_ttls() : session_base()
+{
+}
diff --git a/EAPMethods/src/Main.cpp b/EAPMethods/src/Main.cpp
index b9ced08..6031a2e 100644
--- a/EAPMethods/src/Main.cpp
+++ b/EAPMethods/src/Main.cpp
@@ -20,94 +20,40 @@
#include
-using namespace std;
-using namespace winstd;
+#pragma comment(lib, "Comctl32.lib")
+#pragma comment(lib, "Shlwapi.lib")
+#if EAPMETHOD_TYPE==21
+#define _EAPMETHOD_PEER eap::peer_ttls
+#else
+#error Unknown EAP Method type.
+#endif
-#define ETW_FN_VOID event_fn_auto < &EAPMETHOD_TRACE_EVT_FN_CALL, &EAPMETHOD_TRACE_EVT_FN_RETURN > _event_auto(*g_ep, __FUNCTION__)
-#define ETW_FN_DWORD(res) event_fn_auto_ret _event_auto(*g_ep, __FUNCTION__, res)
-#define ETW_FN_HRESULT(res) event_fn_auto_ret _event_auto(*g_ep, __FUNCTION__, res)
-
-
-event_provider *g_ep = NULL;
-
-
-// event_fn_auto actually and winstd::event_auto_res<> do not need an assignment operator actually, so the C4512 warning is safely ignored.
-#pragma warning(push)
-#pragma warning(disable: 4512)
-
-///
-/// Helper class to write an event on entry/exit of scope.
-///
-/// It writes one string event at creation and another at destruction.
-///
-template
-class event_fn_auto
-{
-public:
- inline event_fn_auto(_In_ event_provider &ep, _In_z_ LPCSTR pszFnName) : m_ep(ep)
- {
- EventDataDescCreate(&m_fn_name, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName));
- m_ep.write(event_cons, 1, &m_fn_name);
- }
-
- inline ~event_fn_auto()
- {
- m_ep.write(event_dest, 1, &m_fn_name);
- }
-
-protected:
- event_provider &m_ep; ///< Reference to event provider in use
- EVENT_DATA_DESCRIPTOR m_fn_name; ///< Function name
-};
+_EAPMETHOD_PEER g_peer;
///
-/// Helper template to write an event on entry/exit of scope with one parameter (typically result).
+/// DLL main entry point
///
-/// It writes one string event at creation and another at destruction, with allowing one sprintf type parameter for string event at destruction.
+/// \sa [DllMain entry point](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx)
///
-template
-class event_fn_auto_ret
-{
-public:
- inline event_fn_auto_ret(_In_ event_provider &ep, _In_z_ LPCSTR pszFnName, T &result) : m_ep(ep), m_result(result)
- {
- EventDataDescCreate(m_desc + 0, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName));
- m_ep.write(event_cons, 1, m_desc);
- }
-
- inline ~event_fn_auto_ret()
- {
- EventDataDescCreate(m_desc + 1, &m_result, sizeof(T));
- m_ep.write(event_dest, 2, m_desc);
- }
-
-protected:
- event_provider &m_ep; ///< Reference to event provider in use
- T &m_result; ///< Function result
- EVENT_DATA_DESCRIPTOR m_desc[2]; ///< Function name and return value
-};
-
-#pragma warning(pop)
-
-
-
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
{
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
if (fdwReason == DLL_PROCESS_ATTACH) {
- g_ep = new event_provider();
- assert(g_ep);
- g_ep->create(&EAPMETHOD_TRACE_EVENT_PROVIDER);
- g_ep->write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, event_data((unsigned int)EAPMETHOD_TYPE), event_data::blank);
- } else if (fdwReason == DLL_PROCESS_DETACH) {
- assert(g_ep);
- g_ep->write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, event_data((unsigned int)EAPMETHOD_TYPE), event_data::blank);
- delete g_ep;
+ //// Load EAPMethodEvents.dll
+ //tstring path;
+ //GetModuleFileName(hinstDLL, path);
+ //LPTSTR pszFilename = PathFindFileName(path.c_str());
+ //path.resize(pszFilename ? (size_t)(pszFilename - (LPCTSTR)path.c_str()) : 0);
+ //path += _T("EAPMethodEvents.dll");
+ //g_EAPMethodEvents.load(path.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
+ if (!g_peer.create())
+ return FALSE;
+ } else if (fdwReason == DLL_PROCESS_DETACH) {
assert(!_CrtDumpMemoryLeaks());
}
@@ -115,66 +61,183 @@ BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID l
}
-//#pragma comment(linker, "/EXPORT:DllRegisterServer,PRIVATE")
-//#pragma comment(linker, "/EXPORT:DllUnregisterServer,PRIVATE")
-
-
-extern "C"
+///
+/// Releases all memory associated with an opaque user interface context data buffer.
+///
+/// \sa [EapPeerFreeMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363606.aspx)
+///
+VOID WINAPI EapPeerFreeMemory(_In_ void *pUIContextData)
{
- /////
- ///// Registers the EAP method.
- /////
- //HRESULT STDAPICALLTYPE DllRegisterServer()
- //{
- // HRESULT hr = S_OK;
- // ETW_FN_HRESULT(hr);
+ g_peer.free_memory(pUIContextData);
+}
- // return hr;
- //}
+#pragma comment(linker, "/EXPORT:EapPeerFreeMemory")
- /////
- ///// Unregisters the EAP method.
- /////
- //HRESULT STDAPICALLTYPE DllUnregisterServer()
- //{
- // HRESULT hr = S_OK;
- // ETW_FN_HRESULT(hr);
+///
+/// Releases error-specific memory allocated by the EAP peer method.
+///
+/// \sa [EapPeerFreeErrorMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363605.aspx)
+///
+VOID WINAPI EapPeerFreeErrorMemory(_In_ EAP_ERROR *ppEapError)
+{
+ g_peer.free_error_memory(ppEapError);
+}
- // return hr;
- //}
+#pragma comment(linker, "/EXPORT:EapPeerFreeErrorMemory")
- ///
- /// Releases all memory associated with an opaque user interface context data buffer.
- ///
- /// \sa [EapPeerFreeMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363606.aspx)
- ///
- __declspec(dllexport) VOID WINAPI EapPeerFreeMemory(_In_ void *pUIContextData)
- {
- ETW_FN_VOID;
+///
+/// Obtains a set of function pointers for an implementation of the EAP peer method currently loaded on the EAPHost service.
+///
+/// \sa [EapPeerGetInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363608.aspx)
+///
+DWORD WINAPI EapPeerGetInfo(_In_ EAP_TYPE* pEapType, _Out_ EAP_PEER_METHOD_ROUTINES* pEapPeerMethodRoutines, _Out_ EAP_ERROR **ppEapError)
+{
+ DWORD dwResult = NO_ERROR;
+#ifdef _DEBUG
+ //Sleep(10000);
+#endif
- if (pUIContextData) {
- // Since we do security here and some of the BLOBs contain credentials, sanitize every memory block before freeing.
- HANDLE hHeap = GetProcessHeap();
- SecureZeroMemory(pUIContextData, HeapSize(hHeap, 0, pUIContextData));
- HeapFree(hHeap, 0, pUIContextData);
- }
+ // Parameter check
+ if (!ppEapError) {
+ dwResult = ERROR_INVALID_PARAMETER;
+ } else if (!pEapType) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
+ } else if (pEapType->type != EAPMETHOD_TYPE) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->type, (int)EAPMETHOD_TYPE).c_str(), NULL);
+ } else if (!pEapPeerMethodRoutines) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapPeerMethodRoutines is NULL."), NULL);
+ } else
+ g_peer.get_info(pEapPeerMethodRoutines);
+
+ return dwResult;
+}
+
+#pragma comment(linker, "/EXPORT:EapPeerGetInfo")
+
+
+///
+/// Raises the EAP method's specific connection configuration user interface dialog on the client.
+///
+/// \sa [EapPeerInvokeConfigUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363614.aspx)
+///
+DWORD WINAPI EapPeerInvokeConfigUI(_In_ EAP_METHOD_TYPE *pEapType, _In_ HWND hwndParent, _In_ DWORD dwFlags, _In_ DWORD dwSizeOfConnectionDataIn, _In_ BYTE *pConnectionDataIn, _Out_ DWORD *pdwSizeOfConnectionDataOut, _Out_ BYTE **ppConnectionDataOut, _Out_ EAP_ERROR **ppEapError)
+{
+ DWORD dwResult = NO_ERROR;
+
+#ifdef _DEBUG
+ //MessageBox(NULL, _T("Attach debugger!"), _T(__FUNCTION__), MB_OK);
+#endif
+
+ // Parameter check
+ if (!ppEapError) {
+ dwResult = ERROR_INVALID_PARAMETER;
+ } else if (!pEapType) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
+ } else if (pEapType->eapType.type != EAPMETHOD_TYPE) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
+ } else if (pEapType->dwAuthorId != 67532) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL);
+ } else if (!pdwSizeOfConnectionDataOut) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwSizeOfConnectionDataOut is NULL."), NULL);
+ } else if (!ppConnectionDataOut) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppConnectionDataOut is NULL."), NULL);
+ } else {
+ UNREFERENCED_PARAMETER(dwFlags);
+ UNREFERENCED_PARAMETER(dwSizeOfConnectionDataIn);
+ UNREFERENCED_PARAMETER(pConnectionDataIn);
+
+ InitCommonControls();
+ MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" configuration goes here!"), _T(PRODUCT_NAME_STR) _T(" Settings"), MB_OK);
}
+ return dwResult;
+}
- ///
- /// Releases error-specific memory allocated by the EAP peer method.
- ///
- /// \sa [EapPeerFreeErrorMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363605.aspx)
- ///
- __declspec(dllexport) VOID WINAPI EapPeerFreeErrorMemory(_In_ EAP_ERROR *ppEapError)
- {
- ETW_FN_VOID;
+#pragma comment(linker, "/EXPORT:EapPeerInvokeConfigUI")
- if (ppEapError) {
- // pRootCauseString and pRepairString always trail the ppEapError to reduce number of (de)allocations.
- HeapFree(GetProcessHeap(), 0, ppEapError);
- }
+
+///
+/// Raises a custom interactive user interface dialog to obtain user identity information for the EAP method on the client.
+///
+/// \sa [EapPeerInvokeIdentityUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363615.aspx)
+///
+DWORD WINAPI EapPeerInvokeIdentityUI(_In_ EAP_METHOD_TYPE *pEapType, _In_ DWORD dwFlags, _In_ HWND hwndParent, _In_ DWORD dwSizeOfConnectionData, _In_ const BYTE *pConnectionData, _Out_ DWORD dwSizeOfUserData, _In_ const BYTE *pUserData, _Out_ DWORD *pdwSizeOfUserDataOut, _Out_ BYTE **ppUserDataOut, _Out_ LPWSTR *ppwszIdentity, _Out_ EAP_ERROR **ppEapError)
+{
+ DWORD dwResult = NO_ERROR;
+
+#ifdef _DEBUG
+ //MessageBox(NULL, _T("Attach debugger!"), _T(__FUNCTION__), MB_OK);
+#endif
+
+ // Parameter check
+ if (!ppEapError) {
+ dwResult = ERROR_INVALID_PARAMETER;
+ } else if (!pEapType) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
+ } else if (pEapType->eapType.type != EAPMETHOD_TYPE) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
+ } else if (pEapType->dwAuthorId != 67532) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL);
+ } else if (!pdwSizeOfUserDataOut) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwSizeOfUserDataOut is NULL."), NULL);
+ } else if (!ppUserDataOut) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppUserDataOut is NULL."), NULL);
+ } else if (!ppwszIdentity) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppwszIdentity is NULL."), NULL);
+ } else {
+ UNREFERENCED_PARAMETER(dwFlags);
+ UNREFERENCED_PARAMETER(pUserData);
+ UNREFERENCED_PARAMETER(dwSizeOfUserData);
+ UNREFERENCED_PARAMETER(pConnectionData);
+ UNREFERENCED_PARAMETER(dwSizeOfConnectionData);
+
+ InitCommonControls();
+ MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" credential prompt goes here!"), _T(PRODUCT_NAME_STR) _T(" Credentials"), MB_OK);
}
-};
+
+ return dwResult;
+}
+
+#pragma comment(linker, "/EXPORT:EapPeerInvokeIdentityUI")
+
+
+///
+/// Raises a custom interactive user interface dialog for the EAP method on the client.
+///
+/// \sa [EapPeerInvokeInteractiveUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363616.aspx)
+///
+DWORD WINAPI EapPeerInvokeInteractiveUI(_In_ EAP_METHOD_TYPE *pEapType, _In_ HWND hwndParent, _In_ DWORD dwSizeofUIContextData, _In_ BYTE *pUIContextData, _Out_ DWORD *pdwSizeOfDataFromInteractiveUI, _Out_ BYTE **ppDataFromInteractiveUI, _Out_ EAP_ERROR **ppEapError)
+{
+ DWORD dwResult = NO_ERROR;
+
+#ifdef _DEBUG
+ //MessageBox(NULL, _T("Attach debugger!"), _T(__FUNCTION__), MB_OK);
+#endif
+
+ // Parameter check
+ if (!ppEapError) {
+ dwResult = ERROR_INVALID_PARAMETER;
+ } else if (!pEapType) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL);
+ } else if (pEapType->eapType.type != EAPMETHOD_TYPE) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL);
+ } else if (pEapType->dwAuthorId != 67532) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL);
+ } else if (!pdwSizeOfDataFromInteractiveUI) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwSizeOfDataFromInteractiveUI is NULL."), NULL);
+ } else if (!ppDataFromInteractiveUI) {
+ *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppDataFromInteractiveUI is NULL."), NULL);
+ } else {
+ UNREFERENCED_PARAMETER(dwSizeofUIContextData);
+ UNREFERENCED_PARAMETER(pUIContextData);
+
+ InitCommonControls();
+ MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" interactive UI goes here!"), _T(PRODUCT_NAME_STR) _T(" Prompt"), MB_OK);
+ }
+
+ return dwResult;
+}
+
+#pragma comment(linker, "/EXPORT:EapPeerInvokeInteractiveUI")
diff --git a/lib/WinStd b/lib/WinStd
index 03cb7ee..61a8704 160000
--- a/lib/WinStd
+++ b/lib/WinStd
@@ -1 +1 @@
-Subproject commit 03cb7ee822826b30f18d9e0fc0a71583999e6b12
+Subproject commit 61a87046166b363382176f2d42f7efa2871d69a0