diff --git a/include/WinStd/EAP.h b/include/WinStd/EAP.h index ceba3f43..de20ba69 100644 --- a/include/WinStd/EAP.h +++ b/include/WinStd/EAP.h @@ -27,10 +27,13 @@ namespace winstd { class WINSTD_API eap_attr; class WINSTD_API eap_method_prop; + class WINSTD_API eap_packet; } #pragma once +#include + namespace winstd { @@ -185,5 +188,168 @@ namespace winstd } }; + + /// + /// EapPacket wrapper class + /// + class WINSTD_API eap_packet : public dplhandle + { + public: + /// + /// Initializes a new class instance with the EAP packet set to NULL. + /// + inline eap_packet() + { + } + + + /// + /// Initializes a new class instance with the duplicated EAP packet. + /// + /// \param[in] h Initial EAP packet value + /// + inline eap_packet(_In_ handle_type h) + { + m_h = duplicate_internal(h); + } + + + /// + /// Destroys the EAP packet. + /// + virtual ~eap_packet(); + + + /// + /// Create new EAP packet + /// + /// \param[in] code EAP code (one of EapCode enum values) + /// \param[in] id Packet ID + /// \param[in] size Initial packet size. Must be at least 4. + /// + /// \note Packet data (beyond first 4B) is not initialized. + /// + /// \return + /// - true when creation succeeds; + /// - false when creation fails. For extended error information, call `GetLastError()`. + /// + inline bool create(_In_ EapCode code, _In_ BYTE id, _In_ WORD size) + { + assert(size >= 4); // EAP packets must contain at least 4B. + + handle_type h = (handle_type)HeapAlloc(GetProcessHeap(), 0, size); + if (h) { + h->Code = (BYTE) code ; + h->Id = id ; + *(WORD*)h->Length = htons(size); + + attach(h); + return true; + } else { + SetLastError(ERROR_OUTOFMEMORY); + return false; + } + } + + + /// + /// Create new EAP Request packet + /// + /// \param[in] id Packet ID + /// \param[in] protocol Protocol ID + /// \param[in] flags Request flags + /// \param[in] size Initial packet size. Must be at least 6. + /// + /// \note Packet data (beyond first 6B) is not initialized. + /// + /// \return + /// - true when creation succeeds; + /// - false when creation fails. For extended error information, call `GetLastError()`. + /// + inline bool create_request(_In_ BYTE id, _In_ BYTE protocol, _In_ BYTE flags, _In_opt_ WORD size = 6) + { + assert(size >= 6); // EAP Request packets must contain at least 6B. + + if (!create(EapCodeRequest, id, size)) + return false; + + m_h->Data[0] = protocol; + m_h->Data[1] = flags; + + return true; + } + + + /// + /// Create new EAP Response packet + /// + /// \param[in] id Packet ID + /// \param[in] protocol Protocol ID + /// \param[in] flags Response flags + /// \param[in] size Initial packet size. Must be at least 6. + /// + /// \note Packet data (beyond first 6B) is not initialized. + /// + /// \return + /// - true when creation succeeds; + /// - false when creation fails. For extended error information, call `GetLastError()`. + /// + inline bool create_response(_In_ BYTE id, _In_ BYTE protocol, _In_ BYTE flags, _In_opt_ WORD size = 6) + { + assert(size >= 6); // EAP Response packets must contain at least 6B. + + if (!create(EapCodeResponse, id, size)) + return false; + + m_h->Data[0] = protocol; + m_h->Data[1] = flags; + + return true; + } + + + /// + /// Create Accept EAP packet + /// + /// \param[in] id ID of EAP packet this packet is rejecting + /// + inline bool create_accept(_In_ BYTE id) + { + return create(EapCodeSuccess, id + 1, 4); + } + + + /// + /// Create Reject EAP packet + /// + /// \param[in] id ID of EAP packet this packet is rejecting + /// + inline bool create_reject(_In_ BYTE id) + { + return create(EapCodeFailure, id + 1, 4); + } + + + /// + /// Returns total EAP packet size in bytes. + /// + inline WORD size() const + { + return m_h ? ntohs(*(WORD*)m_h->Length) : 0; + } + + + protected: + /// + /// Destroys the EAP packet. + /// + virtual void free_internal(); + + /// + /// Duplicates the EAP packet. + /// + virtual handle_type duplicate_internal(_In_ handle_type h) const; + }; + /// @} } diff --git a/src/EAP.cpp b/src/EAP.cpp index f2abe5fb..3787a0af 100644 --- a/src/EAP.cpp +++ b/src/EAP.cpp @@ -25,9 +25,40 @@ // winstd::eap_attr ////////////////////////////////////////////////////////////////////// - winstd::eap_attr::~eap_attr() { if (pValue) delete []pValue; } + + +////////////////////////////////////////////////////////////////////// +// winstd::eap_packet +////////////////////////////////////////////////////////////////////// + +winstd::eap_packet::~eap_packet() +{ + if (m_h) + HeapFree(GetProcessHeap(), 0, m_h); +} + + +void winstd::eap_packet::free_internal() +{ + HeapFree(GetProcessHeap(), 0, m_h); +} + + +winstd::eap_packet::handle_type winstd::eap_packet::duplicate_internal(_In_ handle_type h) const +{ + WORD n = ntohs(*(WORD*)h->Length); + handle_type h2 = (handle_type)HeapAlloc(GetProcessHeap(), 0, n); + if (!h2) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + memcpy(h2, h, n); + + return h2; +}