From: Pierre Schweitzer Date: Wed, 23 Mar 2016 20:01:51 +0000 (+0000) Subject: [NTOSKRNL_VISTA] X-Git-Tag: ReactOS-0.4.1~188 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=bd24dc4921e55acd7a197a9aa240b7b296fbaa31;hp=8a1bed04bb15a6b7b4fa8d49874138d07069c5c7;ds=sidebyside [NTOSKRNL_VISTA] Introduce a new library dedicated to recent drivers: ntoskrnl_vista. Its purpose is to provide some Vista+ syscalls to drivers that would require them. Only 'simple' syscalls not depending on internal structures can land in this library (for the others, you're doomed ;-)). This library is to be statically linked to your driver. For the initial commit, the following syscalls have been implemented: - RtlUnicodeToUTF8N(), RtlUTF8ToUnicodeN(), taken from Wine trunk, implemented by Thomas - FsRtlRemoveDotsFromPath() implemented for the library These three are required by the WinBtrfs FS driver CORE-10892 svn path=/trunk/; revision=71036 --- diff --git a/reactos/lib/drivers/CMakeLists.txt b/reactos/lib/drivers/CMakeLists.txt index 538efc6f972..a65f6876f5c 100644 --- a/reactos/lib/drivers/CMakeLists.txt +++ b/reactos/lib/drivers/CMakeLists.txt @@ -5,4 +5,5 @@ add_subdirectory(hidparser) add_subdirectory(ip) add_subdirectory(libusb) add_subdirectory(lwip) +add_subdirectory(ntoskrnl_vista) add_subdirectory(sound) diff --git a/reactos/lib/drivers/ntoskrnl_vista/CMakeLists.txt b/reactos/lib/drivers/ntoskrnl_vista/CMakeLists.txt new file mode 100644 index 00000000000..05237020cf2 --- /dev/null +++ b/reactos/lib/drivers/ntoskrnl_vista/CMakeLists.txt @@ -0,0 +1,11 @@ +remove_definitions(-D_WIN32_WINNT=0x502) +add_definitions(-D_WIN32_WINNT=0x600) + +add_definitions(-DUNICODE -D_UNICODE) + +list(APPEND SOURCE + fsrtl.c + rtl.c) + +add_library(ntoskrnl_vista ${SOURCE}) +add_dependencies(ntoskrnl_vista bugcodes xdk) diff --git a/reactos/lib/drivers/ntoskrnl_vista/fsrtl.c b/reactos/lib/drivers/ntoskrnl_vista/fsrtl.c new file mode 100644 index 00000000000..607d11d1dc2 --- /dev/null +++ b/reactos/lib/drivers/ntoskrnl_vista/fsrtl.c @@ -0,0 +1,121 @@ +/* + * PROJECT: ReactOS Kernel - Vista+ APIs + * LICENSE: GPL v2 - See COPYING in the top level directory + * FILE: lib/drivers/ntoskrnl_vista/fsrtl.c + * PURPOSE: FsRtl functions of Vista+ + * PROGRAMMERS: Pierre Schweitzer + */ + +#include +#include + +NTKERNELAPI +NTSTATUS +NTAPI +FsRtlRemoveDotsFromPath(IN PWSTR OriginalString, + IN USHORT PathLength, + OUT USHORT *NewLength) +{ + USHORT Length, ReadPos, WritePos = 0; + + Length = PathLength / sizeof(WCHAR); + + if (Length == 3 && OriginalString[0] == '\\' && OriginalString[1] == '.' && OriginalString[2] == '.') + { + return STATUS_IO_REPARSE_DATA_INVALID; + } + + if (Length == 2 && OriginalString[0] == '.' && OriginalString[1] == '.') + { + return STATUS_IO_REPARSE_DATA_INVALID; + } + + if (Length > 2 && OriginalString[0] == '.' && OriginalString[1] == '.' && OriginalString[2] == '\\') + { + return STATUS_IO_REPARSE_DATA_INVALID; + } + + if (Length > 0) + { + ReadPos = 0; + + for (; ReadPos < Length; ++WritePos) + { + for (; ReadPos < Length; ++ReadPos) + { + if (ReadPos < Length - 1 && OriginalString[ReadPos] == '\\' && OriginalString[ReadPos + 1] == '\\') + { + continue; + } + + if (OriginalString[ReadPos] != '.') + { + break; + } + + if (ReadPos == Length - 1) + { + if (OriginalString[ReadPos - 1] == '\\') + { + if (WritePos > 1) + { + --WritePos; + } + + continue; + } + + OriginalString[WritePos] = '.'; + ++WritePos; + continue; + } + + if (OriginalString[ReadPos + 1] == '\\') + { + if (OriginalString[ReadPos - 1] != '\\') + { + OriginalString[WritePos] = '.'; + ++WritePos; + continue; + } + } + else + { + if (OriginalString[ReadPos + 1] != '.' || OriginalString[ReadPos - 1] != '\\' || + ((ReadPos != Length - 2) && OriginalString[ReadPos + 2] != '\\')) + { + OriginalString[WritePos] = '.'; + ++WritePos; + continue; + } + + for (WritePos -= 2; (SHORT)WritePos > 0 && OriginalString[WritePos] != '\\'; --WritePos); + + if ((SHORT)WritePos < 0 || OriginalString[WritePos] != '\\') + { + return STATUS_IO_REPARSE_DATA_INVALID; + } + + if (WritePos == 0 && ReadPos == Length - 2) + { + WritePos = 1; + } + } + + ++ReadPos; + } + + OriginalString[WritePos] = OriginalString[ReadPos]; + ++ReadPos; + } + } + + *NewLength = WritePos * sizeof(WCHAR); + + while (WritePos < Length) + { + OriginalString[WritePos++] = UNICODE_NULL; + } + + return STATUS_SUCCESS; +} diff --git a/reactos/lib/drivers/ntoskrnl_vista/rtl.c b/reactos/lib/drivers/ntoskrnl_vista/rtl.c new file mode 100644 index 00000000000..0aed7ea1351 --- /dev/null +++ b/reactos/lib/drivers/ntoskrnl_vista/rtl.c @@ -0,0 +1,263 @@ +/* + * PROJECT: ReactOS Kernel - Vista+ APIs + * LICENSE: GPL v2 - See COPYING in the top level directory + * FILE: lib/drivers/ntoskrnl_vista/rtl.c + * PURPOSE: Rtl functions of Vista+ + * PROGRAMMERS: Thomas Faber + */ + +#include +#include + +typedef UCHAR BYTE; + +/****************************************************************************** + * RtlUnicodeToUTF8N [NTDLL.@] + */ +NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max, + ULONG *utf8_bytes_written, + const WCHAR *uni_src, ULONG uni_bytes) +{ + NTSTATUS status; + ULONG i; + ULONG written; + ULONG ch; + BYTE utf8_ch[4]; + ULONG utf8_ch_len; + + if (!uni_src) + return STATUS_INVALID_PARAMETER_4; + if (!utf8_bytes_written) + return STATUS_INVALID_PARAMETER; + if (utf8_dest && uni_bytes % sizeof(WCHAR)) + return STATUS_INVALID_PARAMETER_5; + + written = 0; + status = STATUS_SUCCESS; + + for (i = 0; i < uni_bytes / sizeof(WCHAR); i++) + { + /* decode UTF-16 into ch */ + ch = uni_src[i]; + if (ch >= 0xdc00 && ch <= 0xdfff) + { + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + else if (ch >= 0xd800 && ch <= 0xdbff) + { + if (i + 1 < uni_bytes / sizeof(WCHAR)) + { + ch -= 0xd800; + ch <<= 10; + if (uni_src[i + 1] >= 0xdc00 && uni_src[i + 1] <= 0xdfff) + { + ch |= uni_src[i + 1] - 0xdc00; + ch += 0x010000; + i++; + } + else + { + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + } + else + { + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + } + + /* encode ch as UTF-8 */ +#ifndef __REACTOS__ + assert(ch <= 0x10ffff); +#endif + if (ch < 0x80) + { + utf8_ch[0] = ch & 0x7f; + utf8_ch_len = 1; + } + else if (ch < 0x800) + { + utf8_ch[0] = 0xc0 | (ch >> 6 & 0x1f); + utf8_ch[1] = 0x80 | (ch >> 0 & 0x3f); + utf8_ch_len = 2; + } + else if (ch < 0x10000) + { + utf8_ch[0] = 0xe0 | (ch >> 12 & 0x0f); + utf8_ch[1] = 0x80 | (ch >> 6 & 0x3f); + utf8_ch[2] = 0x80 | (ch >> 0 & 0x3f); + utf8_ch_len = 3; + } + else if (ch < 0x200000) + { + utf8_ch[0] = 0xf0 | (ch >> 18 & 0x07); + utf8_ch[1] = 0x80 | (ch >> 12 & 0x3f); + utf8_ch[2] = 0x80 | (ch >> 6 & 0x3f); + utf8_ch[3] = 0x80 | (ch >> 0 & 0x3f); + utf8_ch_len = 4; + } + + if (!utf8_dest) + { + written += utf8_ch_len; + continue; + } + + if (utf8_bytes_max >= utf8_ch_len) + { + memcpy(utf8_dest, utf8_ch, utf8_ch_len); + utf8_dest += utf8_ch_len; + utf8_bytes_max -= utf8_ch_len; + written += utf8_ch_len; + } + else + { + utf8_bytes_max = 0; + status = STATUS_BUFFER_TOO_SMALL; + } + } + + *utf8_bytes_written = written; + return status; +} + + +/****************************************************************************** + * RtlUTF8ToUnicodeN [NTDLL.@] + */ +NTSTATUS NTAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max, + ULONG *uni_bytes_written, + const CHAR *utf8_src, ULONG utf8_bytes) +{ + NTSTATUS status; + ULONG i, j; + ULONG written; + ULONG ch; + ULONG utf8_trail_bytes; + WCHAR utf16_ch[3]; + ULONG utf16_ch_len; + + if (!utf8_src) + return STATUS_INVALID_PARAMETER_4; + if (!uni_bytes_written) + return STATUS_INVALID_PARAMETER; + + written = 0; + status = STATUS_SUCCESS; + + for (i = 0; i < utf8_bytes; i++) + { + /* read UTF-8 lead byte */ + ch = (BYTE)utf8_src[i]; + utf8_trail_bytes = 0; + if (ch >= 0xf5) + { + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + else if (ch >= 0xf0) + { + ch &= 0x07; + utf8_trail_bytes = 3; + } + else if (ch >= 0xe0) + { + ch &= 0x0f; + utf8_trail_bytes = 2; + } + else if (ch >= 0xc2) + { + ch &= 0x1f; + utf8_trail_bytes = 1; + } + else if (ch >= 0x80) + { + /* overlong or trail byte */ + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + + /* read UTF-8 trail bytes */ + if (i + utf8_trail_bytes < utf8_bytes) + { + for (j = 0; j < utf8_trail_bytes; j++) + { + if ((utf8_src[i + 1] & 0xc0) == 0x80) + { + ch <<= 6; + ch |= utf8_src[i + 1] & 0x3f; + i++; + } + else + { + ch = 0xfffd; + utf8_trail_bytes = 0; + status = STATUS_SOME_NOT_MAPPED; + break; + } + } + } + else + { + ch = 0xfffd; + utf8_trail_bytes = 0; + status = STATUS_SOME_NOT_MAPPED; + i = utf8_bytes; + } + + /* encode ch as UTF-16 */ + if ((ch > 0x10ffff) || + (ch >= 0xd800 && ch <= 0xdfff) || + (utf8_trail_bytes == 2 && ch < 0x00800) || + (utf8_trail_bytes == 3 && ch < 0x10000)) + { + /* invalid codepoint or overlong encoding */ + utf16_ch[0] = 0xfffd; + utf16_ch[1] = 0xfffd; + utf16_ch[2] = 0xfffd; + utf16_ch_len = utf8_trail_bytes; + status = STATUS_SOME_NOT_MAPPED; + } + else if (ch >= 0x10000) + { + /* surrogate pair */ + ch -= 0x010000; + utf16_ch[0] = 0xd800 + (ch >> 10 & 0x3ff); + utf16_ch[1] = 0xdc00 + (ch >> 0 & 0x3ff); + utf16_ch_len = 2; + } + else + { + /* single unit */ + utf16_ch[0] = ch; + utf16_ch_len = 1; + } + + if (!uni_dest) + { + written += utf16_ch_len; + continue; + } + + for (j = 0; j < utf16_ch_len; j++) + { + if (uni_bytes_max >= sizeof(WCHAR)) + { + *uni_dest++ = utf16_ch[j]; + uni_bytes_max -= sizeof(WCHAR); + written++; + } + else + { + uni_bytes_max = 0; + status = STATUS_BUFFER_TOO_SMALL; + } + } + } + + *uni_bytes_written = written * sizeof(WCHAR); + return status; +}