public void Dispose()
        {
            if (!_disposed)
            {
                if (_hConnect != IntPtr.Zero)
                {
                    WININET.InternetCloseHandle(_hConnect);
                }

                if (_hInternet != IntPtr.Zero)
                {
                    WININET.InternetCloseHandle(_hInternet);
                }

                _hInternet = IntPtr.Zero;
                _hConnect  = IntPtr.Zero;

                _disposed = true;
                GC.SuppressFinalize(this);
            }
        }
        /// <summary>
        /// Gets details of all directories and their available FTP directory information from the current working FTP directory that match the directory mask.
        /// </summary>
        /// <returns>A <see cref="FtpDirectoryInfo[]"/> representing the directories in the current working directory that match the mask.</returns>
        public FtpDirectoryInfo[] GetDirectories(string path)
        {
            WINAPI.WIN32_FIND_DATA findData = new WINAPI.WIN32_FIND_DATA();

            IntPtr hFindFile = WININET.FtpFindFirstFile(
                _hConnect,
                path,
                ref findData,
                WININET.INTERNET_FLAG_NO_CACHE_WRITE,
                IntPtr.Zero);

            try
            {
                List <FtpDirectoryInfo> directories = new List <FtpDirectoryInfo>();

                if (hFindFile == IntPtr.Zero)
                {
                    if (Marshal.GetLastWin32Error() == WINAPI.ERROR_NO_MORE_FILES)
                    {
                        return(directories.ToArray());
                    }
                    else
                    {
                        Error();
                        return(directories.ToArray());
                    }
                }

                if ((findData.dfFileAttributes & WINAPI.FILE_ATTRIBUTE_DIRECTORY) == WINAPI.FILE_ATTRIBUTE_DIRECTORY)
                {
                    FtpDirectoryInfo dir = new FtpDirectoryInfo(this, new string(findData.fileName).TrimEnd('\0'));
                    dir.LastAccessTime = findData.ftLastAccessTime.ToDateTime();
                    dir.LastWriteTime  = findData.ftLastWriteTime.ToDateTime();
                    dir.CreationTime   = findData.ftCreationTime.ToDateTime();
                    dir.Attributes     = (FileAttributes)findData.dfFileAttributes;
                    directories.Add(dir);
                }

                findData = new WINAPI.WIN32_FIND_DATA();

                while (WININET.InternetFindNextFile(hFindFile, ref findData) != 0)
                {
                    if ((findData.dfFileAttributes & WINAPI.FILE_ATTRIBUTE_DIRECTORY) == WINAPI.FILE_ATTRIBUTE_DIRECTORY)
                    {
                        FtpDirectoryInfo dir = new FtpDirectoryInfo(this, new string(findData.fileName).TrimEnd('\0'));
                        dir.LastAccessTime = findData.ftLastAccessTime.ToDateTime();
                        dir.LastWriteTime  = findData.ftLastWriteTime.ToDateTime();
                        dir.CreationTime   = findData.ftCreationTime.ToDateTime();
                        dir.Attributes     = (FileAttributes)findData.dfFileAttributes;
                        directories.Add(dir);
                    }

                    findData = new WINAPI.WIN32_FIND_DATA();
                }

                if (Marshal.GetLastWin32Error() != WINAPI.ERROR_NO_MORE_FILES)
                {
                    Error();
                }

                return(directories.ToArray());
            }
            finally
            {
                if (hFindFile != IntPtr.Zero)
                {
                    WININET.InternetCloseHandle(hFindFile);
                }
            }
        }
        private List <string> List(string mask, bool onlyDirectories)
        {
            WINAPI.WIN32_FIND_DATA findData = new WINAPI.WIN32_FIND_DATA();

            IntPtr hFindFile = WININET.FtpFindFirstFile(
                _hConnect,
                mask,
                ref findData,
                WININET.INTERNET_FLAG_NO_CACHE_WRITE,
                IntPtr.Zero);

            try
            {
                List <string> files = new List <string>();
                if (hFindFile == IntPtr.Zero)
                {
                    if (Marshal.GetLastWin32Error() == WINAPI.ERROR_NO_MORE_FILES)
                    {
                        return(files);
                    }
                    else
                    {
                        Error();
                        return(files);
                    }
                }

                if (onlyDirectories && (findData.dfFileAttributes & WINAPI.FILE_ATTRIBUTE_DIRECTORY) == WINAPI.FILE_ATTRIBUTE_DIRECTORY)
                {
                    files.Add(new string(findData.fileName).TrimEnd('\0'));
                }
                else if (!onlyDirectories)
                {
                    files.Add(new string(findData.fileName).TrimEnd('\0'));
                }

                findData = new WINAPI.WIN32_FIND_DATA();
                while (WININET.InternetFindNextFile(hFindFile, ref findData) != 0)
                {
                    if (onlyDirectories && (findData.dfFileAttributes & WINAPI.FILE_ATTRIBUTE_DIRECTORY) == WINAPI.FILE_ATTRIBUTE_DIRECTORY)
                    {
                        files.Add(new string(findData.fileName).TrimEnd('\0'));
                    }
                    else if (!onlyDirectories)
                    {
                        files.Add(new string(findData.fileName).TrimEnd('\0'));
                    }
                    findData = new WINAPI.WIN32_FIND_DATA();
                }

                if (Marshal.GetLastWin32Error() != WINAPI.ERROR_NO_MORE_FILES)
                {
                    Error();
                }

                return(files);
            }
            finally
            {
                if (hFindFile != IntPtr.Zero)
                {
                    WININET.InternetCloseHandle(hFindFile);
                }
            }
        }