Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / dir.c
diff --git a/reactos/dll/win32/kernel32/client/file/dir.c b/reactos/dll/win32/kernel32/client/file/dir.c
deleted file mode 100644 (file)
index 433e6d5..0000000
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS system libraries
- * FILE:            dll/win32/kernel32/client/file/dir.c
- * PURPOSE:         Directory functions
- * PROGRAMMER:      Pierre Schweitzer (pierre@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <k32.h>
-#define NDEBUG
-#include <debug.h>
-
-/* Short File Name length in chars (8.3) */
-#define SFN_LENGTH 12
-
-/* Match a volume name like:
- * \\?\Volume{GUID}
- */
-#define IS_VOLUME_NAME(s, l)                       \
-  ((l == 96 || (l == 98 && s[48] == '\\')) &&      \
-   s[0] == '\\'&& (s[1] == '?' || s[1] == '\\') && \
-   s[2] == '?' && s[3] == '\\' && s[4] == 'V' &&   \
-   s[5] == 'o' && s[6] == 'l' && s[7] == 'u' &&    \
-   s[8] == 'm' && s[9] == 'e' && s[10] == '{' &&   \
-   s[19] == '-' && s[24] == '-' && s[29] == '-' && \
-   s[34] == '-' && s[47] == '}')
-
-/* FUNCTIONS *****************************************************************/
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-CreateDirectoryA(IN LPCSTR lpPathName,
-                 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
-{
-    PUNICODE_STRING PathNameW;
-
-    PathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
-    if (!PathNameW)
-    {
-        return FALSE;
-    }
-
-    return CreateDirectoryW(PathNameW->Buffer,
-                            lpSecurityAttributes);
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-CreateDirectoryExA(IN LPCSTR lpTemplateDirectory,
-                   IN LPCSTR lpNewDirectory,
-                   IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
-{
-    PUNICODE_STRING TemplateDirectoryW;
-    UNICODE_STRING NewDirectoryW;
-    BOOL ret;
-
-    TemplateDirectoryW = Basep8BitStringToStaticUnicodeString(lpTemplateDirectory);
-    if (!TemplateDirectoryW)
-    {
-        return FALSE;
-    }
-
-    if (!Basep8BitStringToDynamicUnicodeString(&NewDirectoryW, lpNewDirectory))
-    {
-        return FALSE;
-    }
-
-    ret = CreateDirectoryExW(TemplateDirectoryW->Buffer,
-                             NewDirectoryW.Buffer,
-                             lpSecurityAttributes);
-
-    RtlFreeUnicodeString(&NewDirectoryW);
-
-    return ret;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-CreateDirectoryW(IN LPCWSTR lpPathName,
-                 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
-{
-    DWORD Length;
-    NTSTATUS Status;
-    HANDLE DirectoryHandle;
-    UNICODE_STRING NtPathU;
-    PWSTR PathUBuffer, FilePart;
-    IO_STATUS_BLOCK IoStatusBlock;
-    RTL_RELATIVE_NAME_U RelativeName;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-
-    /* Get relative name */
-    if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
-    {
-        SetLastError(ERROR_PATH_NOT_FOUND);
-        return FALSE;
-    }
-
-    /* Check if path length is < MAX_PATH (with space for file name).
-     * If not, prefix is required.
-     */
-    if (NtPathU.Length > (MAX_PATH - SFN_LENGTH) * sizeof(WCHAR) && lpPathName[0] != L'\\' &&
-        lpPathName[1] != L'\\' && lpPathName[2] != L'?' && lpPathName[3] != L'\\')
-    {
-        /* Get file name position and full path length */
-        Length = GetFullPathNameW(lpPathName, 0, NULL, &FilePart);
-        if (Length == 0)
-        {
-            RtlReleaseRelativeName(&RelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
-            SetLastError(ERROR_FILENAME_EXCED_RANGE);
-            return FALSE;
-        }
-
-        /* Keep place for 8.3 file name */
-        Length += SFN_LENGTH;
-        /* No prefix, so, must be smaller than MAX_PATH */
-        if (Length > MAX_PATH)
-        {
-            RtlReleaseRelativeName(&RelativeName);
-            RtlFreeHeap(GetProcessHeap(), 0, NtPathU.Buffer);
-            SetLastError(ERROR_FILENAME_EXCED_RANGE);
-            return FALSE;
-        }
-    }
-
-    /* Save buffer to allow later freeing */
-    PathUBuffer = NtPathU.Buffer;
-
-    /* If we have relative name (and root dir), use them instead */
-    if (RelativeName.RelativeName.Length != 0)
-    {
-        NtPathU.Length = RelativeName.RelativeName.Length;
-        NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
-        NtPathU.Buffer = RelativeName.RelativeName.Buffer;
-    }
-    else
-    {
-        RelativeName.ContainingDirectory = NULL;
-    }
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &NtPathU,
-                               OBJ_CASE_INSENSITIVE,
-                               RelativeName.ContainingDirectory,
-                               (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
-
-    Status = NtCreateFile(&DirectoryHandle,
-                          FILE_LIST_DIRECTORY | SYNCHRONIZE,
-                          &ObjectAttributes,
-                          &IoStatusBlock,
-                          NULL,
-                          FILE_ATTRIBUTE_NORMAL,
-                          FILE_SHARE_READ | FILE_SHARE_WRITE,
-                          FILE_CREATE,
-                          FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
-                          NULL,
-                          0);
-
-    RtlReleaseRelativeName(&RelativeName);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-
-    if (NT_SUCCESS(Status))
-    {
-        NtClose(DirectoryHandle);
-        return TRUE;
-    }
-
-    if (RtlIsDosDeviceName_U(lpPathName))
-    {
-        Status = STATUS_NOT_A_DIRECTORY;
-    }
-
-    BaseSetLastNTError(Status);
-    return FALSE;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory,
-                   IN LPCWSTR lpNewDirectory,
-                   IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
-{
-    DWORD Length;
-    NTSTATUS Status;
-    PVOID EaBuffer = NULL;
-    BOOL ReparsePoint = FALSE;
-    IO_STATUS_BLOCK IoStatusBlock;
-    FILE_EA_INFORMATION FileEaInfo;
-    ULONG EaLength = 0, StreamSize;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    FILE_BASIC_INFORMATION FileBasicInfo;
-    PREPARSE_DATA_BUFFER ReparseDataBuffer;
-    HANDLE TemplateHandle, DirectoryHandle;
-    PFILE_STREAM_INFORMATION FileStreamInfo;
-    FILE_ATTRIBUTE_TAG_INFORMATION FileTagInfo;
-    UNICODE_STRING NtPathU, NtTemplatePathU, NewDirectory;
-    RTL_RELATIVE_NAME_U RelativeName, TemplateRelativeName;
-    PWSTR TemplateBuffer, PathUBuffer, FilePart, SubstituteName;        
-
-    /* Get relative name of the template */
-    if (!RtlDosPathNameToRelativeNtPathName_U(lpTemplateDirectory, &NtTemplatePathU, NULL, &TemplateRelativeName))
-    {
-        SetLastError(ERROR_PATH_NOT_FOUND);
-        return FALSE;
-    }
-
-    /* Save buffer for further freeing */
-    TemplateBuffer = NtTemplatePathU.Buffer;
-
-    /* If we have relative name (and root dir), use them instead */
-    if (TemplateRelativeName.RelativeName.Length != 0)
-    {
-        NtTemplatePathU.Length = TemplateRelativeName.RelativeName.Length;
-        NtTemplatePathU.MaximumLength = TemplateRelativeName.RelativeName.MaximumLength;
-        NtTemplatePathU.Buffer = TemplateRelativeName.RelativeName.Buffer;
-    }
-    else
-    {
-        TemplateRelativeName.ContainingDirectory = NULL;
-    }
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &NtTemplatePathU,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-
-    /* Open template directory */
-    Status = NtOpenFile(&TemplateHandle,
-                        FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_READ_EA,
-                        &ObjectAttributes,
-                        &IoStatusBlock,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE,
-                        FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT);
-    if (!NT_SUCCESS(Status))
-    {
-        if (Status != STATUS_INVALID_PARAMETER)
-        {
-            RtlReleaseRelativeName(&TemplateRelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-            BaseSetLastNTError(Status);
-            return FALSE;
-        }
-
-OpenWithoutReparseSupport:
-        /* Opening failed due to lacking reparse points support in the FSD, try without */
-        Status = NtOpenFile(&TemplateHandle,
-                            FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_READ_EA,
-                            &ObjectAttributes,
-                            &IoStatusBlock,
-                            FILE_SHARE_READ | FILE_SHARE_WRITE,
-                            FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT);
-
-        if (!NT_SUCCESS(Status))
-        {
-            RtlReleaseRelativeName(&TemplateRelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-            BaseSetLastNTError(Status);
-            return FALSE;
-        }
-
-        /* Request file attributes */
-        FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
-        Status = NtQueryInformationFile(TemplateHandle,
-                                        &IoStatusBlock,
-                                        &FileBasicInfo,
-                                        sizeof(FileBasicInfo),
-                                        FileBasicInformation);
-        if (!NT_SUCCESS(Status))
-        {
-            RtlReleaseRelativeName(&TemplateRelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-            CloseHandle(TemplateHandle);
-            BaseSetLastNTError(Status);
-            return FALSE;
-
-        }
-    }
-    else
-    {
-        /* Request file attributes */
-        FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
-        Status = NtQueryInformationFile(TemplateHandle,
-                                        &IoStatusBlock,
-                                        &FileBasicInfo,
-                                        sizeof(FileBasicInfo),
-                                        FileBasicInformation);
-        if (!NT_SUCCESS(Status))
-        {
-            RtlReleaseRelativeName(&TemplateRelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-            CloseHandle(TemplateHandle);
-            BaseSetLastNTError(Status);
-            return FALSE;
-
-        }
-
-        /* If it is a reparse point, then get information about it */
-        if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-        {
-            Status = NtQueryInformationFile(TemplateHandle,
-                                            &IoStatusBlock,
-                                            &FileTagInfo,
-                                            sizeof(FileTagInfo),
-                                            FileAttributeTagInformation);
-            if (!NT_SUCCESS(Status))
-            {
-                RtlReleaseRelativeName(&TemplateRelativeName);
-                RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-                CloseHandle(TemplateHandle);
-                BaseSetLastNTError(Status);
-                return FALSE;
-            }
-
-            /* Only mount points are supported, retry without if anything different */
-            if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
-            {
-                CloseHandle(TemplateHandle);
-                goto OpenWithoutReparseSupport;
-            }
-
-            /* Mark we are playing with a reparse point */
-            ReparsePoint = TRUE;
-        }
-    }
-
-    /* Get relative name of the directory */
-    if (!RtlDosPathNameToRelativeNtPathName_U(lpNewDirectory, &NtPathU, NULL, &RelativeName))
-    {
-        RtlReleaseRelativeName(&TemplateRelativeName);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-        NtClose(TemplateHandle);
-        SetLastError(ERROR_PATH_NOT_FOUND);
-        return FALSE;
-    }
-
-    /* Save its buffer for further freeing */
-    PathUBuffer = NtPathU.Buffer;
-
-    /* Template & directory can't be the same */
-    if (RtlEqualUnicodeString(&NtPathU,
-                              &NtTemplatePathU,
-                              TRUE))
-    {
-        RtlReleaseRelativeName(&RelativeName);
-        RtlReleaseRelativeName(&TemplateRelativeName);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-        NtClose(TemplateHandle);
-        SetLastError(ERROR_INVALID_NAME);
-        return FALSE;
-    }
-
-    RtlReleaseRelativeName(&TemplateRelativeName);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
-
-    /* Check if path length is < MAX_PATH (with space for file name).
-     * If not, prefix is required.
-     */
-    if (NtPathU.Length > (MAX_PATH - SFN_LENGTH) * sizeof(WCHAR) && lpNewDirectory[0] != L'\\' &&
-        lpNewDirectory[1] != L'\\' && lpNewDirectory[2] != L'?' && lpNewDirectory[3] != L'\\')
-    {
-        /* Get file name position and full path length */
-        Length = GetFullPathNameW(lpNewDirectory, 0, NULL, &FilePart);
-        if (Length == 0)
-        {
-            RtlReleaseRelativeName(&RelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-            CloseHandle(TemplateHandle);
-            SetLastError(ERROR_FILENAME_EXCED_RANGE);
-            return FALSE;
-        }
-
-        /* Keep place for 8.3 file name */
-        Length += SFN_LENGTH;
-        /* No prefix, so, must be smaller than MAX_PATH */
-        if (Length > MAX_PATH)
-        {
-            RtlReleaseRelativeName(&RelativeName);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-            CloseHandle(TemplateHandle);
-            SetLastError(ERROR_FILENAME_EXCED_RANGE);
-            return FALSE;
-        }
-    }
-
-    /* If we have relative name (and root dir), use them instead */
-    if (RelativeName.RelativeName.Length != 0)
-    {
-        NtPathU.Length = RelativeName.RelativeName.Length;
-        NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
-        NtPathU.Buffer = RelativeName.RelativeName.Buffer;
-    }
-    else
-    {
-        RelativeName.ContainingDirectory = NULL;
-    }
-
-    /* Get extended attributes */
-    Status = NtQueryInformationFile(TemplateHandle,
-                                    &IoStatusBlock,
-                                    &FileEaInfo,
-                                    sizeof(FileEaInfo),
-                                    FileEaInformation);
-    if (!NT_SUCCESS(Status))
-    {
-        RtlReleaseRelativeName(&RelativeName);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-        CloseHandle(TemplateHandle);
-        BaseSetLastNTError(Status);
-        return FALSE;
-    } 
-
-    /* Start reading extended attributes */
-    if (FileEaInfo.EaSize != 0)
-    {
-        for (EaLength = FileEaInfo.EaSize * 2; ; EaLength = EaLength * 2)
-        {
-            /* Allocate buffer for reading */
-            EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, EaLength);
-            if (!EaBuffer)
-            {
-                RtlReleaseRelativeName(&RelativeName);
-                RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-                CloseHandle(TemplateHandle);
-                BaseSetLastNTError(STATUS_NO_MEMORY);
-                return FALSE;
-            }
-
-            /* Query EAs */
-            Status = NtQueryEaFile(TemplateHandle,
-                                   &IoStatusBlock,
-                                   EaBuffer,
-                                   EaLength,
-                                   FALSE,
-                                   NULL,
-                                   0,
-                                   NULL,
-                                   TRUE);
-            if (!NT_SUCCESS(Status))
-            {
-                RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
-                IoStatusBlock.Information = 0;
-            }
-
-            /* If we don't fail because of too small buffer, stop here */
-            if (Status != STATUS_BUFFER_OVERFLOW &&
-                Status != STATUS_BUFFER_TOO_SMALL)
-            {
-                EaLength = IoStatusBlock.Information;
-                break;
-            }
-        }
-    }
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &NtPathU,
-                               OBJ_CASE_INSENSITIVE,
-                               RelativeName.ContainingDirectory,
-                               (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
-
-    /* Ensure attributes are valid */
-    FileBasicInfo.FileAttributes &= FILE_ATTRIBUTE_VALID_FLAGS;
-
-    /* Create the new directory */
-    Status = NtCreateFile(&DirectoryHandle,
-                          FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES |
-                          FILE_READ_ATTRIBUTES | (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? FILE_ADD_FILE : 0),
-                          &ObjectAttributes,
-                          &IoStatusBlock,
-                          NULL,
-                          FileBasicInfo.FileAttributes,
-                          FILE_SHARE_READ | FILE_SHARE_WRITE,
-                          FILE_CREATE,
-                          FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                          FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT,
-                          EaBuffer,
-                          EaLength);
-    if (!NT_SUCCESS(Status))
-    {
-        if (Status == STATUS_INVALID_PARAMETER || Status == STATUS_ACCESS_DENIED)
-        {
-            /* If creation failed, it might be because FSD doesn't support reparse points
-             * Retry without asking for such support in case template is not a reparse point
-             */
-            if (!ReparsePoint)
-            {
-                Status = NtCreateFile(&DirectoryHandle,
-                                      FILE_LIST_DIRECTORY | SYNCHRONIZE |
-                                      FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES,
-                                      &ObjectAttributes,
-                                      &IoStatusBlock,
-                                      NULL,
-                                      FileBasicInfo.FileAttributes,
-                                      FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                      FILE_CREATE,
-                                      FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                                      FILE_OPEN_FOR_BACKUP_INTENT,
-                                      EaBuffer,
-                                      EaLength);
-            }
-            else
-            {
-                RtlReleaseRelativeName(&RelativeName);
-                RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-                if (EaBuffer)
-                {
-                    RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
-                }
-                CloseHandle(TemplateHandle);
-                BaseSetLastNTError(Status);
-                return FALSE;
-            }
-        }
-    }
-
-    RtlReleaseRelativeName(&RelativeName);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-    if (EaBuffer)
-    {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
-    }
-
-    if (!NT_SUCCESS(Status))
-    {
-        NtClose(TemplateHandle);
-        if (RtlIsDosDeviceName_U(lpNewDirectory))
-        {
-            Status = STATUS_NOT_A_DIRECTORY;
-        }
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
-    /* If template is a reparse point, copy reparse data */
-    if (ReparsePoint)
-    {
-        ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                            MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
-        if (!ReparseDataBuffer)
-        {
-            NtClose(TemplateHandle);
-            NtClose(DirectoryHandle);
-            SetLastError(STATUS_NO_MEMORY);
-            return FALSE;
-        }
-
-        /* First query data */
-        Status = NtFsControlFile(TemplateHandle,
-                                 NULL,
-                                 NULL,
-                                 NULL,
-                                 &IoStatusBlock,
-                                 FSCTL_GET_REPARSE_POINT,
-                                 NULL,
-                                 0,
-                                 ReparseDataBuffer,
-                                 MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
-        if (!NT_SUCCESS(Status))
-        {
-            RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-            NtClose(TemplateHandle);
-            NtClose(DirectoryHandle);
-            SetLastError(Status);
-            return FALSE;
-        }
-
-        /* Once again, ensure it is a mount point */
-        if (ReparseDataBuffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
-        {
-            RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-            NtClose(TemplateHandle);
-            NtClose(DirectoryHandle);
-            SetLastError(STATUS_OBJECT_NAME_INVALID);
-            return FALSE;
-        }
-
-        /* Get volume name */
-        SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
-                                 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
-        if (IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
-        {
-            /* Prepare to define a new mount point for that volume */
-            RtlInitUnicodeString(&NewDirectory, lpNewDirectory);
-            NewDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewDirectory.Length + 2 * sizeof(WCHAR));
-            if (!NewDirectory.Buffer)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-                NtClose(TemplateHandle);
-                NtClose(DirectoryHandle);
-                return FALSE;
-            }
-
-            RtlCopyMemory(&NewDirectory.Buffer, lpNewDirectory, NewDirectory.Length);
-            if (NewDirectory.Buffer[NewDirectory.Length / sizeof(WCHAR)] != L'\\')
-            {
-                NewDirectory.Buffer[NewDirectory.Length / sizeof(WCHAR)] = L'\\';
-                NewDirectory.Buffer[(NewDirectory.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
-            }
-
-            /* Define a new mount point for that volume */
-            SetVolumeMountPointW(NewDirectory.Buffer, SubstituteName);
-
-            RtlFreeHeap(RtlGetProcessHeap(), 0, NewDirectory.Buffer);
-            RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-            NtClose(TemplateHandle);
-            NtClose(DirectoryHandle);
-            return TRUE;
-        }
-
-        /* Otherwise copy data raw */
-        Status = NtFsControlFile(DirectoryHandle,
-                                 NULL,
-                                 NULL,
-                                 NULL,
-                                 &IoStatusBlock,
-                                 FSCTL_SET_REPARSE_POINT,
-                                 ReparseDataBuffer,
-                                 ReparseDataBuffer->ReparseDataLength +
-                                 FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer),
-                                 NULL,
-                                 0);
-
-        RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-        NtClose(TemplateHandle);
-        NtClose(DirectoryHandle);
-
-        if (NT_SUCCESS(Status))
-        {
-            return TRUE;
-        }
-
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-    /* In case it's not a reparse point, handle streams on the file */
-    else
-    {
-        for (StreamSize = 0x1000; ; StreamSize = StreamSize * 2)
-        {
-            FileStreamInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, StreamSize);
-            if (!FileStreamInfo)
-            {
-                BaseMarkFileForDelete(DirectoryHandle, FileBasicInfo.FileAttributes);
-                SetLastError(STATUS_NO_MEMORY);
-                break;
-            }
-
-            /* Query stream information */
-            Status = NtQueryInformationFile(TemplateHandle,
-                                            &IoStatusBlock,
-                                            FileStreamInfo,
-                                            StreamSize,
-                                            FileStreamInformation);
-            if (NT_SUCCESS(Status))
-            {
-                break;
-            }
-
-            RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
-            FileStreamInfo = NULL;
-
-            /* If it failed, ensure that's not because of too small buffer */
-            if (Status != STATUS_BUFFER_OVERFLOW &&
-                Status != STATUS_BUFFER_TOO_SMALL)
-            {
-                break;
-            }
-        }
-
-        if (!NT_SUCCESS(Status) || IoStatusBlock.Information == 0)
-        {
-            if (FileStreamInfo)
-            {
-                RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
-            }
-
-            NtClose(TemplateHandle);
-            NtClose(DirectoryHandle);
-            return TRUE;
-        }
-
-#if 1
-        /* FIXME: TODO */
-        DPRINT1("Warning: streams copying is unimplemented!\n");
-        RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
-        NtClose(TemplateHandle);
-        NtClose(DirectoryHandle);
-#endif
-        return TRUE;
-    }
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-RemoveDirectoryA(IN LPCSTR lpPathName)
-{
-    PUNICODE_STRING PathNameW;
-
-    PathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
-    if (!PathNameW)
-    {
-        return FALSE;
-    }
-
-    return RemoveDirectoryW(PathNameW->Buffer);
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-RemoveDirectoryW(IN LPCWSTR lpPathName)
-{
-    NTSTATUS Status;
-    DWORD BytesReturned;
-    HANDLE DirectoryHandle;
-    IO_STATUS_BLOCK IoStatusBlock;
-    UNICODE_STRING NtPathU, PathName;
-    RTL_RELATIVE_NAME_U RelativeName;
-    PWSTR PathUBuffer, SubstituteName;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    PREPARSE_DATA_BUFFER ReparseDataBuffer;
-    FILE_DISPOSITION_INFORMATION FileDispInfo;
-    FILE_ATTRIBUTE_TAG_INFORMATION FileTagInfo;
-
-    /* Get relative name */
-    if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
-    {
-        SetLastError(ERROR_PATH_NOT_FOUND);
-        return FALSE;
-    }
-
-    /* Save buffer to allow later freeing */
-    PathUBuffer = NtPathU.Buffer;
-
-    /* If we have relative name (and root dir), use them instead */
-    if (RelativeName.RelativeName.Length != 0)
-    {
-        NtPathU.Length = RelativeName.RelativeName.Length;
-        NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
-        NtPathU.Buffer = RelativeName.RelativeName.Buffer;
-    }
-    else
-    {
-        RelativeName.ContainingDirectory = NULL;
-    }
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &NtPathU,
-                               OBJ_CASE_INSENSITIVE,
-                               RelativeName.ContainingDirectory,
-                               NULL);
-
-    /* Try to open directory */
-    Status = NtOpenFile(&DirectoryHandle,
-                        DELETE | SYNCHRONIZE | FAILED_ACCESS_ACE_FLAG,
-                        &ObjectAttributes,
-                        &IoStatusBlock,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                        FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                        FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
-    if (!NT_SUCCESS(Status))
-    {
-        /* We only accept failure for reparse points not being supported */
-        if (Status != STATUS_INVALID_PARAMETER)
-        {
-            goto Cleanup;
-        }
-
-        /* Try to open, with reparse points support */
-        Status = NtOpenFile(&DirectoryHandle,
-                            DELETE | SYNCHRONIZE,
-                            &ObjectAttributes,
-                            &IoStatusBlock,
-                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                            FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                            FILE_OPEN_FOR_BACKUP_INTENT);
-        if (!NT_SUCCESS(Status))
-        {
-            goto Cleanup;
-        }
-
-        /* Success, mark directory */
-        goto MarkFileForDelete;
-    }
-
-    /* Get information about file (and reparse point) */
-    Status = NtQueryInformationFile(DirectoryHandle,
-                                    &IoStatusBlock,
-                                    &FileTagInfo,
-                                    sizeof(FileTagInfo),
-                                    FileAttributeTagInformation);
-    if (!NT_SUCCESS(Status))
-    {
-        /* FSD might not support querying reparse points information */
-        if (Status != STATUS_NOT_IMPLEMENTED &&
-            Status != STATUS_INVALID_PARAMETER)
-        {
-            goto CleanupHandle;
-        }
-
-        /* If that's the case, then just delete directory */
-        goto MarkFileForDelete;
-    }
-
-    /* If that's not a reparse point, nothing more to do than just delete */
-    if (!(FileTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
-    {
-        goto MarkFileForDelete;
-    }
-
-    /* Check if that's a mount point */
-    if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
-    {
-        /* It's not */
-        NtClose(DirectoryHandle);
-
-        /* So, try to reopen directory, ignoring mount point */
-        Status = NtOpenFile(&DirectoryHandle,
-                            DELETE | SYNCHRONIZE,
-                            &ObjectAttributes,
-                            &IoStatusBlock,
-                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                            FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                            FILE_OPEN_FOR_BACKUP_INTENT);
-        if (NT_SUCCESS(Status))
-        {
-            /* It succeed, we can safely delete directory (and ignore reparse point) */
-            goto MarkFileForDelete;
-        }
-
-        /* If it failed, only allow case where IO mount point was ignored */
-        if (Status != STATUS_IO_REPARSE_TAG_NOT_HANDLED)
-        {
-            goto Cleanup;
-        }
-
-        /* Reopen with reparse point support */
-        Status = NtOpenFile(&DirectoryHandle,
-                            DELETE | SYNCHRONIZE,
-                            &ObjectAttributes,
-                            &IoStatusBlock,
-                            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                            FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
-                            FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
-        if (NT_SUCCESS(Status))
-        {
-            /* And mark for delete */
-            goto MarkFileForDelete;
-        }
-
-        goto Cleanup;
-    }
-
-    /* Here, we have a mount point, prepare to query information about it */
-    ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                        MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
-    if (!ReparseDataBuffer)
-    {
-        RtlReleaseRelativeName(&RelativeName);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-        NtClose(DirectoryHandle);
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
-
-    /* Query */
-    if (!DeviceIoControl(DirectoryHandle,
-                         FSCTL_GET_REPARSE_POINT,
-                         NULL, 0,
-                         ReparseDataBuffer,
-                         MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
-                         &BytesReturned,
-                         NULL))
-    {
-        RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-        goto MarkFileForDelete;
-    }
-
-    /* Get volume name */
-    SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
-                             ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
-    if (!IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
-    {
-        /* This is not a volume, we can safely delete */
-        RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-        goto MarkFileForDelete;
-    }
-
-    /* Prepare to delete mount point */
-    RtlInitUnicodeString(&PathName, lpPathName);
-    PathName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathName.Length + 2 * sizeof(WCHAR));
-    if (!PathName.Buffer)
-    {
-        RtlReleaseRelativeName(&RelativeName);
-        RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-        NtClose(DirectoryHandle);
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        return FALSE;
-    }
-
-    RtlCopyMemory(&PathName.Buffer, lpPathName, PathName.Length);
-    if (PathName.Buffer[PathName.Length / sizeof(WCHAR)] != L'\\')
-    {
-        PathName.Buffer[PathName.Length / sizeof(WCHAR)] = L'\\';
-        PathName.Buffer[(PathName.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
-    }
-
-    /* Delete mount point for that volume */
-    DeleteVolumeMountPointW(PathName.Buffer);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, PathName.Buffer);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
-
-    /* And mark directory for delete */
-MarkFileForDelete:
-    RtlReleaseRelativeName(&RelativeName);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-
-    /* Mark & set */
-    FileDispInfo.DeleteFile = TRUE;
-    Status = NtSetInformationFile(DirectoryHandle,
-                                  &IoStatusBlock,
-                                  &FileDispInfo,
-                                  sizeof(FILE_DISPOSITION_INFORMATION),
-                                  FileDispositionInformation);
-    NtClose(DirectoryHandle);
-
-    if (!NT_SUCCESS(Status))
-    {
-        BaseSetLastNTError(Status);
-        return FALSE;
-    }
-
-    return TRUE;
-
-CleanupHandle:
-    NtClose(DirectoryHandle);
-
-Cleanup:
-    RtlReleaseRelativeName(&RelativeName);
-    RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
-    BaseSetLastNTError(Status);
-    return FALSE;
-}
-
-/* EOF */