foobar2000 SDK  2015-08-03
file_win32_wrapper.h
Go to the documentation of this file.
1 namespace file_win32_helpers {
2  t_filesize get_size(HANDLE p_handle);
3  void seek(HANDLE p_handle,t_sfilesize p_position,file::t_seek_mode p_mode);
4  void fillOverlapped(OVERLAPPED & ol, HANDLE myEvent, t_filesize s);
5  void writeOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, const void * in,DWORD inBytes, abort_callback & abort);
6  void writeOverlapped(HANDLE handle, HANDLE myEvent, t_filesize & position, const void * in, size_t inBytes, abort_callback & abort);
7  void writeStreamOverlapped(HANDLE handle, HANDLE myEvent, const void * in, size_t inBytes, abort_callback & abort);
8  DWORD readOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, void * out, DWORD outBytes, abort_callback & abort);
9  size_t readOverlapped(HANDLE handle, HANDLE myEvent, t_filesize & position, void * out, size_t outBytes, abort_callback & abort);
10  size_t readStreamOverlapped(HANDLE handle, HANDLE myEvent, void * out, size_t outBytes, abort_callback & abort);
11  HANDLE createFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, abort_callback & abort);
12 };
13 
14 template<bool p_seekable,bool p_writeable>
15 class file_win32_wrapper_t : public file {
16 public:
17  file_win32_wrapper_t(HANDLE p_handle) : m_handle(p_handle), m_position(0)
18  {
19  }
20 
21  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) {
22  SetLastError(NO_ERROR);
23  HANDLE handle = uCreateFile(p_path,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template);
24  if (handle == INVALID_HANDLE_VALUE) {
25  const DWORD code = GetLastError();
26  if (p_access & GENERIC_WRITE) win32_file_write_failure(code, p_path);
27  else exception_io_from_win32(code);
28  }
29  try {
30  return g_create_from_handle(handle);
31  } catch(...) {CloseHandle(handle); throw;}
32  }
33 
36  }
37 
38 
39  void reopen(abort_callback & p_abort) {seek(0,p_abort);}
40 
41  void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
42  if (!p_writeable) throw exception_io_denied();
43 
44  PFC_STATIC_ASSERT(sizeof(t_size) >= sizeof(DWORD));
45 
46  t_size bytes_written_total = 0;
47 
48  if (sizeof(t_size) == sizeof(DWORD)) {
49  p_abort.check_e();
50  DWORD bytes_written = 0;
51  SetLastError(ERROR_SUCCESS);
52  if (!WriteFile(m_handle,p_buffer,(DWORD)p_bytes,&bytes_written,0)) exception_io_from_win32(GetLastError());
53  if (bytes_written != p_bytes) throw exception_io("Write failure");
54  bytes_written_total = bytes_written;
55  m_position += bytes_written;
56  } else {
57  while(bytes_written_total < p_bytes) {
58  p_abort.check_e();
59  DWORD bytes_written = 0;
60  DWORD delta = (DWORD) pfc::min_t<t_size>(p_bytes - bytes_written_total, 0x80000000);
61  SetLastError(ERROR_SUCCESS);
62  if (!WriteFile(m_handle,(const t_uint8*)p_buffer + bytes_written_total,delta,&bytes_written,0)) exception_io_from_win32(GetLastError());
63  if (bytes_written != delta) throw exception_io("Write failure");
64  bytes_written_total += bytes_written;
65  m_position += bytes_written;
66  }
67  }
68  }
69 
70  t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
71  PFC_STATIC_ASSERT(sizeof(t_size) >= sizeof(DWORD));
72 
73  t_size bytes_read_total = 0;
74  if (sizeof(t_size) == sizeof(DWORD)) {
75  p_abort.check_e();
76  DWORD bytes_read = 0;
77  SetLastError(ERROR_SUCCESS);
78  if (!ReadFile(m_handle,p_buffer,pfc::downcast_guarded<DWORD>(p_bytes),&bytes_read,0)) exception_io_from_win32(GetLastError());
79  bytes_read_total = bytes_read;
80  m_position += bytes_read;
81  } else {
82  while(bytes_read_total < p_bytes) {
83  p_abort.check_e();
84  DWORD bytes_read = 0;
85  DWORD delta = (DWORD) pfc::min_t<t_size>(p_bytes - bytes_read_total, 0x80000000);
86  SetLastError(ERROR_SUCCESS);
87  if (!ReadFile(m_handle,(t_uint8*)p_buffer + bytes_read_total,delta,&bytes_read,0)) exception_io_from_win32(GetLastError());
88  bytes_read_total += bytes_read;
89  m_position += bytes_read;
90  if (bytes_read != delta) break;
91  }
92  }
93  return bytes_read_total;
94  }
95 
96 
98  p_abort.check_e();
99  return file_win32_helpers::get_size(m_handle);
100  }
101 
103  p_abort.check_e();
104  return m_position;
105  }
106 
107  void resize(t_filesize p_size,abort_callback & p_abort) {
108  if (!p_writeable) throw exception_io_denied();
109  p_abort.check_e();
110  if (m_position != p_size) {
111  file_win32_helpers::seek(m_handle,p_size,file::seek_from_beginning);
112  }
113  SetLastError(ERROR_SUCCESS);
114  if (!SetEndOfFile(m_handle)) {
115  DWORD code = GetLastError();
116  if (m_position != p_size) try {file_win32_helpers::seek(m_handle,m_position,file::seek_from_beginning);} catch(...) {}
118  }
119  if (m_position > p_size) m_position = p_size;
120  if (m_position != p_size) file_win32_helpers::seek(m_handle,m_position,file::seek_from_beginning);
121  }
122 
123 
124  void seek(t_filesize p_position,abort_callback & p_abort) {
125  if (!p_seekable) throw exception_io_object_not_seekable();
126  p_abort.check_e();
127  if (p_position > file_win32_helpers::get_size(m_handle)) throw exception_io_seek_out_of_range();
128  file_win32_helpers::seek(m_handle,p_position,file::seek_from_beginning);
129  m_position = p_position;
130  }
131 
132  bool can_seek() {return p_seekable;}
133  bool get_content_type(pfc::string_base & out) {return false;}
134  bool is_in_memory() {return false;}
135  void on_idle(abort_callback & p_abort) {p_abort.check_e();}
136 
138  p_abort.check_e();
139  FlushFileBuffers(m_handle);
140  SetLastError(ERROR_SUCCESS);
141  t_filetimestamp temp;
142  if (!GetFileTime(m_handle,0,0,(FILETIME*)&temp)) exception_io_from_win32(GetLastError());
143  return temp;
144  }
145 
146  bool is_remote() {return false;}
147  ~file_win32_wrapper_t() {CloseHandle(m_handle);}
148 protected:
151 };
152 
153 template<bool p_writeable>
155 public:
156  file_win32_wrapper_overlapped_t(HANDLE file) : m_handle(file), m_position() {
157  WIN32_OP( (m_event = CreateEvent(NULL, TRUE, FALSE, NULL)) != NULL );
158  }
159  ~file_win32_wrapper_overlapped_t() {CloseHandle(m_event); CloseHandle(m_handle);}
160  void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
161  if (!p_writeable) throw exception_io_denied();
162  return file_win32_helpers::writeOverlapped(m_handle, m_event, m_position, p_buffer, p_bytes, p_abort);
163  }
164  t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
165  return file_win32_helpers::readOverlapped(m_handle, m_event, m_position, p_buffer, p_bytes, p_abort);
166  }
167 
168  void reopen(abort_callback & p_abort) {seek(0,p_abort);}
169 
170 
172  p_abort.check_e();
173  return file_win32_helpers::get_size(m_handle);
174  }
175 
177  p_abort.check_e();
178  return m_position;
179  }
180 
181  void resize(t_filesize p_size,abort_callback & p_abort) {
182  if (!p_writeable) throw exception_io_denied();
183  p_abort.check_e();
184  file_win32_helpers::seek(m_handle,p_size,file::seek_from_beginning);
185  SetLastError(ERROR_SUCCESS);
186  if (!SetEndOfFile(m_handle)) {
187  DWORD code = GetLastError();
189  }
190  if (m_position > p_size) m_position = p_size;
191  }
192 
193 
194  void seek(t_filesize p_position,abort_callback & p_abort) {
195  p_abort.check_e();
196  if (p_position > file_win32_helpers::get_size(m_handle)) throw exception_io_seek_out_of_range();
197  // file_win32_helpers::seek(m_handle,p_position,file::seek_from_beginning);
198  m_position = p_position;
199  }
200 
201  bool can_seek() {return true;}
202  bool get_content_type(pfc::string_base & out) {return false;}
203  bool is_in_memory() {return false;}
204  void on_idle(abort_callback & p_abort) {p_abort.check_e();}
205 
207  p_abort.check_e();
208  FlushFileBuffers(m_handle);
209  SetLastError(ERROR_SUCCESS);
210  t_filetimestamp temp;
211  if (!GetFileTime(m_handle,0,0,(FILETIME*)&temp)) exception_io_from_win32(GetLastError());
212  return temp;
213  }
214 
215  bool is_remote() {return false;}
216 
217 
218  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) {
219  p_flags |= FILE_FLAG_OVERLAPPED;
220  SetLastError(NO_ERROR);
221  HANDLE handle = uCreateFile(p_path,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template);
222  if (handle == INVALID_HANDLE_VALUE) {
223  const DWORD code = GetLastError();
224  if (p_access & GENERIC_WRITE) win32_file_write_failure(code, p_path);
225  else exception_io_from_win32(code);
226  }
227  try {
228  return g_create_from_handle(handle);
229  } catch(...) {CloseHandle(handle); throw;}
230  }
231 
232  static file::ptr g_create_from_handle(HANDLE p_handle) {
234  }
235 
236 protected:
237  HANDLE m_event, m_handle;
239 };
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)
t_filesize get_size(HANDLE p_handle)
void resize(t_filesize p_size, abort_callback &p_abort)
t_int64 t_sfilesize
Type used for file size related variables when a signed value is needed.
Definition: filesystem.h:10
uint8_t t_uint8
Definition: int_types.h:9
Template implementing reference-counting features of service_base. Intended for dynamic instantiation...
Definition: service_impl.h:4
t_filesize get_size(abort_callback &p_abort)
PFC_NORETURN void win32_file_write_failure(DWORD p_code, const char *path)
Definition: filesystem.cpp:765
void seek(HANDLE p_handle, t_sfilesize p_position, file::t_seek_mode p_mode)
t_filesize get_position(abort_callback &p_abort)
void seek(t_filesize p_position, abort_callback &p_abort)
PFC_NORETURN void exception_io_from_win32(DWORD p_code)
Definition: filesystem.cpp:773
void fillOverlapped(OVERLAPPED &ol, HANDLE myEvent, t_filesize s)
HANDLE SHARED_EXPORT uCreateFile(const char *p_path, DWORD p_access, DWORD p_sharemode, LPSECURITY_ATTRIBUTES p_security_attributes, DWORD p_createmode, DWORD p_flags, HANDLE p_template)
t_filetimestamp get_timestamp(abort_callback &p_abort)
void reopen(abort_callback &p_abort)
void writeOverlapped(HANDLE handle, HANDLE myEvent, t_filesize &position, const void *in, size_t inBytes, abort_callback &abort)
void seek(t_filesize p_position, abort_callback &p_abort)
t_filetimestamp get_timestamp(abort_callback &p_abort)
typedef HANDLE(WINAPI *pPowerCreateRequest_t)(__in void *Context)
t_size read(void *p_buffer, t_size p_bytes, abort_callback &p_abort)
void write(const void *p_buffer, t_size p_bytes, abort_callback &p_abort)
void resize(t_filesize p_size, abort_callback &p_abort)
t_size read(void *p_buffer, t_size p_bytes, abort_callback &p_abort)
static file::ptr g_create_from_handle(HANDLE p_handle)
t_filesize get_position(abort_callback &p_abort)
t_filesize get_size(abort_callback &p_abort)
size_t t_size
Definition: int_types.h:48
bool get_content_type(pfc::string_base &out)
DWORD readOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, void *out, DWORD outBytes, abort_callback &abort)
void on_idle(abort_callback &p_abort)
file_win32_wrapper_t(HANDLE p_handle)
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName)
Definition: pp-winapi.h:8
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)
void write(const void *p_buffer, t_size p_bytes, abort_callback &p_abort)
t_uint64 t_filetimestamp
Type used for file timestamp related variables. 64-bit value representing the number of 100-nanosecon...
Definition: filesystem.h:12
bool get_content_type(pfc::string_base &out)
void on_idle(abort_callback &p_abort)
t_uint64 t_filesize
Type used for file size related variables.
Definition: filesystem.h:8
size_t readStreamOverlapped(HANDLE handle, HANDLE myEvent, void *out, size_t outBytes, abort_callback &abort)
size_t readOverlapped(HANDLE handle, HANDLE myEvent, t_filesize &position, void *out, size_t outBytes, abort_callback &abort)
HANDLE createFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, abort_callback &abort)
void writeOverlappedPass(HANDLE handle, HANDLE myEvent, t_filesize position, const void *in, DWORD inBytes, abort_callback &abort)
static service_ptr_t< file > g_create_from_handle(HANDLE p_handle)
void reopen(abort_callback &p_abort)
void writeStreamOverlapped(HANDLE handle, HANDLE myEvent, const void *in, size_t inBytes, abort_callback &abort)