Index: src/OFFileIRIHandler.m ================================================================== --- src/OFFileIRIHandler.m +++ src/OFFileIRIHandler.m @@ -43,13 +43,10 @@ # include #endif #ifdef OF_HAIKU # include #endif -#ifdef OF_WINDOWS -# include -#endif #ifdef OF_DJGPP # include #endif #ifdef HAVE_FCNTL_H @@ -149,11 +146,10 @@ [readdirMutex release]; } #endif #ifdef OF_WINDOWS -static int (*_wutime64FuncPtr)(const wchar_t *, struct __utimbuf64 *); static WINAPI BOOLEAN (*createSymbolicLinkWFuncPtr)(LPCWSTR, LPCWSTR, DWORD); static WINAPI BOOLEAN (*createHardLinkWFuncPtr)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); #endif @@ -167,10 +163,23 @@ filetimeToTimeInterval(const FILETIME *filetime) { return (double)((int64_t)filetime->dwHighDateTime << 32 | filetime->dwLowDateTime) / 10000000.0 - 11644473600.0; } + +static FILETIME +timeIntervalToFiletime(OFTimeInterval timeInterval) +{ + uint64_t timestamp = + (uint64_t)((timeInterval + 11644473600.0) * 10000000.0); + FILETIME filetime = { + .dwHighDateTime = timestamp >> 32, + .dwLowDateTime = timestamp & 0xFFFFFFFF + }; + + return filetime; +} static int lastError(void) { switch (GetLastError()) { @@ -779,14 +788,10 @@ readdirMutex = [[OFMutex alloc] init]; atexit(releaseReaddirMutex); #endif #ifdef OF_WINDOWS - if ((module = GetModuleHandle("msvcrt.dll")) != NULL) - _wutime64FuncPtr = (int (*)(const wchar_t *, - struct __utimbuf64 *))GetProcAddress(module, "_wutime64"); - if ((module = GetModuleHandleA("kernel32.dll")) != NULL) { createSymbolicLinkWFuncPtr = (WINAPI BOOLEAN (*)(LPCWSTR, LPCWSTR, DWORD)) GetProcAddress(module, "CreateSymbolicLinkW"); createHardLinkWFuncPtr = @@ -897,58 +902,46 @@ lastAccessDate = modificationDate; if (modificationDate == nil) modificationDate = lastAccessDate; #if defined(OF_WINDOWS) - if (_wutime64FuncPtr != NULL) { - struct __utimbuf64 times = { - .actime = - (__time64_t)lastAccessDate.timeIntervalSince1970, - .modtime = - (__time64_t)modificationDate.timeIntervalSince1970 - }; - - if (_wutime64FuncPtr([path UTF16String], ×) != 0) { - int errNo = errno; - - if (errNo == EACCES && [self directoryExistsAtIRI: IRI]) - errNo = EISDIR; - - @throw [OFSetItemAttributesFailedException - exceptionWithIRI: IRI - attributes: attributes - failedAttribute: attributeKey - errNo: errNo]; - } - } else { - struct _utimbuf times = { - .actime = (time_t)lastAccessDate.timeIntervalSince1970, - .modtime = - (time_t)modificationDate.timeIntervalSince1970 - }; - int status; - - if ([OFSystemInfo isWindowsNT]) - status = _wutime([path UTF16String], ×); - else - status = _utime( - [path cStringWithEncoding: [OFLocale encoding]], - ×); - - if (status != 0) { - int errNo = errno; - - if (errNo == EACCES && [self directoryExistsAtIRI: IRI]) - errNo = EISDIR; - - @throw [OFSetItemAttributesFailedException - exceptionWithIRI: IRI - attributes: attributes - failedAttribute: attributeKey - errNo: errNo]; - } - } + FILETIME accessTime = timeIntervalToFiletime( + lastAccessDate.timeIntervalSince1970); + FILETIME modificationTime = timeIntervalToFiletime( + modificationDate.timeIntervalSince1970); + HANDLE handle; + + if ([OFSystemInfo isWindowsNT]) + handle = CreateFileW(path.UTF16String, FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + else + handle = CreateFileA( + [path cStringWithEncoding: [OFLocale encoding]], + FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (handle == NULL) + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: lastError()]; + + if (!SetFileTime(handle, NULL, &accessTime, &modificationTime)) { + int errNo = lastError(); + + CloseHandle(handle); + + @throw [OFSetItemAttributesFailedException + exceptionWithIRI: IRI + attributes: attributes + failedAttribute: attributeKey + errNo: errNo]; + } + + CloseHandle(handle); #elif defined(OF_AMIGAOS) /* AmigaOS does not support access time. */ OFTimeInterval modificationTime = modificationDate.timeIntervalSince1970; struct Locale *locale;