00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "Poco/File_WIN32U.h"
00038 #include "Poco/Exception.h"
00039 #include "Poco/String.h"
00040 #include "Poco/UnicodeConverter.h"
00041 #include "Poco/UnWindows.h"
00042
00043
00044 namespace Poco {
00045
00046
00047 class FileHandle
00048 {
00049 public:
00050 FileHandle(const std::string& path, const std::wstring& upath, DWORD access, DWORD share, DWORD disp)
00051 {
00052 _h = CreateFileW(upath.c_str(), access, share, 0, disp, 0, 0);
00053 if (!_h) FileImpl::handleLastErrorImpl(path);
00054 }
00055
00056 ~FileHandle()
00057 {
00058 if (_h) CloseHandle(_h);
00059 }
00060
00061 HANDLE get() const
00062 {
00063 return _h;
00064 }
00065
00066 private:
00067 HANDLE _h;
00068 };
00069
00070
00071 FileImpl::FileImpl()
00072 {
00073 }
00074
00075
00076 FileImpl::FileImpl(const std::string& path): _path(path)
00077 {
00078 std::string::size_type n = _path.size();
00079 if (n > 1 && (_path[n - 1] == '\\' || _path[n - 1] == '/') && !((n == 3 && _path[1]==':')))
00080 {
00081 _path.resize(n - 1);
00082 }
00083 UnicodeConverter::toUTF16(_path, _upath);
00084 }
00085
00086
00087 FileImpl::~FileImpl()
00088 {
00089 }
00090
00091
00092 void FileImpl::swapImpl(FileImpl& file)
00093 {
00094 std::swap(_path, file._path);
00095 std::swap(_upath, file._upath);
00096 }
00097
00098
00099 void FileImpl::setPathImpl(const std::string& path)
00100 {
00101 _path = path;
00102 std::string::size_type n = _path.size();
00103 if (n > 1 && (_path[n - 1] == '\\' || _path[n - 1] == '/') && !((n == 3 && _path[1]==':')))
00104 {
00105 _path.resize(n - 1);
00106 }
00107 UnicodeConverter::toUTF16(_path, _upath);
00108 }
00109
00110
00111 bool FileImpl::existsImpl() const
00112 {
00113 poco_assert (!_path.empty());
00114
00115 DWORD attr = GetFileAttributesW(_upath.c_str());
00116 if (attr == 0xFFFFFFFF)
00117 {
00118 switch (GetLastError())
00119 {
00120 case ERROR_FILE_NOT_FOUND:
00121 case ERROR_PATH_NOT_FOUND:
00122 case ERROR_NOT_READY:
00123 case ERROR_INVALID_DRIVE:
00124 return false;
00125 default:
00126 handleLastErrorImpl(_path);
00127 }
00128 }
00129 return true;
00130 }
00131
00132
00133 bool FileImpl::canReadImpl() const
00134 {
00135 poco_assert (!_path.empty());
00136
00137 DWORD attr = GetFileAttributesW(_upath.c_str());
00138 if (attr == 0xFFFFFFFF)
00139 {
00140 switch (GetLastError())
00141 {
00142 case ERROR_ACCESS_DENIED:
00143 return false;
00144 default:
00145 handleLastErrorImpl(_path);
00146 }
00147 }
00148 return true;
00149 }
00150
00151
00152 bool FileImpl::canWriteImpl() const
00153 {
00154 poco_assert (!_path.empty());
00155
00156 DWORD attr = GetFileAttributesW(_upath.c_str());
00157 if (attr == 0xFFFFFFFF)
00158 handleLastErrorImpl(_path);
00159 return (attr & FILE_ATTRIBUTE_READONLY) == 0;
00160 }
00161
00162
00163 bool FileImpl::canExecuteImpl() const
00164 {
00165 Path p(_path);
00166 return icompare(p.getExtension(), "exe") == 0;
00167 }
00168
00169
00170 bool FileImpl::isFileImpl() const
00171 {
00172 return !isDirectoryImpl() && !isDeviceImpl();
00173 }
00174
00175
00176 bool FileImpl::isDirectoryImpl() const
00177 {
00178 poco_assert (!_path.empty());
00179
00180 DWORD attr = GetFileAttributesW(_upath.c_str());
00181 if (attr == 0xFFFFFFFF)
00182 handleLastErrorImpl(_path);
00183 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
00184 }
00185
00186
00187 bool FileImpl::isLinkImpl() const
00188 {
00189 return false;
00190 }
00191
00192
00193 bool FileImpl::isDeviceImpl() const
00194 {
00195 poco_assert (!_path.empty());
00196
00197 FileHandle fh(_path, _upath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
00198 DWORD type = GetFileType(fh.get());
00199 if (type == FILE_TYPE_CHAR)
00200 return true;
00201 else if (type == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR)
00202 handleLastErrorImpl(_path);
00203 return false;
00204 }
00205
00206
00207 bool FileImpl::isHiddenImpl() const
00208 {
00209 poco_assert (!_path.empty());
00210
00211 DWORD attr = GetFileAttributesW(_upath.c_str());
00212 if (attr == 0xFFFFFFFF)
00213 handleLastErrorImpl(_path);
00214 return (attr & FILE_ATTRIBUTE_HIDDEN) != 0;
00215 }
00216
00217
00218 Timestamp FileImpl::createdImpl() const
00219 {
00220 poco_assert (!_path.empty());
00221
00222 WIN32_FILE_ATTRIBUTE_DATA fad;
00223 if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0)
00224 handleLastErrorImpl(_path);
00225 return Timestamp::fromFileTimeNP(fad.ftCreationTime.dwLowDateTime, fad.ftCreationTime.dwHighDateTime);
00226 }
00227
00228
00229 Timestamp FileImpl::getLastModifiedImpl() const
00230 {
00231 poco_assert (!_path.empty());
00232
00233 WIN32_FILE_ATTRIBUTE_DATA fad;
00234 if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0)
00235 handleLastErrorImpl(_path);
00236 return Timestamp::fromFileTimeNP(fad.ftLastWriteTime.dwLowDateTime, fad.ftLastWriteTime.dwHighDateTime);
00237 }
00238
00239
00240 void FileImpl::setLastModifiedImpl(const Timestamp& ts)
00241 {
00242 poco_assert (!_path.empty());
00243
00244 UInt32 low;
00245 UInt32 high;
00246 ts.toFileTimeNP(low, high);
00247 FILETIME ft;
00248 ft.dwLowDateTime = low;
00249 ft.dwHighDateTime = high;
00250 FileHandle fh(_path, _upath, FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
00251 if (SetFileTime(fh.get(), 0, &ft, &ft) == 0)
00252 handleLastErrorImpl(_path);
00253 }
00254
00255
00256 FileImpl::FileSizeImpl FileImpl::getSizeImpl() const
00257 {
00258 poco_assert (!_path.empty());
00259
00260 WIN32_FILE_ATTRIBUTE_DATA fad;
00261 if (GetFileAttributesExW(_upath.c_str(), GetFileExInfoStandard, &fad) == 0)
00262 handleLastErrorImpl(_path);
00263 LARGE_INTEGER li;
00264 li.LowPart = fad.nFileSizeLow;
00265 li.HighPart = fad.nFileSizeHigh;
00266 return li.QuadPart;
00267 }
00268
00269
00270 void FileImpl::setSizeImpl(FileSizeImpl size)
00271 {
00272 poco_assert (!_path.empty());
00273
00274 FileHandle fh(_path, _upath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
00275 LARGE_INTEGER li;
00276 li.QuadPart = size;
00277 if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1)
00278 handleLastErrorImpl(_path);
00279 if (SetEndOfFile(fh.get()) == 0)
00280 handleLastErrorImpl(_path);
00281 }
00282
00283
00284 void FileImpl::setWriteableImpl(bool flag)
00285 {
00286 poco_assert (!_path.empty());
00287
00288 DWORD attr = GetFileAttributesW(_upath.c_str());
00289 if (attr == -1)
00290 handleLastErrorImpl(_path);
00291 if (flag)
00292 attr &= ~FILE_ATTRIBUTE_READONLY;
00293 else
00294 attr |= FILE_ATTRIBUTE_READONLY;
00295 if (SetFileAttributesW(_upath.c_str(), attr) == 0)
00296 handleLastErrorImpl(_path);
00297 }
00298
00299
00300 void FileImpl::setExecutableImpl(bool flag)
00301 {
00302
00303 }
00304
00305
00306 void FileImpl::copyToImpl(const std::string& path) const
00307 {
00308 poco_assert (!_path.empty());
00309
00310 std::wstring upath;
00311 UnicodeConverter::toUTF16(path, upath);
00312 if (CopyFileW(_upath.c_str(), upath.c_str(), FALSE) != 0)
00313 {
00314 FileImpl copy(path);
00315 copy.setWriteableImpl(true);
00316 }
00317 else handleLastErrorImpl(_path);
00318 }
00319
00320
00321 void FileImpl::renameToImpl(const std::string& path)
00322 {
00323 poco_assert (!_path.empty());
00324
00325 std::wstring upath;
00326 UnicodeConverter::toUTF16(path, upath);
00327 if (MoveFileW(_upath.c_str(), upath.c_str()) == 0)
00328 handleLastErrorImpl(_path);
00329 }
00330
00331
00332 void FileImpl::removeImpl()
00333 {
00334 poco_assert (!_path.empty());
00335
00336 if (isDirectoryImpl())
00337 {
00338 if (RemoveDirectoryW(_upath.c_str()) == 0)
00339 handleLastErrorImpl(_path);
00340 }
00341 else
00342 {
00343 if (DeleteFileW(_upath.c_str()) == 0)
00344 handleLastErrorImpl(_path);
00345 }
00346 }
00347
00348
00349 bool FileImpl::createFileImpl()
00350 {
00351 poco_assert (!_path.empty());
00352
00353 HANDLE hFile = CreateFileW(_upath.c_str(), GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
00354 if (hFile != INVALID_HANDLE_VALUE)
00355 {
00356 CloseHandle(hFile);
00357 return true;
00358 }
00359 else if (GetLastError() == ERROR_FILE_EXISTS)
00360 return false;
00361 else
00362 handleLastErrorImpl(_path);
00363 return false;
00364 }
00365
00366
00367 bool FileImpl::createDirectoryImpl()
00368 {
00369 poco_assert (!_path.empty());
00370
00371 if (existsImpl() && isDirectoryImpl())
00372 return false;
00373 if (CreateDirectoryW(_upath.c_str(), 0) == 0)
00374 handleLastErrorImpl(_path);
00375 return true;
00376 }
00377
00378
00379 void FileImpl::handleLastErrorImpl(const std::string& path)
00380 {
00381 switch (GetLastError())
00382 {
00383 case ERROR_FILE_NOT_FOUND:
00384 throw FileNotFoundException(path);
00385 case ERROR_PATH_NOT_FOUND:
00386 case ERROR_BAD_NETPATH:
00387 case ERROR_CANT_RESOLVE_FILENAME:
00388 case ERROR_INVALID_DRIVE:
00389 throw PathNotFoundException(path);
00390 case ERROR_ACCESS_DENIED:
00391 throw FileAccessDeniedException(path);
00392 case ERROR_ALREADY_EXISTS:
00393 case ERROR_FILE_EXISTS:
00394 throw FileExistsException(path);
00395 case ERROR_INVALID_NAME:
00396 case ERROR_DIRECTORY:
00397 case ERROR_FILENAME_EXCED_RANGE:
00398 case ERROR_BAD_PATHNAME:
00399 throw PathSyntaxException(path);
00400 case ERROR_FILE_READ_ONLY:
00401 throw FileReadOnlyException(path);
00402 case ERROR_CANNOT_MAKE:
00403 throw CreateFileException(path);
00404 case ERROR_DIR_NOT_EMPTY:
00405 throw FileException("directory not empty", path);
00406 case ERROR_WRITE_FAULT:
00407 throw WriteFileException(path);
00408 case ERROR_READ_FAULT:
00409 throw ReadFileException(path);
00410 case ERROR_SHARING_VIOLATION:
00411 throw FileException("sharing violation", path);
00412 case ERROR_LOCK_VIOLATION:
00413 throw FileException("lock violation", path);
00414 case ERROR_HANDLE_EOF:
00415 throw ReadFileException("EOF reached", path);
00416 case ERROR_HANDLE_DISK_FULL:
00417 case ERROR_DISK_FULL:
00418 throw WriteFileException("disk is full", path);
00419 case ERROR_NEGATIVE_SEEK:
00420 throw FileException("negative seek", path);
00421 default:
00422 throw FileException(path);
00423 }
00424 }
00425
00426
00427 }