boost::filesystem::path GetModulePath(HMODULE module_handle) { wchar_t buffer[MAX_PATH]; DWORD path_len = ::GetModuleFileNameW(module_handle, buffer, _countof(buffer)); if (path_len == 0) { throw windows_exception("::GetModuleFileNameW failed."); } if (path_len < _countof(buffer)) { return std::move(boost::filesystem::path(buffer, buffer + path_len)); } for (size_t buf_len = 0x200; buf_len <= 0x10000; buf_len <<= 1) { std::dynarray<wchar_t> buf(path_len); path_len = ::GetModuleFileNameW(module_handle, buf.data(), buf.size()); if (path_len == 0) { throw windows_exception("::GetModuleFileNameW failed."); } if (path_len < _countof(buffer)) { return std::move(boost::filesystem::path(buf.begin(), buf.end())); } } throw windows_exception("::GetModuleFileNameW failed."); }
void memory_mapped_file::open(void* file, uint64_t offset, size_t request_size) { DWORD size_high; DWORD size_low = ::GetFileSize(file, &size_high); DWORD error_code = ::GetLastError(); if (INVALID_FILE_SIZE == size_low && ERROR_SUCCESS != error_code) { throw windows_exception("failed to determine file size", error_code); } uint64_t file_size = (static_cast<uint64_t>(size_high) << 32) | size_low; uint64_t map_size = offset + request_size;; if (map_size < offset) { throw windows_exception("requested region exceeds the available address space", ERROR_INVALID_PARAMETER); } if (offset > file_size) { if (0 == request_size) { throw windows_exception("region out of range", ERROR_INVALID_PARAMETER); } } else if (0 == request_size) { #ifdef _WIN64 request_size = file_size - offset; #else uint64_t request_size2 = file_size - offset; if (request_size2 > static_cast<uint64_t>(0xFFFFFFFF)) { throw windows_exception("region size too large", ERROR_NOT_ENOUGH_MEMORY); } request_size = static_cast<size_t>(request_size2); #endif map_size = offset + request_size; } if (0 == request_size) { memory_ = nullptr; cb_ = 0; return; } file_mapping_handle map_(file, NULL, PAGE_READONLY, map_size, NULL); memory_ = map_.create_view(FILE_MAP_READ, offset, request_size); cb_ = request_size; }
void memory_mapped_file::open(const wchar_t* file_name, uint64_t offset, size_t request_size) { file_handle file_(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); uint64_t file_size = file_.get_size(); uint64_t map_size = offset + request_size; if (map_size < offset) { throw windows_exception("requested region exceeds the available address space", ERROR_INVALID_PARAMETER); } if (offset > file_size) { if(0 == request_size) { throw windows_exception("region out of range", ERROR_INVALID_PARAMETER); } } else if(0 == request_size) { #ifdef _WIN64 request_size = file_size - offset; #else uint64_t request_size2 = file_size - offset; if (request_size2 > static_cast<uint64_t>(0xFFFFFFFF)) { throw windows_exception("region size too large", ERROR_NOT_ENOUGH_MEMORY); } request_size = static_cast<size_t>(request_size2); #endif map_size = offset + request_size; } if (0 == request_size) { memory_ = nullptr; cb_ = 0; return ; } file_mapping_handle map_(file_, NULL, PAGE_READONLY, map_size, NULL); memory_ = map_.create_view(FILE_MAP_READ, offset, request_size); cb_ = request_size; }
file_handle::file_handle(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) : _Mybase(::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)) { if (!_Mybase::operator bool()) { throw windows_exception(L"failed to open file"); } }
// // see the // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188.aspx // std::wstring env_variable::get() { std::array<wchar_t, 32767> buffer; buffer[0] = L'\0'; DWORD retval = ::GetEnvironmentVariableW(name_.c_str(), buffer.data(), buffer.size()); if (retval == 0 || retval > buffer.size()) { throw windows_exception("GetEnvironmentVariable failed."); } return std::move(std::wstring(buffer.begin(), buffer.end())); }
boost::filesystem::path GetSystemPath() { wchar_t buffer[MAX_PATH]; DWORD path_len = ::GetSystemDirectoryW(buffer, _countof(buffer)); if (path_len == 0) { throw windows_exception("::GetSystemDirectoryW failed."); } if (path_len <= _countof(buffer)) { return std::move(boost::filesystem::path(buffer, buffer + path_len)); } std::dynarray<wchar_t> buf(path_len); path_len = ::GetWindowsDirectoryW(buf.data(), buf.size()); if (path_len == 0 || path_len > _countof(buffer)) { throw windows_exception("::GetSystemDirectoryW failed."); } return std::move(boost::filesystem::path(buf.begin(), buf.end())); }
uint64_t file_handle::get_size() { DWORD size_high; DWORD size_low = ::GetFileSize(_Mybase::get(), &size_high); DWORD error_code = ::GetLastError(); if (INVALID_FILE_SIZE == size_low && ERROR_SUCCESS != error_code) { throw windows_exception(L"failed to determine file size", error_code); } return (static_cast<uint64_t>(size_high) << 32) | size_low; }
void convert_aux(const char* from, const char* from_end, wchar_t* to, wchar_t* to_end, std::wstring& target, const codecvt_type& cvt, conv_method how) { std::mbstate_t state = std::mbstate_t(); const char* from_next; wchar_t* to_next; ::SetLastError(ERROR_SUCCESS); if (cvt.in(state, from, from_end, from_next, to, to_end, to_next) == std::codecvt_base::ok) { target.append(to, to_next); return ; } if (how.type() == conv_method::stop) { throw windows_exception("character conversion failed"); } from_next = from; while (from_next != from_end) { wchar_t to_buf[4]; int len = cvt.length(state, from_next, from_end, 1); if (len <= 0) return; const char* from_mid; if (cvt.in(state, from_next, from_next + len, from_mid, to_buf, to_buf + _countof(to_buf), to_next) == std::codecvt_base::ok) { assert(from_next + len == from_mid); target.append(to_buf, to_next); from_next += len; } else { if (how.type() == conv_method::replace) { target.push_back(static_cast<wchar_t>(how.default_char())); from_next += 1; } else { from_next += len; } } } }
// // https://blogs.msdn.com/b/larryosterman/archive/2010/10/19/because-if-you-do_2c00_-stuff-doesn_2700_t-work-the-way-you-intended_2e00_.aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx // boost::filesystem::path GetTempPath() { boost::optional<std::wstring> result; result = win::env_variable(L"TMP").get_nothrow(); if (result && !result->empty()) { return std::move(boost::filesystem::path(result.get())); } result = win::env_variable(L"TEMP").get_nothrow(); if (result && !result->empty()) { return std::move(boost::filesystem::path(result.get())); } wchar_t buffer[MAX_PATH + 1]; DWORD path_len = ::GetTempPathW(MAX_PATH, buffer); if (path_len >= MAX_PATH || path_len <= 0) { throw windows_exception("::GetTempPathW(MAX_PATH, buffer) failed."); } return std::move(boost::filesystem::path(buffer)); }
inline ws_uint64_t load_text_file_impl(S1 const& fileName, S2 &contents) { typedef string_traits<S1> string_traits_t; STLSOFT_STATIC_ASSERT(sizeof(string_traits_t)); // Fires if S1 does not have a traits specialisation defined typedef string_traits<S2> string_traits2_t; STLSOFT_STATIC_ASSERT(sizeof(string_traits2_t)); // Fires if S2 does not have a traits specialisation defined typedef ss_typename_type_k string_traits_t::char_type C; STLSOFT_STATIC_ASSERT(sizeof(C)); // Fires if the traits is not correctly defined typedef ss_typename_type_k string_traits2_t::char_type char_2_type; STLSOFT_STATIC_ASSERT(sizeof(char_2_type)); // Fires if the traits is not correctly defined typedef filesystem_traits<C> filesys_traits_t; STLSOFT_STATIC_ASSERT(sizeof(filesys_traits_t)); // Fires if no corresponding filesystem_traits defined scoped_handle<HANDLE> h( filesys_traits_t::create_file( stlsoft_ns_qual(c_str_ptr)(fileName) , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , NULL) , (void (STLSOFT_CDECL *)(HANDLE))&filesys_traits_t::close_handle // This cast required by VC++ 5 , INVALID_HANDLE_VALUE); if(INVALID_HANDLE_VALUE == h.get()) { STLSOFT_THROW_X(windows_exception("File does not exist", ::GetLastError())); } ws_uint64_t size = filesys_traits_t::get_file_size(h.get()); if( 0 != size && static_cast<ws_uint64_t>(~0) != size) { if(size > 0xFFFFFFFF) { STLSOFT_THROW_X(winstl_ns_qual_std(out_of_range)("Cannot read in files larger than 4GB")); } else { // TODO: Catch the out-of-memory exception and translate to a std::out_of_range() typedef ::stlsoft::auto_buffer_old< char_2_type , processheap_allocator<char_2_type> , 1024 > buffer_t; buffer_t buffer(static_cast<ss_typename_type_k buffer_t::size_type>(size)); DWORD dw; if(!::ReadFile(h.get(), &buffer[0], buffer.size(), &dw, NULL)) { STLSOFT_THROW_X(windows_exception("Read operation failed", ::GetLastError())); } else { contents.assign(&buffer[0], dw); return size; } } } return 0; }