⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dir.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: dir.c 25633 2007-01-26 07:22:19Z ion $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            lib/kernel32/file/dir.c
 * PURPOSE:         Directory functions
 * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
 * UPDATE HISTORY:
 *                  Created 01/11/98
 */

/*
 * NOTES: Changed to using ZwCreateFile
 */

/* INCLUDES ******************************************************************/

#include <k32.h>

#define NDEBUG
#include "../include/debug.h"

UNICODE_STRING DllDirectory = {0, 0, NULL};

/* FUNCTIONS *****************************************************************/

/*
 * @implemented
 */
BOOL
STDCALL
CreateDirectoryA (
        LPCSTR                  lpPathName,
        LPSECURITY_ATTRIBUTES   lpSecurityAttributes
        )
{
   PWCHAR PathNameW;

   if (!(PathNameW = FilenameA2W(lpPathName, FALSE)))
      return FALSE;

   return CreateDirectoryW (PathNameW,
                            lpSecurityAttributes);
}


/*
 * @implemented
 */
BOOL
STDCALL
CreateDirectoryExA (
        LPCSTR                  lpTemplateDirectory,
        LPCSTR                  lpNewDirectory,
        LPSECURITY_ATTRIBUTES   lpSecurityAttributes)
{
   PWCHAR TemplateDirectoryW;
   PWCHAR NewDirectoryW;
   BOOL ret;

   if (!(TemplateDirectoryW = FilenameA2W(lpTemplateDirectory, TRUE)))
      return FALSE;

   if (!(NewDirectoryW = FilenameA2W(lpNewDirectory, FALSE)))
   {
      RtlFreeHeap (RtlGetProcessHeap (),
                   0,
                   TemplateDirectoryW);
      return FALSE;
   }

   ret = CreateDirectoryExW (TemplateDirectoryW,
                             NewDirectoryW,
                             lpSecurityAttributes);

   RtlFreeHeap (RtlGetProcessHeap (),
                0,
                TemplateDirectoryW);

   return ret;
}


/*
 * @implemented
 */
BOOL
STDCALL
CreateDirectoryW (
        LPCWSTR                 lpPathName,
        LPSECURITY_ATTRIBUTES   lpSecurityAttributes
        )
{
        OBJECT_ATTRIBUTES ObjectAttributes;
        IO_STATUS_BLOCK IoStatusBlock;
        UNICODE_STRING NtPathU;
        HANDLE DirectoryHandle;
        NTSTATUS Status;

        DPRINT ("lpPathName %S lpSecurityAttributes %p\n",
                lpPathName, lpSecurityAttributes);

        if (!RtlDosPathNameToNtPathName_U (lpPathName,
                                           &NtPathU,
                                           NULL,
                                           NULL))
        {
                SetLastError(ERROR_PATH_NOT_FOUND);
                return FALSE;
        }

        InitializeObjectAttributes(&ObjectAttributes,
                                   &NtPathU,
                                   OBJ_CASE_INSENSITIVE,
                                   NULL,
                                   (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));

        Status = NtCreateFile (&DirectoryHandle,
                               FILE_LIST_DIRECTORY | SYNCHRONIZE |
                                   FILE_OPEN_FOR_BACKUP_INTENT,
                               &ObjectAttributes,
                               &IoStatusBlock,
                               NULL,
                               FILE_ATTRIBUTE_NORMAL,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               FILE_CREATE,
                               FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
                               NULL,
                               0);

        RtlFreeHeap (RtlGetProcessHeap (),
                     0,
                     NtPathU.Buffer);

        if (!NT_SUCCESS(Status))
        {
                SetLastErrorByStatus(Status);
                return FALSE;
        }

        NtClose (DirectoryHandle);

        return TRUE;
}


/*
 * @implemented
 */
BOOL
STDCALL
CreateDirectoryExW (
        LPCWSTR                 lpTemplateDirectory,
        LPCWSTR                 lpNewDirectory,
        LPSECURITY_ATTRIBUTES   lpSecurityAttributes
        )
{
        OBJECT_ATTRIBUTES ObjectAttributes;
        IO_STATUS_BLOCK IoStatusBlock;
        UNICODE_STRING NtPathU, NtTemplatePathU;
        HANDLE DirectoryHandle = NULL;
        HANDLE TemplateHandle = NULL;
        FILE_EA_INFORMATION EaInformation;
        FILE_BASIC_INFORMATION FileBasicInfo;
        NTSTATUS Status;
        ULONG OpenOptions, CreateOptions;
        ACCESS_MASK DesiredAccess;
        BOOLEAN ReparsePoint = FALSE;
        PVOID EaBuffer = NULL;
        ULONG EaLength = 0;
        
        OpenOptions = FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT |
                      FILE_OPEN_FOR_BACKUP_INTENT;
        CreateOptions = FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT;
        DesiredAccess = FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES |
                        FILE_READ_ATTRIBUTES;

        DPRINT ("lpTemplateDirectory %ws lpNewDirectory %ws lpSecurityAttributes %p\n",
                lpTemplateDirectory, lpNewDirectory, lpSecurityAttributes);

        /*
         * Translate the template directory path
         */

        if (!RtlDosPathNameToNtPathName_U (lpTemplateDirectory,
                                           &NtTemplatePathU,
                                           NULL,
                                           NULL))
        {
                SetLastError(ERROR_PATH_NOT_FOUND);
                return FALSE;
        }

        InitializeObjectAttributes(&ObjectAttributes,
                                   &NtTemplatePathU,
                                   OBJ_CASE_INSENSITIVE,
                                   NULL,
                                   NULL);

        /*
         * Open the template directory
         */

OpenTemplateDir:
        Status = NtOpenFile (&TemplateHandle,
                             FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_READ_EA,
                             &ObjectAttributes,
                             &IoStatusBlock,
                             FILE_SHARE_READ | FILE_SHARE_WRITE,
                             OpenOptions);
        if (!NT_SUCCESS(Status))
        {
            if (Status == STATUS_INVALID_PARAMETER &&
                (OpenOptions & FILE_OPEN_REPARSE_POINT))
            {
                /* Some FSs (FAT) don't support reparse points, try opening
                   the directory without FILE_OPEN_REPARSE_POINT */
                OpenOptions &= ~FILE_OPEN_REPARSE_POINT;
                
                DPRINT("Reparse points not supported, try with less options\n");

                /* try again */
                goto OpenTemplateDir;
            }
            else
            {
                DPRINT1("Failed to open the template directory: 0x%x\n", Status);
                goto CleanupNoNtPath;
            }
        }
        
        /*
         * Translate the new directory path and check if they're the same
         */
        
        if (!RtlDosPathNameToNtPathName_U (lpNewDirectory,
                                           &NtPathU,
                                           NULL,
                                           NULL))
        {
            Status = STATUS_OBJECT_PATH_NOT_FOUND;
            goto CleanupNoNtPath;
        }
        
        if (RtlEqualUnicodeString(&NtPathU,
                                  &NtTemplatePathU,
                                  TRUE))
        {
            DPRINT1("Both directory paths are the same!\n");
            Status = STATUS_OBJECT_NAME_INVALID;
            goto Cleanup;
        }

        InitializeObjectAttributes(&ObjectAttributes,
                                   &NtPathU,
                                   OBJ_CASE_INSENSITIVE,
                                   NULL,
                                   (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));

        /*
         * Query the basic file attributes from the template directory
         */

        /* Make sure FILE_ATTRIBUTE_NORMAL is used in case the information
           isn't set by the FS */
        FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
        Status = NtQueryInformationFile(TemplateHandle,
                                        &IoStatusBlock,
                                        &FileBasicInfo,
                                        sizeof(FILE_BASIC_INFORMATION),
                                        FileBasicInformation);
        if (!NT_SUCCESS(Status))
        {
            DPRINT1("Failed to query the basic directory attributes\n");
            goto Cleanup;
        }
        
        /* clear the reparse point attribute if present. We're going to set the
           reparse point later which will cause the attribute to be set */
        if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
        {
            FileBasicInfo.FileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;

            /* writing the extended attributes requires the FILE_WRITE_DATA
               access right */
            DesiredAccess |= FILE_WRITE_DATA;

            CreateOptions |= FILE_OPEN_REPARSE_POINT;
            ReparsePoint = TRUE;
        }

        /*
         * Read the Extended Attributes if present
         */

        for (;;)
        {
          Status = NtQueryInformationFile(TemplateHandle,
                                          &IoStatusBlock,
                                          &EaInformation,
                                          sizeof(FILE_EA_INFORMATION),
                                          FileEaInformation);
          if (NT_SUCCESS(Status) && (EaInformation.EaSize != 0))
          {
            EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
                                       0,
                                       EaInformation.EaSize);
            if (EaBuffer == NULL)
            {
               Status = STATUS_INSUFFICIENT_RESOURCES;
               break;
            }

            Status = NtQueryEaFile(TemplateHandle,
                                   &IoStatusBlock,
                                   EaBuffer,
                                   EaInformation.EaSize,
                                   FALSE,
                                   NULL,
                                   0,
                                   NULL,
                                   TRUE);

            if (NT_SUCCESS(Status))
            {
               /* we successfully read the extended attributes */
               EaLength = EaInformation.EaSize;
               break;
            }
            else
            {
               RtlFreeHeap(RtlGetProcessHeap(),
                           0,
                           EaBuffer);
               EaBuffer = NULL;

               if (Status != STATUS_BUFFER_TOO_SMALL)
               {
                  /* unless we just allocated not enough memory, break the loop
                     and just continue without copying extended attributes */
                  break;
               }
            }
          }
          else
          {
            /* failure or no extended attributes present, break the loop */
            break;
          }
        }

        if (!NT_SUCCESS(Status))
        {
            DPRINT1("Querying the EA data failed: 0x%x\n", Status);
            goto Cleanup;
        }

        /*
         * Create the new directory
         */

        Status = NtCreateFile (&DirectoryHandle,
                               DesiredAccess,
                               &ObjectAttributes,
                               &IoStatusBlock,
                               NULL,
                               FileBasicInfo.FileAttributes,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               FILE_CREATE,
                               CreateOptions,
                               EaBuffer,
                               EaLength);
        if (!NT_SUCCESS(Status))
        {
            if (ReparsePoint &&
                (Status == STATUS_INVALID_PARAMETER || Status == STATUS_ACCESS_DENIED))
            {
                /* The FS doesn't seem to support reparse points... */
                DPRINT1("Cannot copy the hardlink, destination doesn\'t support reparse points!\n");
            }

            goto Cleanup;
        }
        
        if (ReparsePoint)
        {
            /*
             * Copy the reparse point
             */

            PREPARSE_GUID_DATA_BUFFER ReparseDataBuffer =
                (PREPARSE_GUID_DATA_BUFFER)RtlAllocateHeap(RtlGetProcessHeap(),
                                                           0,
                                                           MAXIMUM_REPARSE_DATA_BUFFER_SIZE);

            if (ReparseDataBuffer == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto Cleanup;
            }

            /* query the size of the reparse data buffer structure */
            Status = NtFsControlFile(TemplateHandle,
                                     NULL,
                                     NULL,
                                     NULL,
                                     &IoStatusBlock,
                                     FSCTL_GET_REPARSE_POINT,
                                     NULL,
                                     0,
                                     ReparseDataBuffer,
                                     MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
            if (NT_SUCCESS(Status))
            {
                /* write the reparse point */
                Status = NtFsControlFile(DirectoryHandle,
                                         NULL,
                                         NULL,
                                         NULL,
                                         &IoStatusBlock,
                                         FSCTL_SET_REPARSE_POINT,
                                         ReparseDataBuffer,
                                         MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
                                         NULL,
                                         0);
            }

            RtlFreeHeap(RtlGetProcessHeap(),
                        0,
                        ReparseDataBuffer);

            if (!NT_SUCCESS(Status))
            {
                /* fail, we were unable to read the reparse point data! */
                DPRINT1("Querying or setting the reparse point failed: 0x%x\n", Status);
                goto Cleanup;
            }
        }
        else
        {
            /*
             * Copy alternate file streams, if existing
             */

            /* FIXME - enumerate and copy the file streams */
        }

        /*
         * We successfully created the directory and copied all information
         * from the template directory
         */
        Status = STATUS_SUCCESS;

Cleanup:
        RtlFreeHeap (RtlGetProcessHeap (),
                     0,
                     NtPathU.Buffer);

CleanupNoNtPath:
        if (TemplateHandle != NULL)
        {
                NtClose(TemplateHandle);
        }

        RtlFreeHeap (RtlGetProcessHeap (),
                     0,
                     NtTemplatePathU.Buffer);

        /* free the he extended attributes buffer */
        if (EaBuffer != NULL)
        {
                RtlFreeHeap (RtlGetProcessHeap (),
                             0,
                             EaBuffer);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -