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; Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -81,10 +81,14 @@ extern struct Stret OFForward_stret(id, SEL, ...); #else # define OFForward OFMethodNotFound # define OFForward_stret OFMethodNotFound_stret #endif + +#ifdef OF_WINDOWS +static BOOLEAN NTAPI (*RtlGenRandomFuncPtr)(PVOID, ULONG); +#endif struct PreIvars { #ifdef OF_MSDOS ptrdiff_t offset; #endif @@ -190,15 +194,27 @@ free((void *)((uintptr_t)ptr - offset)); } #endif -#if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_GETRANDOM) +#if (!defined(HAVE_ARC4RANDOM) && !defined(HAVE_GETRANDOM)) || \ + defined(OF_WINDOWS) +static OFOnceControl randomOnceControl = OFOnceControlInitValue; + static void initRandom(void) { struct timeval tv; + +# ifdef OF_WINDOWS + HANDLE handle; + + if ((handle = GetModuleHandleA("advapi32.dll")) != NULL && + (RtlGenRandomFuncPtr = (BOOLEAN NTAPI (*)(PVOID, ULONG)) + GetProcAddress(handle, "SystemFunction036")) != NULL) + return; +# endif # ifdef HAVE_RANDOM gettimeofday(&tv, NULL); srandom((unsigned)(tv.tv_sec ^ tv.tv_usec)); # else @@ -218,12 +234,20 @@ OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); return buffer; #else - static OFOnceControl onceControl = OFOnceControlInitValue; - OFOnce(&onceControl, initRandom); + OFOnce(&randomOnceControl, initRandom); + +# ifdef OF_WINDOWS + if (RtlGenRandomFuncPtr != NULL) { + uint16_t buffer; + OFEnsure(RtlGenRandomFuncPtr(&buffer, sizeof(buffer))); + return buffer; + } +# endif + # ifdef HAVE_RANDOM return random() & 0xFFFF; # else return rand() & 0xFFFF; # endif @@ -240,10 +264,20 @@ OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); return buffer; #else +# ifdef OF_WINDOWS + OFOnce(&randomOnceControl, initRandom); + + if (RtlGenRandomFuncPtr != NULL) { + uint32_t buffer; + OFEnsure(RtlGenRandomFuncPtr(&buffer, sizeof(buffer))); + return buffer; + } +# endif + return ((uint32_t)OFRandom16() << 16) | OFRandom16(); #endif } uint64_t @@ -260,10 +294,20 @@ OFEnsure(getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)); return buffer; #else +# ifdef OF_WINDOWS + OFOnce(&randomOnceControl, initRandom); + + if (RtlGenRandomFuncPtr != NULL) { + uint64_t buffer; + OFEnsure(RtlGenRandomFuncPtr(&buffer, sizeof(buffer))); + return buffer; + } +# endif + return ((uint64_t)OFRandom32() << 32) | OFRandom32(); #endif } void