[NTOSKRNL_VISTA]
authorPierre Schweitzer <pierre@reactos.org>
Wed, 23 Mar 2016 20:01:51 +0000 (20:01 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Wed, 23 Mar 2016 20:01:51 +0000 (20:01 +0000)
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

reactos/lib/drivers/CMakeLists.txt
reactos/lib/drivers/ntoskrnl_vista/CMakeLists.txt [new file with mode: 0644]
reactos/lib/drivers/ntoskrnl_vista/fsrtl.c [new file with mode: 0644]
reactos/lib/drivers/ntoskrnl_vista/rtl.c [new file with mode: 0644]

index 538efc6..a65f687 100644 (file)
@@ -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 (file)
index 0000000..0523702
--- /dev/null
@@ -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 (file)
index 0000000..607d11d
--- /dev/null
@@ -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 <pierre@reactos.org>
+ */
+
+#include <ntdef.h>
+#include <ntifs.h>
+
+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 (file)
index 0000000..0aed7ea
--- /dev/null
@@ -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 <thomas.faber@reactos.org>
+ */
+
+#include <ntdef.h>
+#include <ntifs.h>
+
+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;
+}