コード例 #1
0
        public static FileAttributes GetAttributes(string fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: true);

            if (errorCode != 0)
            {
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            return((FileAttributes)data.dwFileAttributes);
        }
コード例 #2
0
        public static DateTimeOffset GetCreationTime(string fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: false);

            if (errorCode != 0)
            {
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            return(data.ftCreationTime.ToDateTimeOffset());
        }
コード例 #3
0
        private void EnsureDataInitialized()
        {
            if (_dataInitialized == -1)
            {
                _data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
                Refresh();
            }

            if (_dataInitialized != 0) // Refresh was unable to initialize the data
            {
                throw Win32Marshal.GetExceptionForWin32Error(_dataInitialized, FullPath);
            }
        }
コード例 #4
0
        private void EnsureDataInitialized()
        {
            if (_dataInitialized == -1)
            {
                _data = default;
                Refresh();
            }

            if (_dataInitialized != 0) // Refresh was unable to initialize the data
            {
                throw Win32Marshal.GetExceptionForWin32Error(_dataInitialized, FullPath);
            }
        }
コード例 #5
0
        internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound)
        {
            int errorCode = Interop.Errors.ERROR_SUCCESS;

            // Neither GetFileAttributes or FindFirstFile like trailing separators
            path = path.TrimEnd(PathHelpers.DirectorySeparatorChars);

            using (new DisableMediaInsertionPrompt())
            {
                if (!Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data))
                {
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED)
                    {
                        // Files that are marked for deletion will not let you GetFileAttributes,
                        // ERROR_ACCESS_DENIED is given back without filling out the data struct.
                        // FindFirstFile, however, will. Historically we always gave back attributes
                        // for marked-for-deletion files.

                        var findData = new Interop.Kernel32.WIN32_FIND_DATA();
                        using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path, ref findData))
                        {
                            if (handle.IsInvalid)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                            }
                            else
                            {
                                errorCode = Interop.Errors.ERROR_SUCCESS;
                                data.PopulateFrom(ref findData);
                            }
                        }
                    }
                }
            }

            if (errorCode != Interop.Errors.ERROR_SUCCESS && !returnErrorOnNotFound)
            {
                switch (errorCode)
                {
                case Interop.Errors.ERROR_FILE_NOT_FOUND:
                case Interop.Errors.ERROR_PATH_NOT_FOUND:
                case Interop.Errors.ERROR_NOT_READY:     // Removable media not ready
                    // Return default value for backward compatibility
                    data.fileAttributes = -1;
                    return(Interop.Errors.ERROR_SUCCESS);
                }
            }

            return(errorCode);
        }
コード例 #6
0
        public override DateTimeOffset GetLastWriteTime(string fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: false);

            if (errorCode != 0)
            {
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            long dt = ((long)data.ftLastWriteTimeHigh << 32) | ((long)data.ftLastWriteTimeLow);

            return(DateTimeOffset.FromFileTime(dt));
        }
コード例 #7
0
        internal static void CreateSymbolicLink(string path, string pathToTarget, bool isDirectory)
        {
            string pathToTargetFullPath = PathInternal.GetLinkTargetFullPath(path, pathToTarget);

            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = default;
            int errorCode = FillAttributeInfo(pathToTargetFullPath, ref data, returnErrorOnNotFound: true);

            if (errorCode == Interop.Errors.ERROR_SUCCESS &&
                data.dwFileAttributes != -1 &&
                isDirectory != ((data.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0))
            {
                throw new IOException(SR.Format(SR.IO_InconsistentLinkType, path));
            }

            Interop.Kernel32.CreateSymbolicLink(path, pathToTarget, isDirectory);
        }
コード例 #8
0
        private static bool IsReparsePoint(string fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: true);

            if (errorCode != Interop.Errors.ERROR_SUCCESS)
            {
                // File not found doesn't make much sense coming from a directory delete.
                if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND)
                {
                    errorCode = Interop.Errors.ERROR_PATH_NOT_FOUND;
                }
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            return(((FileAttributes)data.dwFileAttributes & FileAttributes.ReparsePoint) != 0);
        }
コード例 #9
0
 private static void PopulateAttributeData(ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, in Interop.Kernel32.BY_HANDLE_FILE_INFORMATION fileInformationData)
コード例 #10
0
        // Returns 0 on success, otherwise a Win32 error code.  Note that
        // classes should use -1 as the uninitialized state for dataInitialized.
        internal static int FillAttributeInfo(String path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool tryagain, bool returnErrorOnNotFound)
        {
            int errorCode = 0;

            if (tryagain) // someone has a handle to the file open, or other error
            {
                Interop.Kernel32.WIN32_FIND_DATA findData;
                findData = new Interop.Kernel32.WIN32_FIND_DATA();

                // Remove trailing slash since this can cause grief to FindFirstFile. You will get an invalid argument error
                String tempPath = path.TrimEnd(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });

                // For floppy drives, normally the OS will pop up a dialog saying
                // there is no disk in drive A:, please insert one.  We don't want that.
                // SetThreadErrorMode will let us disable this, but we should set the error
                // mode back, since this may have wide-ranging effects.
                uint oldMode;
                bool setThreadErrorModeSuccess = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
                try
                {
                    bool           error  = false;
                    SafeFindHandle handle = Interop.Kernel32.FindFirstFile(tempPath, ref findData);
                    try
                    {
                        if (handle.IsInvalid)
                        {
                            error     = true;
                            errorCode = Marshal.GetLastWin32Error();

                            if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND ||
                                errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND ||
                                errorCode == Interop.Errors.ERROR_NOT_READY)  // floppy device not ready
                            {
                                if (!returnErrorOnNotFound)
                                {
                                    // Return default value for backward compatibility
                                    errorCode           = 0;
                                    data.fileAttributes = -1;
                                }
                            }
                            return(errorCode);
                        }
                    }
                    finally
                    {
                        // Close the Win32 handle
                        try
                        {
                            handle.Dispose();
                        }
                        catch
                        {
                            // if we're already returning an error, don't throw another one.
                            if (!error)
                            {
                                throw Win32Marshal.GetExceptionForLastWin32Error();
                            }
                        }
                    }
                }
                finally
                {
                    if (setThreadErrorModeSuccess)
                    {
                        Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
                    }
                }

                // Copy the information to data
                data.PopulateFrom(ref findData);
            }
            else
            {
                // For floppy drives, normally the OS will pop up a dialog saying
                // there is no disk in drive A:, please insert one.  We don't want that.
                // SetThreadErrorMode will let us disable this, but we should set the error
                // mode back, since this may have wide-ranging effects.
                bool success = false;
                uint oldMode;
                bool setThreadErrorModeSuccess = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS, out oldMode);
                try
                {
                    success = Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data);
                }
                finally
                {
                    if (setThreadErrorModeSuccess)
                    {
                        Interop.Kernel32.SetThreadErrorMode(oldMode, out oldMode);
                    }
                }

                if (!success)
                {
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode != Interop.Errors.ERROR_FILE_NOT_FOUND &&
                        errorCode != Interop.Errors.ERROR_PATH_NOT_FOUND &&
                        errorCode != Interop.Errors.ERROR_NOT_READY)  // floppy device not ready
                    {
                        // In case someone latched onto the file. Take the perf hit only for failure
                        return(FillAttributeInfo(path, ref data, true, returnErrorOnNotFound));
                    }
                    else
                    {
                        if (!returnErrorOnNotFound)
                        {
                            // Return default value for backward compatibility
                            errorCode           = 0;
                            data.fileAttributes = -1;
                        }
                    }
                }
            }

            return(errorCode);
        }
コード例 #11
0
ファイル: Win32FileSystem.cs プロジェクト: dotnet/corefx
        public override bool FileExists(System.String fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, false, true);

            return (errorCode == 0) && (data.fileAttributes != -1)
                    && ((data.fileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0);
        }
コード例 #12
0
        private void EnsureDataInitialized()
        {
            if (_dataInitialized == -1)
            {
                _data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
                Refresh();
            }

            if (_dataInitialized != 0) // Refresh was unable to initialize the data
                throw Win32Marshal.GetExceptionForWin32Error(_dataInitialized, FullPath);
        }
コード例 #13
0
ファイル: Win32FileSystem.cs プロジェクト: dotnet/corefx
        public override void RemoveDirectory(string fullPath, bool recursive)
        {
            // Do not recursively delete through reparse points.  Perhaps in a 
            // future version we will add a new flag to control this behavior, 
            // but for now we're much safer if we err on the conservative side.
            // This applies to symbolic links and mount points.
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, false, true);
            if (errorCode != 0)
            {
                // Ensure we throw a DirectoryNotFoundException.
                if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND)
                    errorCode = Interop.Errors.ERROR_PATH_NOT_FOUND;
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            if (((FileAttributes)data.fileAttributes & FileAttributes.ReparsePoint) != 0)
                recursive = false;

            // We want extended syntax so we can delete "extended" subdirectories and files
            // (most notably ones with trailing whitespace or periods)
            RemoveDirectoryHelper(PathInternal.EnsureExtendedPrefix(fullPath), recursive, true);
        }
コード例 #14
0
ファイル: Win32FileSystem.cs プロジェクト: dotnet/corefx
        public override DateTimeOffset GetLastWriteTime(string fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, false, false);
            if (errorCode != 0)
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);

            long dt = ((long)data.ftLastWriteTimeHigh << 32) | ((long)data.ftLastWriteTimeLow);
            return DateTimeOffset.FromFileTime(dt);
        }
コード例 #15
0
ファイル: Win32FileSystem.cs プロジェクト: dotnet/corefx
        public override FileAttributes GetAttributes(string fullPath)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            int errorCode = FillAttributeInfo(fullPath, ref data, false, true);
            if (errorCode != 0)
                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);

            return (FileAttributes)data.fileAttributes;
        }
コード例 #16
0
        private static bool ShouldUseWinRT(string fullPath, bool isCreate)
        {
            // The purpose of this method is to determine if we can access a path
            // via Win32 or if we need to fallback to WinRT.
            // We prefer Win32 since it is faster, WinRT's APIs eventually just
            // call into Win32 after all, but it doesn't provide access to,
            // brokered paths (like Pictures or Documents) nor does it handle 
            // placeholder files.  So we'd like to fall back to WinRT whenever
            // we can't access a path, or if it known to be a placeholder file.

            bool useWinRt = false;

            do
            {
                // first use GetFileAttributesEx as it is faster than FindFirstFile and requires minimum permissions
                Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
                if (Interop.Kernel32.GetFileAttributesEx(fullPath, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data))
                {
                    // got the attributes
                    if ((data.fileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0 ||
                        (data.fileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) == 0)
                    {
                        // we have a directory or a file that is not a reparse point
                        // useWinRt = false;
                        break;
                    }
                    else
                    {
                        // we need to get the find data to determine if it is a placeholder file
                        Interop.Kernel32.WIN32_FIND_DATA findData = new Interop.Kernel32.WIN32_FIND_DATA();
                        using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(fullPath, ref findData))
                        {
                            if (!handle.IsInvalid)
                            {
                                // got the find data, use WinRT for placeholder files

                                Debug.Assert((findData.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0);
                                Debug.Assert((findData.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) != 0);

                                useWinRt = findData.dwReserved0 == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_FILE_PLACEHOLDER;
                                break;
                            }
                        }
                    }
                }

                int error = Marshal.GetLastWin32Error();
                Debug.Assert(error != Interop.Errors.ERROR_SUCCESS);

                if (error == Interop.Errors.ERROR_ACCESS_DENIED)
                {
                    // The path was not accessible with Win32, so try WinRT
                    useWinRt = true;
                    break;
                }
                else if (error != Interop.Errors.ERROR_PATH_NOT_FOUND && error != Interop.Errors.ERROR_FILE_NOT_FOUND)
                {
                    // We hit some error other than ACCESS_DENIED or NOT_FOUND,
                    // Default to Win32 to provide most accurate error behavior
                    break;
                }

                // error was ERROR_PATH_NOT_FOUND or ERROR_FILE_NOT_FOUND
                // if we are creating a file/directory we cannot assume that Win32 will have access to 
                // the parent directory, so we walk up the path.
                fullPath = PathHelpers.GetDirectoryNameInternal(fullPath);
                // only walk up the path if we are creating a file/directory and not at the root
            } while (isCreate && !String.IsNullOrEmpty(fullPath));

            return useWinRt;
        }
コード例 #17
0
        private static bool ShouldUseWinRT(string fullPath, bool isCreate)
        {
            // The purpose of this method is to determine if we can access a path
            // via Win32 or if we need to fallback to WinRT.
            // We prefer Win32 since it is faster, WinRT's APIs eventually just
            // call into Win32 after all, but it doesn't provide access to,
            // brokered paths (like Pictures or Documents) nor does it handle
            // placeholder files.  So we'd like to fall back to WinRT whenever
            // we can't access a path, or if it known to be a placeholder file.

            bool useWinRt = false;

            do
            {
                // first use GetFileAttributesEx as it is faster than FindFirstFile and requires minimum permissions
                Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
                if (Interop.Kernel32.GetFileAttributesEx(fullPath, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data))
                {
                    // got the attributes
                    if ((data.fileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0 ||
                        (data.fileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) == 0)
                    {
                        // we have a directory or a file that is not a reparse point
                        // useWinRt = false;
                        break;
                    }
                    else
                    {
                        // we need to get the find data to determine if it is a placeholder file
                        Interop.Kernel32.WIN32_FIND_DATA findData = new Interop.Kernel32.WIN32_FIND_DATA();
                        using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(fullPath, ref findData))
                        {
                            if (!handle.IsInvalid)
                            {
                                // got the find data, use WinRT for placeholder files

                                Debug.Assert((findData.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0);
                                Debug.Assert((findData.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) != 0);

                                useWinRt = findData.dwReserved0 == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_FILE_PLACEHOLDER;
                                break;
                            }
                        }
                    }
                }

                int error = Marshal.GetLastWin32Error();
                Debug.Assert(error != Interop.Errors.ERROR_SUCCESS);

                if (error == Interop.Errors.ERROR_ACCESS_DENIED)
                {
                    // The path was not accessible with Win32, so try WinRT
                    useWinRt = true;
                    break;
                }
                else if (error != Interop.Errors.ERROR_PATH_NOT_FOUND && error != Interop.Errors.ERROR_FILE_NOT_FOUND)
                {
                    // We hit some error other than ACCESS_DENIED or NOT_FOUND,
                    // Default to Win32 to provide most accurate error behavior
                    break;
                }

                // error was ERROR_PATH_NOT_FOUND or ERROR_FILE_NOT_FOUND
                // if we are creating a file/directory we cannot assume that Win32 will have access to
                // the parent directory, so we walk up the path.
                fullPath = PathHelpers.GetDirectoryNameInternal(fullPath);
                // only walk up the path if we are creating a file/directory and not at the root
            } while (isCreate && !String.IsNullOrEmpty(fullPath));

            return(useWinRt);
        }
コード例 #18
0
        /// <summary>
        /// Returns 0 on success, otherwise a Win32 error code.  Note that
        /// classes should use -1 as the uninitialized state for dataInitialized.
        /// </summary>
        /// <param name="returnErrorOnNotFound">Return the error code for not found errors?</param>
        internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound)
        {
            int errorCode = Interop.Errors.ERROR_SUCCESS;

            // Neither GetFileAttributes or FindFirstFile like trailing separators
            path = PathInternal.TrimEndingDirectorySeparator(path);

            using (DisableMediaInsertionPrompt.Create())
            {
                if (!Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data))
                {
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode != Interop.Errors.ERROR_FILE_NOT_FOUND &&
                        errorCode != Interop.Errors.ERROR_PATH_NOT_FOUND &&
                        errorCode != Interop.Errors.ERROR_NOT_READY &&
                        errorCode != Interop.Errors.ERROR_INVALID_NAME &&
                        errorCode != Interop.Errors.ERROR_BAD_PATHNAME &&
                        errorCode != Interop.Errors.ERROR_BAD_NETPATH &&
                        errorCode != Interop.Errors.ERROR_BAD_NET_NAME &&
                        errorCode != Interop.Errors.ERROR_INVALID_PARAMETER &&
                        errorCode != Interop.Errors.ERROR_NETWORK_UNREACHABLE)
                    {
                        // Assert so we can track down other cases (if any) to add to our test suite
                        Debug.Assert(errorCode == Interop.Errors.ERROR_ACCESS_DENIED || errorCode == Interop.Errors.ERROR_SHARING_VIOLATION,
                                     $"Unexpected error code getting attributes {errorCode}");

                        // Files that are marked for deletion will not let you GetFileAttributes,
                        // ERROR_ACCESS_DENIED is given back without filling out the data struct.
                        // FindFirstFile, however, will. Historically we always gave back attributes
                        // for marked-for-deletion files.
                        //
                        // Another case where enumeration works is with special system files such as
                        // pagefile.sys that give back ERROR_SHARING_VIOLATION on GetAttributes.
                        //
                        // Ideally we'd only try again for known cases due to the potential performance
                        // hit. The last attempt to do so baked for nearly a year before we found the
                        // pagefile.sys case. As such we're probably stuck filtering out specific
                        // cases that we know we don't want to retry on.

                        var findData = new Interop.Kernel32.WIN32_FIND_DATA();
                        using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path, ref findData))
                        {
                            if (handle.IsInvalid)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                            }
                            else
                            {
                                errorCode = Interop.Errors.ERROR_SUCCESS;
                                data.PopulateFrom(ref findData);
                            }
                        }
                    }
                }
            }

            if (errorCode != Interop.Errors.ERROR_SUCCESS && !returnErrorOnNotFound)
            {
                switch (errorCode)
                {
                case Interop.Errors.ERROR_FILE_NOT_FOUND:
                case Interop.Errors.ERROR_PATH_NOT_FOUND:
                case Interop.Errors.ERROR_NOT_READY:     // Removable media not ready
                    // Return default value for backward compatibility
                    data.dwFileAttributes = -1;
                    return(Interop.Errors.ERROR_SUCCESS);
                }
            }

            return(errorCode);
        }
コード例 #19
0
ファイル: Win32FileSystem.cs プロジェクト: dotnet/corefx
        private bool DirectoryExists(String path, out int lastError)
        {
            Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
            lastError = FillAttributeInfo(path, ref data, false, true);

            return (lastError == 0) && (data.fileAttributes != -1)
                    && ((data.fileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0);
        }