00001 namespace file_win32_helpers {
00002 static t_filesize get_size(HANDLE p_handle) {
00003 union {
00004 t_uint64 val64;
00005 t_uint32 val32[2];
00006 } u;
00007
00008 u.val64 = 0;
00009 SetLastError(NO_ERROR);
00010 u.val32[0] = GetFileSize(p_handle,reinterpret_cast<DWORD*>(&u.val32[1]));
00011 if (GetLastError()!=NO_ERROR) exception_io_from_win32(GetLastError());
00012 return u.val64;
00013 }
00014 static void seek(HANDLE p_handle,t_sfilesize p_position,file::t_seek_mode p_mode) {
00015 union {
00016 t_int64 temp64;
00017 struct {
00018 DWORD temp_lo;
00019 LONG temp_hi;
00020 };
00021 };
00022
00023 temp64 = p_position;
00024 SetLastError(ERROR_SUCCESS);
00025 temp_lo = SetFilePointer(p_handle,temp_lo,&temp_hi,(DWORD)p_mode);
00026 if (GetLastError() != ERROR_SUCCESS) exception_io_from_win32(GetLastError());
00027 }
00028 }
00029
00030 template<bool p_seekable,bool p_writeable>
00031 class file_win32_wrapper_t : public file {
00032 public:
00033 file_win32_wrapper_t(HANDLE p_handle) : m_handle(p_handle), m_position(0)
00034 {
00035 }
00036
00037 static service_ptr_t<file> 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) {
00038 SetLastError(NO_ERROR);
00039 HANDLE handle = uCreateFile(p_path,p_access,p_sharemode,p_security_attributes,p_createmode,p_flags,p_template);
00040 if (handle == INVALID_HANDLE_VALUE) exception_io_from_win32(GetLastError());
00041 try {
00042 return g_create_from_handle(handle);
00043 } catch(...) {CloseHandle(handle); throw;}
00044 }
00045
00046 static service_ptr_t<file> g_create_from_handle(HANDLE p_handle) {
00047 return new service_impl_t<file_win32_wrapper_t<p_seekable,p_writeable> >(p_handle);
00048 }
00049
00050
00051 void reopen(abort_callback & p_abort) {seek(0,p_abort);}
00052
00053 void write(const void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
00054 if (!p_writeable) throw exception_io_denied();
00055
00056 pfc::static_assert_t< (sizeof(t_size) >= sizeof(DWORD)) >();
00057
00058 t_size bytes_written_total = 0;
00059
00060 if (sizeof(t_size) == sizeof(DWORD)) {
00061 p_abort.check_e();
00062 DWORD bytes_written = 0;
00063 SetLastError(ERROR_SUCCESS);
00064 if (!WriteFile(m_handle,p_buffer,(DWORD)p_bytes,&bytes_written,0)) exception_io_from_win32(GetLastError());
00065 if (bytes_written != p_bytes) throw exception_io("Write failure");
00066 bytes_written_total = bytes_written;
00067 m_position += bytes_written;
00068 } else {
00069 while(bytes_written_total < p_bytes) {
00070 p_abort.check_e();
00071 DWORD bytes_written = 0;
00072 DWORD delta = (DWORD) pfc::min_t<t_size>(p_bytes - bytes_written_total, 0x80000000);
00073 SetLastError(ERROR_SUCCESS);
00074 if (!WriteFile(m_handle,(const t_uint8*)p_buffer + bytes_written_total,delta,&bytes_written,0)) exception_io_from_win32(GetLastError());
00075 if (bytes_written != delta) throw exception_io("Write failure");
00076 bytes_written_total += bytes_written;
00077 m_position += bytes_written;
00078 }
00079 }
00080 }
00081
00082 t_size read(void * p_buffer,t_size p_bytes,abort_callback & p_abort) {
00083 pfc::static_assert_t< (sizeof(t_size) >= sizeof(DWORD)) >();
00084
00085 t_size bytes_read_total = 0;
00086 if (sizeof(t_size) == sizeof(DWORD)) {
00087 p_abort.check_e();
00088 DWORD bytes_read = 0;
00089 SetLastError(ERROR_SUCCESS);
00090 if (!ReadFile(m_handle,p_buffer,pfc::downcast_guarded<DWORD>(p_bytes),&bytes_read,0)) exception_io_from_win32(GetLastError());
00091 bytes_read_total = bytes_read;
00092 m_position += bytes_read;
00093 } else {
00094 while(bytes_read_total < p_bytes) {
00095 p_abort.check_e();
00096 DWORD bytes_read = 0;
00097 DWORD delta = (DWORD) pfc::min_t<t_size>(p_bytes - bytes_read_total, 0x80000000);
00098 SetLastError(ERROR_SUCCESS);
00099 if (!ReadFile(m_handle,(t_uint8*)p_buffer + bytes_read_total,delta,&bytes_read,0)) exception_io_from_win32(GetLastError());
00100 bytes_read_total += bytes_read;
00101 m_position += bytes_read;
00102 if (bytes_read != delta) break;
00103 }
00104 }
00105 return bytes_read_total;
00106 }
00107
00108
00109 t_filesize get_size(abort_callback & p_abort) {
00110 p_abort.check_e();
00111 return file_win32_helpers::get_size(m_handle);
00112 }
00113
00114 t_filesize get_position(abort_callback & p_abort) {
00115 p_abort.check_e();
00116 return m_position;
00117 }
00118
00119 void resize(t_filesize p_size,abort_callback & p_abort) {
00120 if (!p_writeable) throw exception_io_denied();
00121 p_abort.check_e();
00122 if (m_position != p_size) {
00123 file_win32_helpers::seek(m_handle,p_size,file::seek_from_beginning);
00124 }
00125 SetLastError(ERROR_SUCCESS);
00126 if (!SetEndOfFile(m_handle)) {
00127 DWORD code = GetLastError();
00128 if (m_position != p_size) try {file_win32_helpers::seek(m_handle,m_position,file::seek_from_beginning);} catch(...) {}
00129 exception_io_from_win32(code);
00130 }
00131 if (m_position > p_size) m_position = p_size;
00132 if (m_position != p_size) file_win32_helpers::seek(m_handle,m_position,file::seek_from_beginning);
00133 }
00134
00135 #if 0
00136 void set_eof(abort_callback & p_abort) {
00137 if (!p_writeable) throw exception_io_denied();
00138 p_abort.check_e();
00139
00140 SetLastError(ERROR_SUCCESS);
00141 if (!SetEndOfFile(m_handle)) exception_io_from_win32(GetLastError());
00142 }
00143 #endif
00144
00145 void seek(t_filesize p_position,abort_callback & p_abort) {
00146 if (!p_seekable) throw exception_io_object_not_seekable();
00147 p_abort.check_e();
00148 if (p_position > file_win32_helpers::get_size(m_handle)) throw exception_io_seek_out_of_range();
00149 file_win32_helpers::seek(m_handle,p_position,file::seek_from_beginning);
00150 m_position = p_position;
00151
00152 }
00153 #if 0
00154 void seek_ex(t_sfilesize p_position,file::t_seek_mode p_mode,abort_callback & p_abort) {
00155 if (!p_seekable) throw exception_io_object_not_seekable();
00156 p_abort.check_e();
00157
00158 file_win32_helpers::seek(m_handle,p_position,p_mode);
00159
00160 m_position = (t_filesize) temp64;
00161 }
00162 #endif
00163
00164 bool can_seek() {return p_seekable;}
00165 bool get_content_type(pfc::string_base & out) {return false;}
00166 bool is_in_memory() {return false;}
00167 void on_idle(abort_callback & p_abort) {p_abort.check_e();}
00168
00169 t_filetimestamp get_timestamp(abort_callback & p_abort) {
00170 p_abort.check_e();
00171 FlushFileBuffers(m_handle);
00172 SetLastError(ERROR_SUCCESS);
00173 t_filetimestamp temp;
00174 if (!GetFileTime(m_handle,0,0,(FILETIME*)&temp)) exception_io_from_win32(GetLastError());
00175 return temp;
00176 }
00177
00178 bool is_remote() {return false;}
00179 ~file_win32_wrapper_t() {CloseHandle(m_handle);}
00180 private:
00181 HANDLE m_handle;
00182 t_filesize m_position;
00183 };