[System.Security.SecurityCritical]  // auto-generated
        private void AddSearchableDirsToStack(Directory.SearchData localSearchData)
        {
            Contract.Requires(localSearchData != null);

            String         searchPath = Path.Combine(localSearchData.fullPath, "*");
            SafeFindHandle hnd        = null;

            Interop.WIN32_FIND_DATA data = new Interop.WIN32_FIND_DATA();
            try
            {
                // Get all files and dirs
                hnd = Interop.mincore.FindFirstFile(searchPath, ref data);

                if (hnd.IsInvalid)
                {
                    int errorCode = Marshal.GetLastWin32Error();

                    // This could happen if the dir doesn't contain any files.
                    // Continue with the recursive search though, eventually
                    // searchStack will become empty
                    if (errorCode == Interop.ERROR_FILE_NOT_FOUND || errorCode == Interop.ERROR_NO_MORE_FILES || errorCode == Interop.ERROR_PATH_NOT_FOUND)
                    {
                        return;
                    }

                    HandleError(errorCode, localSearchData.fullPath);
                }

                // Add subdirs to searchStack. Exempt ReparsePoints as appropriate
                int incr = 0;
                do
                {
                    if (Win32FileSystemEnumerableHelpers.IsDir(data))
                    {
                        Contract.Assert(data.cFileName.Length != 0 && !Path.IsPathRooted(data.cFileName),
                                        "Expected file system enumeration to not have empty file/directory name and not have rooted name");

                        String tempFullPath = Path.Combine(localSearchData.fullPath, data.cFileName);
                        String tempUserPath = Path.Combine(localSearchData.userPath, data.cFileName);

                        SearchOption option = localSearchData.searchOption;

                        // Setup search data for the sub directory and push it into the stack
                        Directory.SearchData searchDataSubDir = new Directory.SearchData(tempFullPath, tempUserPath, option);

                        _searchStack.Insert(incr++, searchDataSubDir);
                    }
                } while (Interop.mincore.FindNextFile(hnd, ref data));
                // We don't care about errors here
            }
            finally
            {
                if (hnd != null)
                {
                    hnd.Dispose();
                }
            }
        }
        internal SearchResult(String fullPath, String userPath, Interop.WIN32_FIND_DATA findData)
        {
            Contract.Requires(fullPath != null);
            Contract.Requires(userPath != null);

            this._fullPath = fullPath;
            this._userPath = userPath;
            this._findData = findData;
        }
        private void CommonInit()
        {
            Contract.Assert(_searchCriteria != null && _searchData != null, "searchCriteria and searchData should be initialized");

            // Execute searchCriteria against the current directory
            PathHelpers.ThrowIfEmptyOrRootedPath(_searchCriteria);
            String searchPath = Path.Combine(_searchData.fullPath, _searchCriteria);

            Interop.WIN32_FIND_DATA data = new Interop.WIN32_FIND_DATA();

            // Open a Find handle
            _hnd = Interop.mincore.FindFirstFile(searchPath, ref data);

            if (_hnd.IsInvalid)
            {
                int errorCode = Marshal.GetLastWin32Error();
                if (errorCode != Interop.ERROR_FILE_NOT_FOUND && errorCode != Interop.ERROR_NO_MORE_FILES)
                {
                    HandleError(errorCode, _searchData.fullPath);
                }
                else
                {
                    // flag this as empty only if we're searching just top directory
                    // Used in fast path for top directory only
                    _empty = _searchData.searchOption == SearchOption.TopDirectoryOnly;
                }
            }
            // fast path for TopDirectoryOnly. If we have a result, go ahead and set it to
            // current. If empty, dispose handle.
            if (_searchData.searchOption == SearchOption.TopDirectoryOnly)
            {
                if (_empty)
                {
                    _hnd.Dispose();
                }
                else
                {
                    SearchResult searchResult = CreateSearchResult(_searchData, data);
                    if (_resultHandler.IsResultIncluded(searchResult))
                    {
                        current = _resultHandler.CreateObject(searchResult);
                    }
                }
            }
            // for AllDirectories, we first recurse into dirs, so cleanup and add searchData
            // to the stack
            else
            {
                _hnd.Dispose();
                _searchStack.Add(_searchData);
            }
        }
Beispiel #4
0
 public Win32FileSystemObject(string fullPath, Interop.WIN32_FIND_DATA findData, bool asDirectory)
 {
     _fullPath = fullPath;
     // Copy the information to data
     _data.fileAttributes       = (int)findData.dwFileAttributes;
     _data.ftCreationTimeLow    = findData.ftCreationTime.dwLowDateTime;
     _data.ftCreationTimeHigh   = findData.ftCreationTime.dwHighDateTime;
     _data.ftLastAccessTimeLow  = findData.ftLastAccessTime.dwLowDateTime;
     _data.ftLastAccessTimeHigh = findData.ftLastAccessTime.dwHighDateTime;
     _data.ftLastWriteTimeLow   = findData.ftLastWriteTime.dwLowDateTime;
     _data.ftLastWriteTimeHigh  = findData.ftLastWriteTime.dwHighDateTime;
     _data.fileSizeHigh         = findData.nFileSizeHigh;
     _data.fileSizeLow          = findData.nFileSizeLow;
     _dataInitialised           = 0;
 }
        private bool ShouldUseWinRT(string fullPath, bool isCreate)
        {
            bool useWinRt = false;

            do
            {
                Interop.WIN32_FIND_DATA findData = new Interop.WIN32_FIND_DATA();
                using (SafeFindHandle handle = Interop.mincore.FindFirstFile(fullPath, ref findData))
                {
                    int error = Marshal.GetLastWin32Error();

                    if (handle.IsInvalid)
                    {
                        if (error == Interop.ERROR_ACCESS_DENIED)
                        {
                            // The path was not accessible with Win32, so try WinRT
                            useWinRt = true;
                            break;
                        }
                        else if (error != Interop.ERROR_PATH_NOT_FOUND && error != Interop.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;
                        }
                    }
                    else
                    {
                        // Use WinRT for placeholder files
                        useWinRt = IsPlaceholderFile(findData);
                        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);
        }
Beispiel #6
0
 internal static SafeFindHandle FindFirstFile(String fileName, ref Interop.WIN32_FIND_DATA data)
 {
     // use FindExInfoBasic since we don't care about short name and it has better perf
     return(FindFirstFileEx(fileName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0));
 }
 private static bool IsPlaceholderFile(Interop.WIN32_FIND_DATA findData)
 {
     return((findData.dwFileAttributes & Interop.FILE_ATTRIBUTE_DIRECTORY) == 0 &&
            (findData.dwFileAttributes & Interop.FILE_ATTRIBUTE_REPARSE_POINT) != 0 &&
            (findData.dwReserved0 == Interop.IO_REPARSE_TAG_FILE_PLACEHOLDER));
 }
 [System.Security.SecurityCritical]  // auto-generated
 internal static bool IsFile(Interop.WIN32_FIND_DATA data)
 {
     return(0 == (data.dwFileAttributes & Interop.FILE_ATTRIBUTE_DIRECTORY));
 }
 [System.Security.SecurityCritical]  // auto-generated
 internal static bool IsDir(Interop.WIN32_FIND_DATA data)
 {
     // Don't add "." nor ".."
     return((0 != (data.dwFileAttributes & Interop.FILE_ATTRIBUTE_DIRECTORY)) &&
            !data.cFileName.Equals(".") && !data.cFileName.Equals(".."));
 }
Beispiel #10
0
        [System.Security.SecurityCritical]  // auto-generated
        internal static int FillAttributeInfo(String path, ref Interop.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.WIN32_FIND_DATA findData;
                findData = new Interop.WIN32_FIND_DATA();

                // Remove trialing slash since this can cause grief to FindFirstFile. You will get an invalid argument error
                String tempPath = path.TrimEnd(PathHelpers.DirectorySeparatorChars);

                // 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.
                // SetErrorMode will let us disable this, but we should set the error
                // mode back, since this may have wide-ranging effects.
                uint oldMode = Interop.mincore.SetErrorMode(Interop.SEM_FAILCRITICALERRORS);
                try
                {
                    bool error = false;
                    SafeFindHandle handle = Interop.mincore.FindFirstFile(tempPath, ref findData);
                    try
                    {
                        if (handle.IsInvalid)
                        {
                            error = true;
                            errorCode = Marshal.GetLastWin32Error();

                            if (errorCode == Interop.ERROR_FILE_NOT_FOUND ||
                                errorCode == Interop.ERROR_PATH_NOT_FOUND ||
                                errorCode == Interop.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
                {
                    Interop.mincore.SetErrorMode(oldMode);
                }

                // Copy the information to data
                data.PopulateFrom(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.
                // SetErrorMode 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 = Interop.mincore.SetErrorMode(Interop.SEM_FAILCRITICALERRORS);
                try
                {
                    success = Interop.mincore.GetFileAttributesEx(path, Interop.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data);
                }
                finally
                {
                    Interop.mincore.SetErrorMode(oldMode);
                }

                if (!success)
                {
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode != Interop.ERROR_FILE_NOT_FOUND &&
                        errorCode != Interop.ERROR_PATH_NOT_FOUND &&
                        errorCode != Interop.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 compbatibility
                            errorCode = 0;
                            data.fileAttributes = -1;
                        }
                    }
                }
            }

            return errorCode;
        }
        private SearchResult CreateSearchResult(Directory.SearchData localSearchData, Interop.WIN32_FIND_DATA findData)
        {
            string findData_fileName = findData.cFileName;

            Contract.Requires(findData_fileName.Length != 0 && !Path.IsPathRooted(findData_fileName),
                              "Expected file system enumeration to not have empty file/directory name and not have rooted name");

            String userPathFinal = Path.Combine(localSearchData.userPath, findData_fileName);
            String fullPathFinal = Path.Combine(localSearchData.fullPath, findData_fileName);

            return(new SearchResult(fullPathFinal, userPathFinal, findData));
        }
        public override bool MoveNext()
        {
            Interop.WIN32_FIND_DATA data = new Interop.WIN32_FIND_DATA();
            switch (state)
            {
            case STATE_INIT:
            {
                if (_empty)
                {
                    state = STATE_FINISH;
                    goto case STATE_FINISH;
                }
                if (_searchData.searchOption == SearchOption.TopDirectoryOnly)
                {
                    state = STATE_FIND_NEXT_FILE;
                    if (current != null)
                    {
                        return(true);
                    }
                    else
                    {
                        goto case STATE_FIND_NEXT_FILE;
                    }
                }
                else
                {
                    state = STATE_SEARCH_NEXT_DIR;
                    goto case STATE_SEARCH_NEXT_DIR;
                }
            }

            case STATE_SEARCH_NEXT_DIR:
            {
                Contract.Assert(_searchData.searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly");
                // Traverse directory structure. We need to get '*'
                while (_searchStack.Count > 0)
                {
                    _searchData = _searchStack[0];
                    Contract.Assert((_searchData.fullPath != null), "fullpath can't be null!");
                    _searchStack.RemoveAt(0);

                    // Traverse the subdirs
                    AddSearchableDirsToStack(_searchData);

                    // Execute searchCriteria against the current directory
                    String searchPath = Path.Combine(_searchData.fullPath, _searchCriteria);

                    // Open a Find handle
                    _hnd = Interop.mincore.FindFirstFile(searchPath, ref data);
                    if (_hnd.IsInvalid)
                    {
                        int errorCode = Marshal.GetLastWin32Error();
                        if (errorCode == Interop.ERROR_FILE_NOT_FOUND || errorCode == Interop.ERROR_NO_MORE_FILES || errorCode == Interop.ERROR_PATH_NOT_FOUND)
                        {
                            continue;
                        }

                        _hnd.Dispose();
                        HandleError(errorCode, _searchData.fullPath);
                    }

                    state = STATE_FIND_NEXT_FILE;

                    SearchResult searchResult = CreateSearchResult(_searchData, data);
                    if (_resultHandler.IsResultIncluded(searchResult))
                    {
                        current = _resultHandler.CreateObject(searchResult);
                        return(true);
                    }
                    else
                    {
                        goto case STATE_FIND_NEXT_FILE;
                    }
                }
                state = STATE_FINISH;
                goto case STATE_FINISH;
            }

            case STATE_FIND_NEXT_FILE:
            {
                if (_searchData != null && _hnd != null)
                {
                    // Keep asking for more matching files/dirs, add it to the list
                    while (Interop.mincore.FindNextFile(_hnd, ref data))
                    {
                        SearchResult searchResult = CreateSearchResult(_searchData, data);
                        if (_resultHandler.IsResultIncluded(searchResult))
                        {
                            current = _resultHandler.CreateObject(searchResult);
                            return(true);
                        }
                    }

                    // Make sure we quit with a sensible error.
                    int errorCode = Marshal.GetLastWin32Error();

                    if (_hnd != null)
                    {
                        _hnd.Dispose();
                    }

                    // ERROR_FILE_NOT_FOUND is valid here because if the top level
                    // dir doen't contain any subdirs and matching files then
                    // we will get here with this errorcode from the searchStack walk
                    if ((errorCode != 0) && (errorCode != Interop.ERROR_NO_MORE_FILES) &&
                        (errorCode != Interop.ERROR_FILE_NOT_FOUND))
                    {
                        HandleError(errorCode, _searchData.fullPath);
                    }
                }
                if (_searchData.searchOption == SearchOption.TopDirectoryOnly)
                {
                    state = STATE_FINISH;
                    goto case STATE_FINISH;
                }
                else
                {
                    state = STATE_SEARCH_NEXT_DIR;
                    goto case STATE_SEARCH_NEXT_DIR;
                }
            }

            case STATE_FINISH:
            {
                Dispose();
                break;
            }
            }
            return(false);
        }
        private 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.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.WIN32_FILE_ATTRIBUTE_DATA();
                if (Interop.mincore.GetFileAttributesEx(fullPath, Interop.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data))
                {
                    // got the attributes
                    if ((data.fileAttributes & Interop.FILE_ATTRIBUTE_DIRECTORY) != 0 ||
                        (data.fileAttributes & Interop.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.WIN32_FIND_DATA findData = new Interop.WIN32_FIND_DATA();
                        using (SafeFindHandle handle = Interop.mincore.FindFirstFile(fullPath, ref findData))
                        {
                            if (!handle.IsInvalid)
                            {
                                // got the find data, use WinRT for placeholder files

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

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

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

                if (error == Interop.ERROR_ACCESS_DENIED)
                {
                    // The path was not accessible with Win32, so try WinRT
                    useWinRt = true;
                    break;
                }
                else if (error != Interop.ERROR_PATH_NOT_FOUND && error != Interop.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);
        }
Beispiel #14
0
        [System.Security.SecurityCritical]  // auto-generated
        private static void RemoveDirectoryHelper(String fullPath, bool recursive, bool throwOnTopLevelDirectoryNotFound)
        {
            bool r;
            int errorCode;
            Exception ex = null;

            // 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.
            // Note the logic to check whether fullPath is a reparse point is
            // in Delete(String, String, bool), and will set "recursive" to false.
            // Note that Win32's DeleteFile and RemoveDirectory will just delete
            // the reparse point itself.

            if (recursive)
            {
                Interop.WIN32_FIND_DATA data = new Interop.WIN32_FIND_DATA();

                // Open a Find handle
                using (SafeFindHandle hnd = Interop.mincore.FindFirstFile(fullPath + PathHelpers.DirectorySeparatorCharAsString + "*", ref data))
                {
                    if (hnd.IsInvalid)
                        throw Win32Marshal.GetExceptionForLastWin32Error(fullPath);

                    do
                    {
                        bool isDir = (0 != (data.dwFileAttributes & Interop.FILE_ATTRIBUTE_DIRECTORY));
                        if (isDir)
                        {
                            // Skip ".", "..".
                            if (data.cFileName.Equals(".") || data.cFileName.Equals(".."))
                                continue;

                            // Recurse for all directories, unless they are 
                            // reparse points.  Do not follow mount points nor
                            // symbolic links, but do delete the reparse point 
                            // itself.
                            bool shouldRecurse = (0 == (data.dwFileAttributes & (int)FileAttributes.ReparsePoint));
                            if (shouldRecurse)
                            {
                                String newFullPath = Path.Combine(fullPath, data.cFileName);
                                try
                                {
                                    RemoveDirectoryHelper(newFullPath, recursive, false);
                                }
                                catch (Exception e)
                                {
                                    if (ex == null)
                                        ex = e;
                                }
                            }
                            else
                            {
                                // Check to see if this is a mount point, and
                                // unmount it.
                                if (data.dwReserved0 == Interop.IO_REPARSE_TAG_MOUNT_POINT)
                                {
                                    // Use full path plus a trailing '\'
                                    String mountPoint = Path.Combine(fullPath, data.cFileName + PathHelpers.DirectorySeparatorCharAsString);
                                    r = Interop.mincore.DeleteVolumeMountPoint(mountPoint);
                                    if (!r)
                                    {
                                        errorCode = Marshal.GetLastWin32Error();
                                        if (errorCode != Interop.ERROR_PATH_NOT_FOUND)
                                        {
                                            try
                                            {
                                                throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName);
                                            }
                                            catch (Exception e)
                                            {
                                                if (ex == null)
                                                    ex = e;
                                            }
                                        }
                                    }
                                }

                                // RemoveDirectory on a symbolic link will
                                // remove the link itself.
                                String reparsePoint = Path.Combine(fullPath, data.cFileName);
                                r = Interop.mincore.RemoveDirectory(reparsePoint);
                                if (!r)
                                {
                                    errorCode = Marshal.GetLastWin32Error();
                                    if (errorCode != Interop.ERROR_PATH_NOT_FOUND)
                                    {
                                        try
                                        {
                                            throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName);
                                        }
                                        catch (Exception e)
                                        {
                                            if (ex == null)
                                                ex = e;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            String fileName = Path.Combine(fullPath, data.cFileName);
                            r = Interop.mincore.DeleteFile(fileName);
                            if (!r)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                                if (errorCode != Interop.ERROR_FILE_NOT_FOUND)
                                {
                                    try
                                    {
                                        throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName);
                                    }
                                    catch (Exception e)
                                    {
                                        if (ex == null)
                                            ex = e;
                                    }
                                }
                            }
                        }
                    } while (Interop.mincore.FindNextFile(hnd, ref data));
                    // Make sure we quit with a sensible error.
                    errorCode = Marshal.GetLastWin32Error();
                }

                if (ex != null)
                    throw ex;
                if (errorCode != 0 && errorCode != Interop.ERROR_NO_MORE_FILES)
                    throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            r = Interop.mincore.RemoveDirectory(fullPath);

            if (!r)
            {
                errorCode = Marshal.GetLastWin32Error();
                if (errorCode == Interop.ERROR_FILE_NOT_FOUND) // A dubious error code.
                    errorCode = Interop.ERROR_PATH_NOT_FOUND;
                // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons.
                if (errorCode == Interop.ERROR_ACCESS_DENIED)
                    throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath));

                // don't throw the DirectoryNotFoundException since this is a subdir and 
                // there could be a race condition between two Directory.Delete callers
                if (errorCode == Interop.ERROR_PATH_NOT_FOUND && !throwOnTopLevelDirectoryNotFound)
                    return;

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }
        }
Beispiel #15
0
        [System.Security.SecurityCritical]  // auto-generated
        internal static int FillAttributeInfo(String path, ref Interop.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.WIN32_FIND_DATA findData;
                findData = new Interop.WIN32_FIND_DATA();

                // Remove trialing slash since this can cause grief to FindFirstFile. You will get an invalid argument error
                String tempPath = path.TrimEnd(PathHelpers.DirectorySeparatorChars);

                // 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.
                // SetErrorMode will let us disable this, but we should set the error
                // mode back, since this may have wide-ranging effects.
                uint oldMode = Interop.mincore.SetErrorMode(Interop.SEM_FAILCRITICALERRORS);
                try
                {
                    bool           error  = false;
                    SafeFindHandle handle = Interop.mincore.FindFirstFile(tempPath, ref findData);
                    try
                    {
                        if (handle.IsInvalid)
                        {
                            error     = true;
                            errorCode = Marshal.GetLastWin32Error();

                            if (errorCode == Interop.ERROR_FILE_NOT_FOUND ||
                                errorCode == Interop.ERROR_PATH_NOT_FOUND ||
                                errorCode == Interop.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
                {
                    Interop.mincore.SetErrorMode(oldMode);
                }

                // Copy the information to data
                data.PopulateFrom(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.
                // SetErrorMode 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 = Interop.mincore.SetErrorMode(Interop.SEM_FAILCRITICALERRORS);
                try
                {
                    success = Interop.mincore.GetFileAttributesEx(path, Interop.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data);
                }
                finally
                {
                    Interop.mincore.SetErrorMode(oldMode);
                }

                if (!success)
                {
                    errorCode = Marshal.GetLastWin32Error();
                    if (errorCode != Interop.ERROR_FILE_NOT_FOUND &&
                        errorCode != Interop.ERROR_PATH_NOT_FOUND &&
                        errorCode != Interop.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);
        }
Beispiel #16
0
        [System.Security.SecurityCritical]  // auto-generated
        private static void RemoveDirectoryHelper(String fullPath, bool recursive, bool throwOnTopLevelDirectoryNotFound)
        {
            bool      r;
            int       errorCode;
            Exception ex = null;

            // 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.
            // Note the logic to check whether fullPath is a reparse point is
            // in Delete(String, String, bool), and will set "recursive" to false.
            // Note that Win32's DeleteFile and RemoveDirectory will just delete
            // the reparse point itself.

            if (recursive)
            {
                Interop.WIN32_FIND_DATA data = new Interop.WIN32_FIND_DATA();

                // Open a Find handle
                using (SafeFindHandle hnd = Interop.mincore.FindFirstFile(fullPath + PathHelpers.DirectorySeparatorCharAsString + "*", ref data))
                {
                    if (hnd.IsInvalid)
                    {
                        throw Win32Marshal.GetExceptionForLastWin32Error(fullPath);
                    }

                    do
                    {
                        bool isDir = (0 != (data.dwFileAttributes & Interop.FILE_ATTRIBUTE_DIRECTORY));
                        if (isDir)
                        {
                            // Skip ".", "..".
                            if (data.cFileName.Equals(".") || data.cFileName.Equals(".."))
                            {
                                continue;
                            }

                            // Recurse for all directories, unless they are
                            // reparse points.  Do not follow mount points nor
                            // symbolic links, but do delete the reparse point
                            // itself.
                            bool shouldRecurse = (0 == (data.dwFileAttributes & (int)FileAttributes.ReparsePoint));
                            if (shouldRecurse)
                            {
                                String newFullPath = Path.Combine(fullPath, data.cFileName);
                                try
                                {
                                    RemoveDirectoryHelper(newFullPath, recursive, false);
                                }
                                catch (Exception e)
                                {
                                    if (ex == null)
                                    {
                                        ex = e;
                                    }
                                }
                            }
                            else
                            {
                                // Check to see if this is a mount point, and
                                // unmount it.
                                if (data.dwReserved0 == Interop.IO_REPARSE_TAG_MOUNT_POINT)
                                {
                                    // Use full path plus a trailing '\'
                                    String mountPoint = Path.Combine(fullPath, data.cFileName + PathHelpers.DirectorySeparatorCharAsString);
                                    r = Interop.mincore.DeleteVolumeMountPoint(mountPoint);
                                    if (!r)
                                    {
                                        errorCode = Marshal.GetLastWin32Error();
                                        if (errorCode != Interop.ERROR_PATH_NOT_FOUND)
                                        {
                                            try
                                            {
                                                throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName);
                                            }
                                            catch (Exception e)
                                            {
                                                if (ex == null)
                                                {
                                                    ex = e;
                                                }
                                            }
                                        }
                                    }
                                }

                                // RemoveDirectory on a symbolic link will
                                // remove the link itself.
                                String reparsePoint = Path.Combine(fullPath, data.cFileName);
                                r = Interop.mincore.RemoveDirectory(reparsePoint);
                                if (!r)
                                {
                                    errorCode = Marshal.GetLastWin32Error();
                                    if (errorCode != Interop.ERROR_PATH_NOT_FOUND)
                                    {
                                        try
                                        {
                                            throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName);
                                        }
                                        catch (Exception e)
                                        {
                                            if (ex == null)
                                            {
                                                ex = e;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            String fileName = Path.Combine(fullPath, data.cFileName);
                            r = Interop.mincore.DeleteFile(fileName);
                            if (!r)
                            {
                                errorCode = Marshal.GetLastWin32Error();
                                if (errorCode != Interop.ERROR_FILE_NOT_FOUND)
                                {
                                    try
                                    {
                                        throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName);
                                    }
                                    catch (Exception e)
                                    {
                                        if (ex == null)
                                        {
                                            ex = e;
                                        }
                                    }
                                }
                            }
                        }
                    } while (Interop.mincore.FindNextFile(hnd, ref data));
                    // Make sure we quit with a sensible error.
                    errorCode = Marshal.GetLastWin32Error();
                }

                if (ex != null)
                {
                    throw ex;
                }
                if (errorCode != 0 && errorCode != Interop.ERROR_NO_MORE_FILES)
                {
                    throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
                }
            }

            r = Interop.mincore.RemoveDirectory(fullPath);

            if (!r)
            {
                errorCode = Marshal.GetLastWin32Error();
                if (errorCode == Interop.ERROR_FILE_NOT_FOUND) // A dubious error code.
                {
                    errorCode = Interop.ERROR_PATH_NOT_FOUND;
                }
                // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons.
                if (errorCode == Interop.ERROR_ACCESS_DENIED)
                {
                    throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath));
                }

                // don't throw the DirectoryNotFoundException since this is a subdir and
                // there could be a race condition between two Directory.Delete callers
                if (errorCode == Interop.ERROR_PATH_NOT_FOUND && !throwOnTopLevelDirectoryNotFound)
                {
                    return;
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }
        }
        private bool ShouldUseWinRT(string fullPath, bool isCreate)
        {
            bool useWinRt = false;

            do
            {
                Interop.WIN32_FIND_DATA findData = new Interop.WIN32_FIND_DATA();
                using (SafeFindHandle handle = Interop.mincore.FindFirstFile(fullPath, ref findData))
                {
                    int error = Marshal.GetLastWin32Error();

                    if (handle.IsInvalid)
                    {
                        if (error == Interop.ERROR_ACCESS_DENIED)
                        {
                            // The path was not accessible with Win32, so try WinRT
                            useWinRt = true;
                            break;
                        }
                        else if (error != Interop.ERROR_PATH_NOT_FOUND && error != Interop.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;
                        }
                    }
                    else
                    {
                        // Use WinRT for placeholder files
                        useWinRt = IsPlaceholderFile(findData);
                        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;
        }