diff --git a/CMakeLists.txt b/CMakeLists.txt index f40d04ab..ce086f4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -483,7 +483,6 @@ endif() target_link_libraries(uv_a ${uv_libraries}) set_target_properties(uv_a PROPERTIES OUTPUT_NAME "uv") if(WIN32) - target_link_libraries(uv_a ntdll) set_target_properties(uv_a PROPERTIES PREFIX "lib") endif() diff --git a/src/win/fs.c b/src/win/fs.c index b1379084..2f85ca2c 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -35,7 +35,6 @@ /* requires , included via "uv.h" above, but needs to be included before our "winapi.h", included via "internal.h" below. */ #include -#include #include "internal.h" #include "req-inl.h" @@ -674,13 +673,13 @@ void fs__openat(uv_fs_t* req) { /* convert flags and mode to CreateFile parameters */ switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) { case UV_FS_O_RDONLY: - access = FILE_GENERIC_READ; + access = GENERIC_READ; break; case UV_FS_O_WRONLY: - access = FILE_GENERIC_WRITE; + access = GENERIC_WRITE; break; case UV_FS_O_RDWR: - access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; + access = GENERIC_READ | GENERIC_WRITE; break; default: goto einval; @@ -710,21 +709,21 @@ void fs__openat(uv_fs_t* req) { switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) { case 0: case UV_FS_O_EXCL: - disposition = OPEN_EXISTING; + disposition = FILE_OPEN; break; case UV_FS_O_CREAT: - disposition = OPEN_ALWAYS; + disposition = FILE_OPEN_IF; break; case UV_FS_O_CREAT | UV_FS_O_EXCL: case UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL: - disposition = CREATE_NEW; + disposition = FILE_CREATE; break; case UV_FS_O_TRUNC: case UV_FS_O_TRUNC | UV_FS_O_EXCL: - disposition = TRUNCATE_EXISTING; + disposition = FILE_OVERWRITE; break; case UV_FS_O_CREAT | UV_FS_O_TRUNC: - disposition = CREATE_ALWAYS; + disposition = FILE_SUPERSEDE; break; default: goto einval; @@ -738,7 +737,8 @@ void fs__openat(uv_fs_t* req) { } if (flags & UV_FS_O_TEMPORARY ) { - attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY; + options |= FILE_DELETE_ON_CLOSE; + attributes |= FILE_ATTRIBUTE_TEMPORARY; access |= DELETE; } @@ -750,10 +750,10 @@ void fs__openat(uv_fs_t* req) { case 0: break; case UV_FS_O_SEQUENTIAL: - attributes |= FILE_FLAG_SEQUENTIAL_SCAN; + options |= FILE_SEQUENTIAL_ONLY; break; case UV_FS_O_RANDOM: - attributes |= FILE_FLAG_RANDOM_ACCESS; + options |= FILE_RANDOM_ACCESS; break; default: goto einval; @@ -787,7 +787,7 @@ void fs__openat(uv_fs_t* req) { goto einval; } } - attributes |= FILE_FLAG_NO_BUFFERING; + options |= FILE_NO_INTERMEDIATE_BUFFERING; } switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) { @@ -795,36 +795,46 @@ void fs__openat(uv_fs_t* req) { break; case UV_FS_O_DSYNC: case UV_FS_O_SYNC: - attributes |= FILE_FLAG_WRITE_THROUGH; + options |= FILE_WRITE_THROUGH; break; default: goto einval; } - /* Setting this flag makes it possible to open a directory. */ - attributes |= FILE_FLAG_BACKUP_SEMANTICS; if (flags & UV_FS_O_DIRECTORY) { + /* Setting this flag makes it possible to open a directory. */ + options |= FILE_OPEN_FOR_BACKUP_INTENT; options |= FILE_DIRECTORY_FILE; } - RtlInitUnicodeString(&str, req->file.pathw); - InitializeObjectAttributes(&obj, &str, OBJ_CASE_INSENSITIVE, NULL, NULL); + HMODULE ntdll = GetModuleHandle("ntdll.dll"); + RtlInitUnicodeString _RtlInitUnicodeString = + (RtlInitUnicodeString) GetProcAddress(ntdll, "RtlInitUnicodeString"); + NtCreateFile _NtCreateFile = + (NtCreateFile) GetProcAddress(ntdll, "NtCreateFile"); - NTSTATUS status = NtCreateFile(&file, - access, - &obj, - &isb, - 0, - attributes, - share, - disposition, - options, - NULL, - 0); + _RtlInitUnicodeString(&str, req->file.pathw); + InitializeObjectAttributes(&obj, + &str, + OBJ_CASE_INSENSITIVE, + req->fs.info.hFile_out, + NULL); + + NTSTATUS status = _NtCreateFile(&file, + access, + &obj, + &isb, + 0, + attributes, + share, + disposition, + options, + NULL, + 0); if (!NT_SUCCESS(status)) { - if (file == INVALID_HANDLE_VALUE) { - ULONG error = RtlNtStatusToDosError(status); + ULONG error = pRtlNtStatusToDosError(status); + if ((isb.Information & FILE_EXISTS != 0) && (flags & UV_FS_O_CREAT) && !(flags & UV_FS_O_EXCL)) { /* Special case: when FILE_EXISTS happens and UV_FS_O_CREAT was @@ -3043,6 +3053,7 @@ static void uv__fs_work(struct uv__work* w) { #define XX(uc, lc) case UV_FS_##uc: fs__##lc(req); break; switch (req->fs_type) { XX(OPEN, open) + XX(OPENAT, openat) XX(CLOSE, close) XX(READ, read) XX(WRITE, write) @@ -3164,7 +3175,7 @@ int uv_fs_openat(uv_loop_t* loop, return req->result; } - req->file.hFile = handle; + req->fs.info.hFile_out = handle; req->fs.info.file_flags = flags; req->fs.info.mode = mode; POST0; diff --git a/src/win/winapi.h b/src/win/winapi.h index d380bda4..3aab5c7d 100644 --- a/src/win/winapi.h +++ b/src/win/winapi.h @@ -4108,10 +4108,7 @@ # define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002 #endif -/* from winternl.h */ -#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32__) -#define __UNICODE_STRING_DEFINED -#endif +/* from ntdef.h */ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; @@ -4119,6 +4116,52 @@ typedef struct _UNICODE_STRING { } UNICODE_STRING, *PUNICODE_STRING; typedef const UNICODE_STRING *PCUNICODE_STRING; +#ifndef _OBJECT_ATTRIBUTES +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; +#endif + + +#ifndef FILE_DIRECTORY_FILE +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_FOR_RECOVERY 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#define FILE_OPEN_NO_RECALL 0x00400000 +#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000 +#endif + +#ifndef OBJ_CASE_INSENSITIVE +#define OBJ_CASE_INSENSITIVE 0x00000040 +#endif + +#ifndef FILE_EXISTS +#define FILE_EXISTS 0x00000004 +#endif + +#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32__) +#define __UNICODE_STRING_DEFINED +#endif /* from ntifs.h */ #ifndef DEVICE_TYPE @@ -4168,6 +4211,7 @@ typedef struct _IO_STATUS_BLOCK { ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + typedef enum _FILE_INFORMATION_CLASS { FileDirectoryInformation = 1, FileFullDirectoryInformation, @@ -4707,6 +4751,14 @@ typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification) HANDLE Recipient, _PHPOWERNOTIFY RegistrationHandle); + +/* from wdm.h */ +typedef VOID (NTAPI *RtlInitUnicodeString)( + PUNICODE_STRING DestinationString, + __drv_aliasesMem PCWSTR SourceString +); + + /* from Winuser.h */ typedef VOID (CALLBACK* WINEVENTPROC) (HWINEVENTHOOK hWinEventHook, @@ -4766,4 +4818,44 @@ typedef int (WINAPI *uv_sGetHostNameW) int); extern uv_sGetHostNameW pGetHostNameW; + +/* from winternl.h */ +typedef NTSTATUS (__stdcall *NtCreateFile)( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength +); + +/* from ntdef.h */ +#ifndef InitializeObjectAttributes +#define InitializeObjectAttributes( p, n, a, r, s ) { \ + (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ + (p)->RootDirectory = r; \ + (p)->Attributes = a; \ + (p)->ObjectName = n; \ + (p)->SecurityDescriptor = s; \ + (p)->SecurityQualityOfService = NULL; \ + } +#endif + +// NtCreateFile CreateDisposition +#ifndef FILE_SUPERSEDE +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 +#define FILE_MAXIMUM_DISPOSITION 0x00000005 +#endif + + #endif /* UV_WIN_WINAPI_H_ */