/** * \file * \author Egor Tensin * \date 2015 * \copyright This file is licensed under the terms of the MIT License. * See LICENSE.txt for details. */ #include "libservice/all.hpp" #include #include #include #include #include #include #include namespace libservice { namespace { Handle open_device(const std::string& path) { const auto raw = CreateFileA( path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == raw) { const auto ec = GetLastError(); throw std::system_error( ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); } return Handle(raw); } } Device Device::open(const std::string& path) { return Device(open_device(path)); } std::size_t Device::get_required_output_size( Code code, const void* in_buf, std::size_t in_buf_size) const { DWORD nbreq; if (in_buf_size > std::numeric_limits::max()) throw std::range_error("input buffer size is too large"); std::size_t nbwritten = DeviceIoControl( handle, code, const_cast(in_buf), static_cast(in_buf_size), NULL, 0, &nbreq, NULL); if (0 == nbwritten) { const auto ec = GetLastError(); switch (ec) { case ERROR_MORE_DATA: return nbreq; default: throw std::system_error( ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); } } return nbwritten; } std::size_t Device::send_control_code( Code code, const void* in_buf, std::size_t in_buf_size, void* out_buf, std::size_t out_buf_size) const { DWORD nbreq; if (in_buf_size > std::numeric_limits::max()) throw std::range_error("input buffer size is too large"); if (out_buf_size > std::numeric_limits::max()) throw std::range_error("output buffer size is too large"); std::size_t nbwritten = DeviceIoControl( handle, code, const_cast(in_buf), static_cast(in_buf_size), out_buf, static_cast(out_buf_size), &nbreq, NULL); if (0 == nbwritten) { const auto ec = GetLastError(); throw std::system_error( ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); } return nbwritten; } void swap(Device& a, Device& b) LIBSERVICE_NOEXCEPT { a.swap(b); } } namespace std { template <> void swap( libservice::Device& a, libservice::Device& b) { a.swap(b); } }