annotate foosdk/sdk/foobar2000/helpers/file_win32_wrapper.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include <libPPUI/win32_op.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include <pfc/string-conv-lite.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 namespace file_win32_helpers {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 t_filesize get_size(HANDLE p_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 void seek(HANDLE p_handle,t_sfilesize p_position,file::t_seek_mode p_mode);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 void fillOverlapped(OVERLAPPED & ol, HANDLE myEvent, t_filesize s);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 void writeOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, const void * in,DWORD inBytes, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 void writeOverlapped(HANDLE handle, HANDLE myEvent, t_filesize & position, const void * in, size_t inBytes, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 void writeStreamOverlapped(HANDLE handle, HANDLE myEvent, const void * in, size_t inBytes, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 DWORD readOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, void * out, DWORD outBytes, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 size_t readOverlapped(HANDLE handle, HANDLE myEvent, t_filesize & position, void * out, size_t outBytes, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 size_t readStreamOverlapped(HANDLE handle, HANDLE myEvent, void * out, size_t outBytes, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 HANDLE createFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 size_t lowLevelIO(HANDLE hFile, const GUID & guid, size_t arg1, void * arg2, size_t arg2size, bool canWrite, abort_callback & abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 bool querySeekPenalty(const char * fb2k_path, bool & out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 bool querySeekPenalty(const wchar_t * nativePath, bool & out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 static uint64_t make_uint64(t_uint32 p_low, t_uint32 p_high) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 return ((t_uint64)p_low) + ((t_uint64)p_high << 32);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 static uint64_t make_uint64(LARGE_INTEGER const& i) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 return reinterpret_cast<uint64_t const&>(i);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 static uint64_t make_uint64(FILETIME const& ft) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 return reinterpret_cast<uint64_t const&>(ft);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 // return make_uint64(ft.dwLowDateTime, ft.dwHighDateTime);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 template<typename t_info>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 static t_filestats translate_stats(const t_info& p_info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 t_filestats ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 ret.m_size = make_uint64(p_info.nFileSizeLow, p_info.nFileSizeHigh);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 ret.m_timestamp = make_uint64(p_info.ftLastWriteTime);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 void attribs_from_win32(t_filestats2& out, DWORD in);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 template<typename t_info>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 static t_filestats2 translate_stats2(const t_info& p_info) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 t_filestats2 ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 ret.m_size = make_uint64(p_info.nFileSizeLow, p_info.nFileSizeHigh);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 ret.m_timestamp = make_uint64(p_info.ftLastWriteTime);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 ret.m_timestampCreate = make_uint64(p_info.ftCreationTime);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 attribs_from_win32(ret, p_info.dwFileAttributes);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 t_filestats2 stats2_from_handle(HANDLE, const wchar_t * fallbackPath, uint32_t flags, abort_callback &a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 template<bool p_seekable,bool p_writeable>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 class file_win32_wrapper_t : public service_multi_inherit<file_v2, file_lowLevelIO> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 typedef file_win32_wrapper_t<p_seekable, p_writeable> self_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 file_win32_wrapper_t(HANDLE handle, pfc::wstringLite && path) : m_handle(handle), m_path(std::move(path)) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 static file::ptr g_CreateFile(const char * p_path,DWORD p_access,DWORD p_sharemode,LPSECURITY_ATTRIBUTES p_security_attributes,DWORD p_createmode,DWORD p_flags,HANDLE p_template) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 auto pathW = pfc::wideFromUTF8(p_path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 SetLastError(NO_ERROR);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 HANDLE handle = CreateFile(pathW,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 if (handle == INVALID_HANDLE_VALUE) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 const DWORD code = GetLastError();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 if (p_access & GENERIC_WRITE) win32_file_write_failure(code, p_path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 else exception_io_from_win32(code);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 return g_create_from_handle(handle, std::move(pathW));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 } catch(...) {CloseHandle(handle); throw;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 static service_ptr_t<file> g_create_from_handle(HANDLE handle, pfc::wstringLite && path) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 return new service_impl_t<self_t>(handle, std::move(path));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 static service_ptr_t<file> g_create_from_handle(HANDLE handle) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 pfc::wstringLite blank;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 g_create_from_handle(handle, std::move(blank));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 void reopen(abort_callback & p_abort) {seek(0,p_abort);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 if (!p_writeable) throw exception_io_denied();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 PFC_STATIC_ASSERT(sizeof(t_size) >= sizeof(DWORD));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 t_size bytes_written_total = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 if (sizeof(t_size) == sizeof(DWORD)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 DWORD bytes_written = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 if (!WriteFile(m_handle,p_buffer,(DWORD)p_bytes,&bytes_written,0)) exception_io_from_win32(GetLastError());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 if (bytes_written != p_bytes) throw exception_io("Write failure");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 bytes_written_total = bytes_written;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 m_position += bytes_written;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 while(bytes_written_total < p_bytes) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 DWORD bytes_written = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 DWORD delta = (DWORD) pfc::min_t<t_size>(p_bytes - bytes_written_total, 0x80000000u);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 if (!WriteFile(m_handle,(const t_uint8*)p_buffer + bytes_written_total,delta,&bytes_written,0)) exception_io_from_win32(GetLastError());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 if (bytes_written != delta) throw exception_io("Write failure");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 bytes_written_total += bytes_written;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 m_position += bytes_written;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 PFC_STATIC_ASSERT(sizeof(t_size) >= sizeof(DWORD));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 t_size bytes_read_total = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 if (sizeof(t_size) == sizeof(DWORD)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 DWORD bytes_read = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 if (!ReadFile(m_handle,p_buffer,pfc::downcast_guarded<DWORD>(p_bytes),&bytes_read,0)) exception_io_from_win32(GetLastError());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 bytes_read_total = bytes_read;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 m_position += bytes_read;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 while(bytes_read_total < p_bytes) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 DWORD bytes_read = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 DWORD delta = (DWORD) pfc::min_t<t_size>(p_bytes - bytes_read_total, 0x80000000u);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 if (!ReadFile(m_handle,(t_uint8*)p_buffer + bytes_read_total,delta,&bytes_read,0)) exception_io_from_win32(GetLastError());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 bytes_read_total += bytes_read;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 m_position += bytes_read;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 if (bytes_read != delta) break;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 return bytes_read_total;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 t_filesize get_size(abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 return file_win32_helpers::get_size(m_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 t_filesize get_position(abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 return m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 void resize(t_filesize p_size,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 if (!p_writeable) throw exception_io_denied();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 if (m_position != p_size) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 file_win32_helpers::seek(m_handle,p_size,file::seek_from_beginning);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 if (!SetEndOfFile(m_handle)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 DWORD code = GetLastError();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 if (m_position != p_size) try {file_win32_helpers::seek(m_handle,m_position,file::seek_from_beginning);} catch(...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 exception_io_from_win32(code);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 if (m_position > p_size) m_position = p_size;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 if (m_position != p_size) file_win32_helpers::seek(m_handle,m_position,file::seek_from_beginning);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 void seek(t_filesize p_position,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 if (!p_seekable) throw exception_io_object_not_seekable();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 if (p_position > file_win32_helpers::get_size(m_handle)) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 file_win32_helpers::seek(m_handle,p_position,file::seek_from_beginning);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 m_position = p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 bool can_seek() {return p_seekable;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 bool get_content_type(pfc::string_base & out) {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 bool is_in_memory() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 void on_idle(abort_callback & p_abort) {p_abort.check_e();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 t_filestats2 get_stats2(uint32_t f, abort_callback& a) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 a.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 if (p_writeable) FlushFileBuffers(m_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 return file_win32_helpers::stats2_from_handle(m_handle, m_path, f, a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 t_filetimestamp get_timestamp(abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 if (p_writeable) FlushFileBuffers(m_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 FILETIME temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 if (!GetFileTime(m_handle,0,0,&temp)) exception_io_from_win32(GetLastError());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 return file_win32_helpers::make_uint64(temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 bool is_remote() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 ~file_win32_wrapper_t() {CloseHandle(m_handle);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 size_t lowLevelIO(const GUID & guid, size_t arg1, void * arg2, size_t arg2size, abort_callback & abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 return file_win32_helpers::lowLevelIO(m_handle, guid, arg1, arg2, arg2size, p_writeable, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 HANDLE m_handle;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 t_filesize m_position = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 pfc::wstringLite m_path;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 template<bool p_writeable>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 class file_win32_wrapper_overlapped_t : public service_multi_inherit< file_v2, file_lowLevelIO > {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 typedef file_win32_wrapper_overlapped_t<p_writeable> self_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 file_win32_wrapper_overlapped_t(HANDLE file, pfc::wstringLite && path) : m_handle(file), m_path(std::move(path)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 WIN32_OP( (m_event = CreateEvent(NULL, TRUE, FALSE, NULL)) != NULL );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 ~file_win32_wrapper_overlapped_t() {CloseHandle(m_event); CloseHandle(m_handle);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 if (!p_writeable) throw exception_io_denied();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 return file_win32_helpers::writeOverlapped(m_handle, m_event, m_position, p_buffer, p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 return file_win32_helpers::readOverlapped(m_handle, m_event, m_position, p_buffer, p_bytes, p_abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 void reopen(abort_callback & p_abort) {seek(0,p_abort);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 t_filesize get_size(abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 return file_win32_helpers::get_size(m_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 t_filesize get_position(abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 return m_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 void resize(t_filesize p_size,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 if (!p_writeable) throw exception_io_denied();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 file_win32_helpers::seek(m_handle,p_size,file::seek_from_beginning);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 if (!SetEndOfFile(m_handle)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 DWORD code = GetLastError();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 exception_io_from_win32(code);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 if (m_position > p_size) m_position = p_size;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 void seek(t_filesize p_position,abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 if (p_position > file_win32_helpers::get_size(m_handle)) throw exception_io_seek_out_of_range();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 // file_win32_helpers::seek(m_handle,p_position,file::seek_from_beginning);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 m_position = p_position;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 bool can_seek() {return true;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 bool get_content_type(pfc::string_base & out) {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 bool is_in_memory() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 void on_idle(abort_callback & p_abort) {p_abort.check_e();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 t_filestats2 get_stats2(uint32_t f, abort_callback& a) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 a.check();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 if (p_writeable) FlushFileBuffers(m_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 return file_win32_helpers::stats2_from_handle(m_handle, m_path, f, a);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 t_filetimestamp get_timestamp(abort_callback & p_abort) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 p_abort.check_e();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 if (p_writeable) FlushFileBuffers(m_handle);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 SetLastError(ERROR_SUCCESS);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 FILETIME temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 if (!GetFileTime(m_handle,0,0,&temp)) exception_io_from_win32(GetLastError());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 return file_win32_helpers::make_uint64(temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 bool is_remote() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 static file::ptr g_CreateFile(const char * p_path,DWORD p_access,DWORD p_sharemode,LPSECURITY_ATTRIBUTES p_security_attributes,DWORD p_createmode,DWORD p_flags,HANDLE p_template) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 auto pathW = pfc::wideFromUTF8(p_path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 p_flags |= FILE_FLAG_OVERLAPPED;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 SetLastError(NO_ERROR);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 HANDLE handle = CreateFile(pathW,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 if (handle == INVALID_HANDLE_VALUE) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 const DWORD code = GetLastError();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 if (p_access & GENERIC_WRITE) win32_file_write_failure(code, p_path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 else exception_io_from_win32(code);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 return g_create_from_handle(handle, std::move(pathW));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 } catch(...) {CloseHandle(handle); throw;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 static file::ptr g_create_from_handle(HANDLE p_handle, pfc::wstringLite && path) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298 return new service_impl_t<self_t>(p_handle, std::move(path));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 static file::ptr g_create_from_handle(HANDLE p_handle) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 pfc::wstringLite blank;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 return g_create_from_handle(p_handle, std::move(blank));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 size_t lowLevelIO(const GUID & guid, size_t arg1, void * arg2, size_t arg2size, abort_callback & abort) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 return file_win32_helpers::lowLevelIO(m_handle, guid, arg1, arg2, arg2size, p_writeable, abort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 HANDLE m_event, m_handle;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 t_filesize m_position = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 pfc::wstringLite m_path;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 #endif // _WIN32