FileDialog.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / WinForms / Managed / System / WinForms / FileDialog.cs / 1 / FileDialog.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms { 
    using System.Text; 
    using System.Threading;
    using System.Runtime.Remoting; 
    using System.Runtime.InteropServices;

    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 

    using System; 
    using System.Security.Permissions; 
    using System.Drawing;
    using System.ComponentModel; 
    using System.Windows.Forms;
    using System.IO;
    using ArrayList = System.Collections.ArrayList;
 
    using Encoding = System.Text.Encoding;
    using Microsoft.Win32; 
    using System.Security; 
    using CharBuffer = System.Windows.Forms.UnsafeNativeMethods.CharBuffer;
 
    /// 
    /// 
    ///    
    ///       Displays a dialog window from which the user can select a file. 
    ///    
    ///  
    [ 
    DefaultEvent("FileOk"),
    DefaultProperty("FileName") 
    ]
    public abstract partial class FileDialog : CommonDialog {

        private const int FILEBUFSIZE = 8192; 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        /// 
        protected static readonly object EventFileOk = new object();

        internal const int OPTION_ADDEXTENSION = unchecked(unchecked((int)0x80000000)); 

        internal int options; 
 
        private string title;
        private string initialDir; 
        private string defaultExt;
        private string[] fileNames;
        private bool securityCheckFileNames;
        private string filter; 
        private int filterIndex;
        private bool supportMultiDottedExtensions; 
        private bool ignoreSecondFileOkNotification;  // Used for VS Whidbey 95342 
        private int okNotificationCount;              // Same
        private CharBuffer charBuffer; 
        private IntPtr dialogHWnd;

        /// 
        ///  
        ///    
        ///       In an inherited class, 
        ///       initializes a new instance of the  
        ///       class.
        ///     
        /// 
        [
            SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")  // If the constructor does not call Reset
                                                                                                    // it would be a breaking change. 
        ]
        internal FileDialog() { 
            Reset(); 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value indicating whether the 
        ///       dialog box automatically adds an extension to a
        ///       file name if the user omits the extension. 
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        SRDescription(SR.FDaddExtensionDescr)
        ] 
        public bool AddExtension {
            get { 
                return GetOption(OPTION_ADDEXTENSION); 
            }
 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand();
                SetOption(OPTION_ADDEXTENSION, value); 
            }
        } 
 
        /// 
        ///  
        ///    Gets or sets a value indicating whether
        ///       the dialog box displays a warning if the user specifies a file name that does not exist.
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        SRDescription(SR.FDcheckFileExistsDescr) 
        ]
        public virtual bool CheckFileExists { 
            get {
                return GetOption(NativeMethods.OFN_FILEMUSTEXIST);
            }
 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded"); 
                IntSecurity.FileDialogCustomization.Demand(); 
                SetOption(NativeMethods.OFN_FILEMUSTEXIST, value);
            } 
        }

        /// 
        ///  
        ///    
        ///       Gets or sets a value indicating whether the 
        ///       dialog box displays a warning if the user specifies a path that does not exist. 
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        SRDescription(SR.FDcheckPathExistsDescr) 
        ]
        public bool CheckPathExists { 
            get { 
                return GetOption(NativeMethods.OFN_PATHMUSTEXIST);
            } 

            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 
                SetOption(NativeMethods.OFN_PATHMUSTEXIST, value);
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or sets the default file extension.
        /// 
        ///    
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(""), 
        SRDescription(SR.FDdefaultExtDescr)
        ]
        public string DefaultExt {
            get { 
                return defaultExt == null? "": defaultExt;
            } 
 
            set {
                if (value != null) { 
                    if (value.StartsWith("."))
                        value = value.Substring(1);
                    else if (value.Length == 0)
                        value = null; 
                }
                defaultExt = value; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value 
        ///       indicating whether the dialog box returns the location of the file referenced by the shortcut or
        ///       whether it returns the location of the shortcut (.lnk). 
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        SRDescription(SR.FDdereferenceLinksDescr)
        ] 
        public bool DereferenceLinks {
            get { 
                return !GetOption(NativeMethods.OFN_NODEREFERENCELINKS); 
            }
            set { 
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand();
                SetOption(NativeMethods.OFN_NODEREFERENCELINKS, !value);
            } 
        }
 
        internal string DialogCaption { 
            get {
                int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(this, dialogHWnd)); 
                StringBuilder sb = new StringBuilder(textLen+1);
                UnsafeNativeMethods.GetWindowText(new HandleRef(this, dialogHWnd), sb, sb.Capacity);
                return sb.ToString();
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets
        ///       or sets a string containing
        ///       the file name selected in the file dialog box.
        ///     
        /// 
        [ 
        SRCategory(SR.CatData), 
        DefaultValue(""),
        SRDescription(SR.FDfileNameDescr) 
        ]
        public string FileName {
            get {
                if (fileNames == null) { 
                    return "";
                } 
                else { 
                    if (fileNames[0].Length > 0) {
 
                        // See if we need to perform a security check on file names.  We need
                        // to do this if the set of file names was provided by the file dialog.
                        // A developer can set file names through the FileDialog API as well,
                        // but we don't need to check those since the developer can provide any 
                        // name s/he wants.  This is important because it is otherwise possible
                        // to get the FileName property to accept garbage, but throw during get. 
 
                        if (securityCheckFileNames) {
                            Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + fileNames[0] + ") Demanded"); 
                            IntSecurity.DemandFileIO(FileIOPermissionAccess.AllAccess, fileNames[0]);
                        }

                        return fileNames[0]; 
                    }
                    else { 
                        return ""; 
                    }
                } 
            }
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 
                if (value == null) {
                    fileNames = null; 
                } 
                else {
                    fileNames = new string[] {value}; 
                }

                // As the developer has called this API and set the file name with an arbitrary value,
                // we do not need to perform a security check on the name. 
                securityCheckFileNames = false;
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets the file
        ///       names of all selected files in the dialog box. 
        ///    
        ///  
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.FDFileNamesDescr)
        ]
        public string[] FileNames {
            get{ 
                string[] files = FileNamesInternal;
 
                // See if we need to perform a security check on file names.  We need 
                // to do this if the set of file names was provided by the file dialog.
                // A developer can set file names through the FileDialog API as well, 
                // but we don't need to check those since the developer can provide any
                // name s/he wants.  This is important because it is otherwise possible
                // to get the FileName property to accept garbage, but throw during get.
 
                if (securityCheckFileNames) {
                    foreach (string file in files) { 
                        Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + file + ") Demanded"); 
                        IntSecurity.DemandFileIO(FileIOPermissionAccess.AllAccess, file);
                    } 
                }
                return files;
            }
        } 

        internal string[] FileNamesInternal { 
            get { 

                if (fileNames == null) { 
                    return new string[0];
                }
                else {
                    return(string[])fileNames.Clone(); 
                }
            } 
        } 

 
        /// 
        /// 
        ///    
        ///       Gets 
        ///       or sets the current file name filter string,
        ///       which determines the choices that appear in the "Save as file type" or 
        ///       "Files of type" box in the dialog box. 
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(""),
        Localizable(true), 
        SRDescription(SR.FDfilterDescr)
        ] 
        public string Filter { 
            get {
                return filter == null? "": filter; 
            }

            set {
                if (value != filter) { 
                    if (value != null && value.Length > 0) {
                        string[] formats = value.Split('|'); 
                        if (formats == null || formats.Length % 2 != 0) { 
                            throw new ArgumentException(SR.GetString(SR.FileDialogInvalidFilter));
                        } 
                    }
                    else {
                        value = null;
                    } 
                    filter = value;
                } 
            } 
        }
 
        /// 
        /// 
        ///     Extracts the file extensions specified by the current file filter into
        ///     an array of strings.  None of the extensions contain .'s, and the 
        ///     default extension is first.
        ///  
        private string[] FilterExtensions { 
            get {
                string filter = this.filter; 
                ArrayList extensions = new ArrayList();

                // First extension is the default one.  It's a little strange if DefaultExt
                // is not in the filters list, but I guess it's legal. 
                if (defaultExt != null)
                    extensions.Add(defaultExt); 
 
                if (filter != null) {
                    string[] tokens = filter.Split('|'); 

                    if ((filterIndex * 2) - 1 >= tokens.Length) {
                        throw new InvalidOperationException(SR.GetString(SR.FileDialogInvalidFilterIndex));
                    } 

                    if (filterIndex > 0) { 
                        string[] exts = tokens[(filterIndex * 2) - 1].Split(';'); 
                        foreach (string ext in exts) {
                            int i = this.supportMultiDottedExtensions ? ext.IndexOf('.') : ext.LastIndexOf('.'); 
                            if (i >= 0) {
                                extensions.Add(ext.Substring(i + 1, ext.Length - (i + 1)));
                            }
                        } 
                    }
                } 
                string[] temp = new string[extensions.Count]; 
                extensions.CopyTo(temp, 0);
                return temp; 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets the index of the filter currently selected in the file dialog box. 
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(1),
        SRDescription(SR.FDfilterIndexDescr) 
        ]
        public int FilterIndex { 
            get { 
                return filterIndex;
            } 

            set {
                filterIndex = value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets the initial directory displayed by the file dialog
        ///       box.
        ///    
        ///  
        [
        SRCategory(SR.CatData), 
        DefaultValue(""), 
        SRDescription(SR.FDinitialDirDescr)
        ] 
        public string InitialDirectory {
            get {
                return initialDir == null? "": initialDir;
            } 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded"); 
                IntSecurity.FileDialogCustomization.Demand(); 

                initialDir = value; 
            }
        }

        ///  
        /// 
        ///  
        ///     
        ///       Gets the Win32 instance handle for the application.
        ///     
        /// 
        /* SECURITYUNDONE : should require EventQueue permission */
        protected virtual IntPtr Instance {
            [ 
                SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
                SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
            ] 
            get { return UnsafeNativeMethods.GetModuleHandle(null); }
        } 

        /// 
        /// 
        ///  
        ///    
        ///       Gets the Win32 common Open File Dialog OFN_* option flags. 
        ///     
        /// 
        protected int Options { 
            get {
                return options & (NativeMethods.OFN_READONLY | NativeMethods.OFN_HIDEREADONLY |
                                  NativeMethods.OFN_NOCHANGEDIR | NativeMethods.OFN_SHOWHELP | NativeMethods.OFN_NOVALIDATE |
                                  NativeMethods.OFN_ALLOWMULTISELECT | NativeMethods.OFN_PATHMUSTEXIST | 
                                  NativeMethods.OFN_NODEREFERENCELINKS);
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or sets a value indicating whether the dialog box restores the current directory before
        ///       closing. 
        ///    
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        SRDescription(SR.FDrestoreDirectoryDescr)
        ]
        public bool RestoreDirectory {
            get { 
                return GetOption(NativeMethods.OFN_NOCHANGEDIR);
            } 
            set { 
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 

                SetOption(NativeMethods.OFN_NOCHANGEDIR, value);
            }
        } 

 
        ///  
        /// 
        ///     
        ///       Gets or sets a value indicating
        ///       whether whether the Help button is displayed in the file dialog.
        ///
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.FDshowHelpDescr) 
        ]
        public bool ShowHelp {
            get {
                return GetOption(NativeMethods.OFN_SHOWHELP); 
            }
            set { 
                SetOption(NativeMethods.OFN_SHOWHELP, value); 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets whether def or abc.def is the extension of the file filename.abc.def
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.FDsupportMultiDottedExtensionsDescr)
        ]
        public bool SupportMultiDottedExtensions 
        {
            get 
            { 
                return this.supportMultiDottedExtensions;
            } 
            set
            {
                this.supportMultiDottedExtensions = value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets the file dialog box title.
        ///    
        /// 
        [ 
        SRCategory(SR.CatAppearance),
        DefaultValue(""), 
        Localizable(true), 
        SRDescription(SR.FDtitleDescr)
        ] 
        public string Title {
            get {
                return title == null? "": title;
            } 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded"); 
                IntSecurity.FileDialogCustomization.Demand(); 

                title = value; 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets a value indicating whether the dialog box accepts only valid 
        ///       Win32 file names.
        ///     
        /// 
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(true), 
        SRDescription(SR.FDvalidateNamesDescr)
        ] 
        public bool ValidateNames { 
            get {
                return !GetOption(NativeMethods.OFN_NOVALIDATE); 
            }
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 

                SetOption(NativeMethods.OFN_NOVALIDATE, !value); 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Occurs when the user clicks on the Open or Save button on a file dialog 
        ///       box.
        ///     
        ///  
        ///    
        ///       For information about handling events, see . 
        ///    
        /// 
        /// 
        [SRDescription(SR.FDfileOkDescr)] 
        public event CancelEventHandler FileOk {
            add { 
                Events.AddHandler(EventFileOk, value); 
            }
            remove { 
                Events.RemoveHandler(EventFileOk, value);
            }
        }
 
        /// 
        ///  
        ///     Processes the CDN_FILEOK notification. 
        /// 
        private bool DoFileOk(IntPtr lpOFN) { 
            NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(lpOFN, typeof(NativeMethods.OPENFILENAME_I));
            int saveOptions = options;
            int saveFilterIndex = filterIndex;
            string[] saveFileNames = fileNames; 
            bool saveSecurityCheckFileNames = securityCheckFileNames;
            bool ok = false; 
            try { 
                options = options & ~NativeMethods.OFN_READONLY |
                          ofn.Flags & NativeMethods.OFN_READONLY; 
                filterIndex = ofn.nFilterIndex;
                charBuffer.PutCoTaskMem(ofn.lpstrFile);

                // We are filling in the file names list with secure 
                // data.  Any access to this list now will require
                // a security demand.  We set this bit before actually 
                // setting the names; otherwise a thread ---- could 
                // expose them.
                securityCheckFileNames = true; 
                Thread.MemoryBarrier();

                if ((options & NativeMethods.OFN_ALLOWMULTISELECT) == 0) {
                    fileNames = new string[] {charBuffer.GetString()}; 
                }
                else { 
                    fileNames = GetMultiselectFiles(charBuffer); 
                }
 
                if (ProcessFileNames()) {
                    CancelEventArgs ceevent = new CancelEventArgs();
                    if (NativeWindow.WndProcShouldBeDebuggable) {
                        OnFileOk(ceevent); 
                        ok = !ceevent.Cancel;
                    } 
                    else { 
                        try
                        { 
                            OnFileOk(ceevent);
                            ok = !ceevent.Cancel;
                        }
                        catch (Exception e) 
                        {
                            Application.OnThreadException(e); 
                        } 
                    }
                } 
            }
            finally {
                if (!ok) {
                    securityCheckFileNames = saveSecurityCheckFileNames; 
                    Thread.MemoryBarrier();
                    fileNames = saveFileNames; 
 
                    options = saveOptions;
                    filterIndex = saveFilterIndex; 
                }
            }
            return ok;
        } 

        /// SECREVIEW: ReviewImperativeSecurity 
        ///   vulnerability to watch out for: A method uses imperative security and might be constructing the permission using state information or return values that can change while the demand is active. 
        ///   reason for exclude: filename is a local variable and not subject to race conditions.
        [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")] 
        internal static bool FileExists(string fileName)
        {
            bool fileExists = false;
            try { 
                // SECREVIEW : We must Assert just to check if the file exists. Since
                //           : we are doing this as part of the FileDialog, this is OK. 
                new FileIOPermission(FileIOPermissionAccess.Read, IntSecurity.UnsafeGetFullPath(fileName)).Assert(); 
                try {
                    fileExists = File.Exists(fileName); 
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                } 
            }
            catch (System.IO.PathTooLongException) { 
            } 
            return fileExists;
        } 

        /// 
        /// 
        ///     Extracts the filename(s) returned by the file dialog. 
        /// 
        private string[] GetMultiselectFiles(CharBuffer charBuffer) { 
            string directory = charBuffer.GetString(); 
            string fileName = charBuffer.GetString();
            if (fileName.Length == 0) return new string[] { 
                    directory
                };
            if (directory[directory.Length - 1] != '\\') {
                directory = directory + "\\"; 
            }
            ArrayList names = new ArrayList(); 
            do { 
                if (fileName[0] != '\\' && (fileName.Length <= 3 ||
                                            fileName[1] != ':' || fileName[2] != '\\')) { 
                    fileName = directory + fileName;
                }
                names.Add(fileName);
                fileName = charBuffer.GetString(); 
            } while (fileName.Length > 0);
            string[] temp = new string[names.Count]; 
            names.CopyTo(temp, 0); 
            return temp;
        } 

        /// 
        /// 
        ///     Returns the state of the given option flag. 
        /// 
        ///  
 
        internal bool GetOption(int option) {
            return(options & option) != 0; 
        }

        /// 
        ///  
        ///    
        ///       Defines the common dialog box hook procedure that is overridden to add 
        ///       specific functionality to the file dialog box. 
        ///    
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) {
            if (msg == NativeMethods.WM_NOTIFY) {
                dialogHWnd = UnsafeNativeMethods.GetParent(new HandleRef(null, hWnd)); 
                try {
                    UnsafeNativeMethods.OFNOTIFY notify = (UnsafeNativeMethods.OFNOTIFY)UnsafeNativeMethods.PtrToStructure(lparam, typeof(UnsafeNativeMethods.OFNOTIFY)); 
 
                    switch (notify.hdr_code) {
                        case -601: /* CDN_INITDONE */ 
                            MoveToScreenCenter(dialogHWnd);
                            break;
                        case -602: /* CDN_SELCHANGE */
                            NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(notify.lpOFN, typeof(NativeMethods.OPENFILENAME_I)); 
                            // Get the buffer size required to store the selected file names.
                            int sizeNeeded = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, dialogHWnd), 1124 /*CDM_GETSPEC*/, System.IntPtr.Zero, System.IntPtr.Zero); 
                            if (sizeNeeded > ofn.nMaxFile) { 
                                // A bigger buffer is required.
                                try { 
                                    int newBufferSize = sizeNeeded + (FILEBUFSIZE / 4);
                                    // Allocate new buffer
                                    CharBuffer charBufferTmp = CharBuffer.CreateBuffer(newBufferSize);
                                    IntPtr newBuffer = charBufferTmp.AllocCoTaskMem(); 
                                    // Free old buffer
                                    Marshal.FreeCoTaskMem(ofn.lpstrFile); 
                                    // Substitute buffer 
                                    ofn.lpstrFile = newBuffer;
                                    ofn.nMaxFile = newBufferSize; 
                                    this.charBuffer = charBufferTmp;
                                    Marshal.StructureToPtr(ofn, notify.lpOFN, true);
                                    Marshal.StructureToPtr(notify, lparam, true);
                                } 
                                catch {
                                    // intentionaly not throwing here. 
                                } 
                            }
                            this.ignoreSecondFileOkNotification = false; 
                            break;
                        case -604: /* CDN_SHAREVIOLATION */
                            // See VS Whidbey 95342. When the selected file is locked for writing,
                            // we get this notification followed by *two* CDN_FILEOK notifications. 
                            this.ignoreSecondFileOkNotification = true;  // We want to ignore the second CDN_FILEOK
                            this.okNotificationCount = 0;                // to avoid a second prompt by PromptFileOverwrite. 
                            break; 
                        case -606: /* CDN_FILEOK */
                            if (this.ignoreSecondFileOkNotification) 
                            {
                                // We got a CDN_SHAREVIOLATION notification and want to ignore the second CDN_FILEOK notification
                                if (this.okNotificationCount == 0)
                                { 
                                    this.okNotificationCount = 1;   // This one is the first and is all right.
                                } 
                                else 
                                {
                                    // This is the second CDN_FILEOK, so we want to ignore it. 
                                    this.ignoreSecondFileOkNotification = false;
                                    UnsafeNativeMethods.SetWindowLong(new HandleRef(null, hWnd), 0, new HandleRef(null, NativeMethods.InvalidIntPtr));
                                    return NativeMethods.InvalidIntPtr;
                                } 
                            }
                            if (!DoFileOk(notify.lpOFN)) { 
                                UnsafeNativeMethods.SetWindowLong(new HandleRef(null, hWnd), 0, new HandleRef(null, NativeMethods.InvalidIntPtr)); 
                                return NativeMethods.InvalidIntPtr;
                            } 
                            break;
                    }
                }
                catch { 
                    if (dialogHWnd != IntPtr.Zero) {
                        UnsafeNativeMethods.EndDialog(new HandleRef(this, dialogHWnd), IntPtr.Zero); 
                    } 
                    throw;
                } 
            }
            return IntPtr.Zero;
        }
 
        /// 
        ///  
        ///     Converts the given filter string to the format required in an OPENFILENAME_I 
        ///     structure.
        ///  
        private static string MakeFilterString(string s, bool dereferenceLinks) {
            if (s == null || s.Length == 0)
            {
                // Workaround for Whidbey bug #5165 
                // Apply the workaround only when DereferenceLinks is true and OS is at least WinXP.
                if (dereferenceLinks && System.Environment.OSVersion.Version.Major >= 5) 
                { 
                    s = " |*.*";
                } 
                else if (s == null)
                {
                    return null;
                } 
            }
            int length = s.Length; 
            char[] filter = new char[length + 2]; 
            s.CopyTo(0, filter, 0, length);
            for (int i = 0; i < length; i++) { 
                if (filter[i] == '|') filter[i] = (char)0;
            }
            filter[length + 1] = (char)0;
            return new string(filter); 
        }
 
        ///  
        /// 
        ///     
        ///       Raises the  event.
        ///    
        /// 
        protected void OnFileOk(CancelEventArgs e) { 
            CancelEventHandler handler = (CancelEventHandler)Events[EventFileOk];
            if (handler != null) handler(this, e); 
        } 

        ///  
        /// 
        ///     Processes the filenames entered in the dialog according to the settings
        ///     of the "addExtension", "checkFileExists", "createPrompt", and
        ///     "overwritePrompt" properties. 
        /// 
        private bool ProcessFileNames() { 
            if ((options & NativeMethods.OFN_NOVALIDATE) == 0) { 
                string[] extensions = FilterExtensions;
                for (int i = 0; i < fileNames.Length; i++) { 
                    string fileName = fileNames[i];
                    if ((options & OPTION_ADDEXTENSION) != 0 && !Path.HasExtension(fileName)) {
                        bool fileMustExist = (options & NativeMethods.OFN_FILEMUSTEXIST) != 0;
 
                        for (int j = 0; j < extensions.Length; j++) {
                            string currentExtension = Path.GetExtension(fileName); 
 
                            Debug.Assert(!extensions[j].StartsWith("."),
                                         "FileDialog.FilterExtensions should not return things starting with '.'"); 
                            Debug.Assert(currentExtension.Length == 0 || currentExtension.StartsWith("."),
                                         "File.GetExtension should return something that starts with '.'");

                            string s = fileName.Substring(0, fileName.Length - currentExtension.Length); 

                            // we don't want to append the extension if it contains wild cards 
                            if (extensions[j].IndexOfAny(new char[] { '*', '?' }) == -1) { 
                                s += "." + extensions[j];
                            } 

                            if (!fileMustExist || FileExists(s)) {
                                fileName = s;
                                break; 
                            }
                        } 
                        fileNames[i] = fileName; 
                    }
                    if (!PromptUserIfAppropriate(fileName)) 
                        return false;
                }
            }
            return true; 
        }
 
        ///  
        /// 
        ///     
        ///       Prompts the user with a 
        ///       with the given parameters. It also ensures that
        ///       the focus is set back on the window that had
        ///       the focus to begin with (before we displayed 
        ///       the MessageBox).
        ///     
        ///  
        internal bool MessageBoxWithFocusRestore(string message, string caption,
                MessageBoxButtons buttons, MessageBoxIcon icon) 
        {
            bool ret;
            IntPtr focusHandle = UnsafeNativeMethods.GetFocus();
            try { 
                ret = RTLAwareMessageBox.Show(null, message, caption, buttons, icon,
                        MessageBoxDefaultButton.Button1, 0) == DialogResult.Yes; 
            } 
            finally {
                UnsafeNativeMethods.SetFocus(new HandleRef(null, focusHandle)); 
            }
            return ret;
        }
 
        /// 
        ///  
        ///     
        ///       Prompts the user with a 
        ///       when a file 
        ///       does not exist.
        ///    
        /// 
        private void PromptFileNotFound(string fileName) { 
            MessageBoxWithFocusRestore(SR.GetString(SR.FileDialogFileNotFound, fileName), DialogCaption,
                    MessageBoxButtons.OK, MessageBoxIcon.Warning); 
        } 

        // If it's necessary to throw up a "This file exists, are you sure?" kind of 
        // MessageBox, here's where we do it
        // Return value is whether or not the user hit "okay".
        internal virtual bool PromptUserIfAppropriate(string fileName) {
            if ((options & NativeMethods.OFN_FILEMUSTEXIST) != 0) { 
                if (!FileExists(fileName)) {
                    PromptFileNotFound(fileName); 
                    return false; 
                }
            } 
            return true;
        }

        ///  
        /// 
        ///     
        ///       Resets all properties to their default values. 
        ///    
        ///  
        public override void Reset() {
            options = NativeMethods.OFN_HIDEREADONLY | NativeMethods.OFN_PATHMUSTEXIST |
                      OPTION_ADDEXTENSION;
            title = null; 
            initialDir = null;
            defaultExt = null; 
            fileNames = null; 
            filter = null;
            filterIndex = 1; 
            supportMultiDottedExtensions = false;
            this._customPlaces.Clear();
        }
 
        /// 
        ///  
        ///    Implements running of a file dialog. 
        /// 
        ///  
        protected override bool RunDialog(IntPtr hWndOwner) {
            // See VSWhidbey bug 107000. Shell APIs do not support multisthreaded apartment model.
            if (Control.CheckForIllegalCrossThreadCalls && Application.OleRequired() != System.Threading.ApartmentState.STA) {
                throw new System.Threading.ThreadStateException(SR.GetString(SR.DebuggingExceptionOnly, SR.GetString(SR.ThreadMustBeSTA))); 
            }
            EnsureFileDialogPermission(); 
            if (this.UseVistaDialogInternal) 
            {
                return RunDialogVista(hWndOwner); 
            }
            else
            {
                return RunDialogOld(hWndOwner); 
            }
        } 
 
        internal abstract void EnsureFileDialogPermission();
 
        private bool RunDialogOld(IntPtr hWndOwner)
        {
            NativeMethods.WndProc hookProcPtr = new NativeMethods.WndProc(this.HookProc);
            NativeMethods.OPENFILENAME_I ofn = new NativeMethods.OPENFILENAME_I(); 
            try {
                charBuffer = CharBuffer.CreateBuffer(FILEBUFSIZE); 
                if (fileNames != null) { 
                    charBuffer.PutString(fileNames[0]);
                } 
                ofn.lStructSize = Marshal.SizeOf(typeof(NativeMethods.OPENFILENAME_I));
                // Degrade to the older style dialog if we're not on Win2K.
                // We do this by setting the struct size to a different value
                // 
                if (Environment.OSVersion.Platform != System.PlatformID.Win32NT ||
                    Environment.OSVersion.Version.Major < 5) { 
                    ofn.lStructSize = 0x4C; 
                }
                ofn.hwndOwner = hWndOwner; 
                ofn.hInstance = Instance;
                ofn.lpstrFilter = MakeFilterString(filter, this.DereferenceLinks);
                ofn.nFilterIndex = filterIndex;
                ofn.lpstrFile = charBuffer.AllocCoTaskMem(); 
                ofn.nMaxFile = FILEBUFSIZE;
                ofn.lpstrInitialDir = initialDir; 
                ofn.lpstrTitle = title; 
                ofn.Flags = Options | (NativeMethods.OFN_EXPLORER | NativeMethods.OFN_ENABLEHOOK | NativeMethods.OFN_ENABLESIZING);
                ofn.lpfnHook = hookProcPtr; 
                ofn.FlagsEx = NativeMethods.OFN_USESHELLITEM;
                if (defaultExt != null && AddExtension) {
                    ofn.lpstrDefExt = defaultExt;
                } 
                //Security checks happen here
                return RunFileDialog(ofn); 
            } 
            finally {
                charBuffer = null; 
                if (ofn.lpstrFile != IntPtr.Zero) {
                    Marshal.FreeCoTaskMem(ofn.lpstrFile);
                }
            } 
        }
 
        ///  
        /// 
        ///     Implements the actual call to GetOPENFILENAME_I or GetSaveFileName. 
        /// 
        /// 
        internal abstract bool RunFileDialog(NativeMethods.OPENFILENAME_I ofn);
 
        /// 
        ///  
        ///     Sets the given option to the given boolean value. 
        /// 
        ///  
        internal void SetOption(int option, bool value) {
            if (value) {
                options |= option;
            } 
            else {
                options &= ~option; 
            } 
        }
 
        /// 
        /// 
        /// 
        ///     
        ///       Provides a string version of this Object.
        ///     
        ///  
        public override string ToString() {
            StringBuilder sb = new StringBuilder(base.ToString() + ": Title: " + Title + ", FileName: "); 
            try
            {
                sb.Append(FileName);
            } 
            catch (Exception e)
            { 
                sb.Append("<"); 
                sb.Append(e.GetType().FullName);
                sb.Append(">"); 
            }
            return sb.ToString();
        }
 

    } 
} 

 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms { 
    using System.Text; 
    using System.Threading;
    using System.Runtime.Remoting; 
    using System.Runtime.InteropServices;

    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 

    using System; 
    using System.Security.Permissions; 
    using System.Drawing;
    using System.ComponentModel; 
    using System.Windows.Forms;
    using System.IO;
    using ArrayList = System.Collections.ArrayList;
 
    using Encoding = System.Text.Encoding;
    using Microsoft.Win32; 
    using System.Security; 
    using CharBuffer = System.Windows.Forms.UnsafeNativeMethods.CharBuffer;
 
    /// 
    /// 
    ///    
    ///       Displays a dialog window from which the user can select a file. 
    ///    
    ///  
    [ 
    DefaultEvent("FileOk"),
    DefaultProperty("FileName") 
    ]
    public abstract partial class FileDialog : CommonDialog {

        private const int FILEBUFSIZE = 8192; 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        /// 
        protected static readonly object EventFileOk = new object();

        internal const int OPTION_ADDEXTENSION = unchecked(unchecked((int)0x80000000)); 

        internal int options; 
 
        private string title;
        private string initialDir; 
        private string defaultExt;
        private string[] fileNames;
        private bool securityCheckFileNames;
        private string filter; 
        private int filterIndex;
        private bool supportMultiDottedExtensions; 
        private bool ignoreSecondFileOkNotification;  // Used for VS Whidbey 95342 
        private int okNotificationCount;              // Same
        private CharBuffer charBuffer; 
        private IntPtr dialogHWnd;

        /// 
        ///  
        ///    
        ///       In an inherited class, 
        ///       initializes a new instance of the  
        ///       class.
        ///     
        /// 
        [
            SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")  // If the constructor does not call Reset
                                                                                                    // it would be a breaking change. 
        ]
        internal FileDialog() { 
            Reset(); 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value indicating whether the 
        ///       dialog box automatically adds an extension to a
        ///       file name if the user omits the extension. 
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        SRDescription(SR.FDaddExtensionDescr)
        ] 
        public bool AddExtension {
            get { 
                return GetOption(OPTION_ADDEXTENSION); 
            }
 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand();
                SetOption(OPTION_ADDEXTENSION, value); 
            }
        } 
 
        /// 
        ///  
        ///    Gets or sets a value indicating whether
        ///       the dialog box displays a warning if the user specifies a file name that does not exist.
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        SRDescription(SR.FDcheckFileExistsDescr) 
        ]
        public virtual bool CheckFileExists { 
            get {
                return GetOption(NativeMethods.OFN_FILEMUSTEXIST);
            }
 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded"); 
                IntSecurity.FileDialogCustomization.Demand(); 
                SetOption(NativeMethods.OFN_FILEMUSTEXIST, value);
            } 
        }

        /// 
        ///  
        ///    
        ///       Gets or sets a value indicating whether the 
        ///       dialog box displays a warning if the user specifies a path that does not exist. 
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        SRDescription(SR.FDcheckPathExistsDescr) 
        ]
        public bool CheckPathExists { 
            get { 
                return GetOption(NativeMethods.OFN_PATHMUSTEXIST);
            } 

            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 
                SetOption(NativeMethods.OFN_PATHMUSTEXIST, value);
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or sets the default file extension.
        /// 
        ///    
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(""), 
        SRDescription(SR.FDdefaultExtDescr)
        ]
        public string DefaultExt {
            get { 
                return defaultExt == null? "": defaultExt;
            } 
 
            set {
                if (value != null) { 
                    if (value.StartsWith("."))
                        value = value.Substring(1);
                    else if (value.Length == 0)
                        value = null; 
                }
                defaultExt = value; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Gets or sets a value 
        ///       indicating whether the dialog box returns the location of the file referenced by the shortcut or
        ///       whether it returns the location of the shortcut (.lnk). 
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(true),
        SRDescription(SR.FDdereferenceLinksDescr)
        ] 
        public bool DereferenceLinks {
            get { 
                return !GetOption(NativeMethods.OFN_NODEREFERENCELINKS); 
            }
            set { 
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand();
                SetOption(NativeMethods.OFN_NODEREFERENCELINKS, !value);
            } 
        }
 
        internal string DialogCaption { 
            get {
                int textLen = SafeNativeMethods.GetWindowTextLength(new HandleRef(this, dialogHWnd)); 
                StringBuilder sb = new StringBuilder(textLen+1);
                UnsafeNativeMethods.GetWindowText(new HandleRef(this, dialogHWnd), sb, sb.Capacity);
                return sb.ToString();
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets
        ///       or sets a string containing
        ///       the file name selected in the file dialog box.
        ///     
        /// 
        [ 
        SRCategory(SR.CatData), 
        DefaultValue(""),
        SRDescription(SR.FDfileNameDescr) 
        ]
        public string FileName {
            get {
                if (fileNames == null) { 
                    return "";
                } 
                else { 
                    if (fileNames[0].Length > 0) {
 
                        // See if we need to perform a security check on file names.  We need
                        // to do this if the set of file names was provided by the file dialog.
                        // A developer can set file names through the FileDialog API as well,
                        // but we don't need to check those since the developer can provide any 
                        // name s/he wants.  This is important because it is otherwise possible
                        // to get the FileName property to accept garbage, but throw during get. 
 
                        if (securityCheckFileNames) {
                            Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + fileNames[0] + ") Demanded"); 
                            IntSecurity.DemandFileIO(FileIOPermissionAccess.AllAccess, fileNames[0]);
                        }

                        return fileNames[0]; 
                    }
                    else { 
                        return ""; 
                    }
                } 
            }
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 
                if (value == null) {
                    fileNames = null; 
                } 
                else {
                    fileNames = new string[] {value}; 
                }

                // As the developer has called this API and set the file name with an arbitrary value,
                // we do not need to perform a security check on the name. 
                securityCheckFileNames = false;
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets the file
        ///       names of all selected files in the dialog box. 
        ///    
        ///  
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        SRDescription(SR.FDFileNamesDescr)
        ]
        public string[] FileNames {
            get{ 
                string[] files = FileNamesInternal;
 
                // See if we need to perform a security check on file names.  We need 
                // to do this if the set of file names was provided by the file dialog.
                // A developer can set file names through the FileDialog API as well, 
                // but we don't need to check those since the developer can provide any
                // name s/he wants.  This is important because it is otherwise possible
                // to get the FileName property to accept garbage, but throw during get.
 
                if (securityCheckFileNames) {
                    foreach (string file in files) { 
                        Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileIO(" + file + ") Demanded"); 
                        IntSecurity.DemandFileIO(FileIOPermissionAccess.AllAccess, file);
                    } 
                }
                return files;
            }
        } 

        internal string[] FileNamesInternal { 
            get { 

                if (fileNames == null) { 
                    return new string[0];
                }
                else {
                    return(string[])fileNames.Clone(); 
                }
            } 
        } 

 
        /// 
        /// 
        ///    
        ///       Gets 
        ///       or sets the current file name filter string,
        ///       which determines the choices that appear in the "Save as file type" or 
        ///       "Files of type" box in the dialog box. 
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(""),
        Localizable(true), 
        SRDescription(SR.FDfilterDescr)
        ] 
        public string Filter { 
            get {
                return filter == null? "": filter; 
            }

            set {
                if (value != filter) { 
                    if (value != null && value.Length > 0) {
                        string[] formats = value.Split('|'); 
                        if (formats == null || formats.Length % 2 != 0) { 
                            throw new ArgumentException(SR.GetString(SR.FileDialogInvalidFilter));
                        } 
                    }
                    else {
                        value = null;
                    } 
                    filter = value;
                } 
            } 
        }
 
        /// 
        /// 
        ///     Extracts the file extensions specified by the current file filter into
        ///     an array of strings.  None of the extensions contain .'s, and the 
        ///     default extension is first.
        ///  
        private string[] FilterExtensions { 
            get {
                string filter = this.filter; 
                ArrayList extensions = new ArrayList();

                // First extension is the default one.  It's a little strange if DefaultExt
                // is not in the filters list, but I guess it's legal. 
                if (defaultExt != null)
                    extensions.Add(defaultExt); 
 
                if (filter != null) {
                    string[] tokens = filter.Split('|'); 

                    if ((filterIndex * 2) - 1 >= tokens.Length) {
                        throw new InvalidOperationException(SR.GetString(SR.FileDialogInvalidFilterIndex));
                    } 

                    if (filterIndex > 0) { 
                        string[] exts = tokens[(filterIndex * 2) - 1].Split(';'); 
                        foreach (string ext in exts) {
                            int i = this.supportMultiDottedExtensions ? ext.IndexOf('.') : ext.LastIndexOf('.'); 
                            if (i >= 0) {
                                extensions.Add(ext.Substring(i + 1, ext.Length - (i + 1)));
                            }
                        } 
                    }
                } 
                string[] temp = new string[extensions.Count]; 
                extensions.CopyTo(temp, 0);
                return temp; 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets the index of the filter currently selected in the file dialog box. 
        ///    
        ///  
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(1),
        SRDescription(SR.FDfilterIndexDescr) 
        ]
        public int FilterIndex { 
            get { 
                return filterIndex;
            } 

            set {
                filterIndex = value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets the initial directory displayed by the file dialog
        ///       box.
        ///    
        ///  
        [
        SRCategory(SR.CatData), 
        DefaultValue(""), 
        SRDescription(SR.FDinitialDirDescr)
        ] 
        public string InitialDirectory {
            get {
                return initialDir == null? "": initialDir;
            } 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded"); 
                IntSecurity.FileDialogCustomization.Demand(); 

                initialDir = value; 
            }
        }

        ///  
        /// 
        ///  
        ///     
        ///       Gets the Win32 instance handle for the application.
        ///     
        /// 
        /* SECURITYUNDONE : should require EventQueue permission */
        protected virtual IntPtr Instance {
            [ 
                SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode),
                SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode) 
            ] 
            get { return UnsafeNativeMethods.GetModuleHandle(null); }
        } 

        /// 
        /// 
        ///  
        ///    
        ///       Gets the Win32 common Open File Dialog OFN_* option flags. 
        ///     
        /// 
        protected int Options { 
            get {
                return options & (NativeMethods.OFN_READONLY | NativeMethods.OFN_HIDEREADONLY |
                                  NativeMethods.OFN_NOCHANGEDIR | NativeMethods.OFN_SHOWHELP | NativeMethods.OFN_NOVALIDATE |
                                  NativeMethods.OFN_ALLOWMULTISELECT | NativeMethods.OFN_PATHMUSTEXIST | 
                                  NativeMethods.OFN_NODEREFERENCELINKS);
            } 
        } 

        ///  
        /// 
        ///    
        ///       Gets or sets a value indicating whether the dialog box restores the current directory before
        ///       closing. 
        ///    
        ///  
        [ 
        SRCategory(SR.CatBehavior),
        DefaultValue(false), 
        SRDescription(SR.FDrestoreDirectoryDescr)
        ]
        public bool RestoreDirectory {
            get { 
                return GetOption(NativeMethods.OFN_NOCHANGEDIR);
            } 
            set { 
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 

                SetOption(NativeMethods.OFN_NOCHANGEDIR, value);
            }
        } 

 
        ///  
        /// 
        ///     
        ///       Gets or sets a value indicating
        ///       whether whether the Help button is displayed in the file dialog.
        ///
        ///     
        /// 
        [ 
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.FDshowHelpDescr) 
        ]
        public bool ShowHelp {
            get {
                return GetOption(NativeMethods.OFN_SHOWHELP); 
            }
            set { 
                SetOption(NativeMethods.OFN_SHOWHELP, value); 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets whether def or abc.def is the extension of the file filename.abc.def
        ///     
        ///  
        [
        SRCategory(SR.CatBehavior), 
        DefaultValue(false),
        SRDescription(SR.FDsupportMultiDottedExtensionsDescr)
        ]
        public bool SupportMultiDottedExtensions 
        {
            get 
            { 
                return this.supportMultiDottedExtensions;
            } 
            set
            {
                this.supportMultiDottedExtensions = value;
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Gets or sets the file dialog box title.
        ///    
        /// 
        [ 
        SRCategory(SR.CatAppearance),
        DefaultValue(""), 
        Localizable(true), 
        SRDescription(SR.FDtitleDescr)
        ] 
        public string Title {
            get {
                return title == null? "": title;
            } 
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded"); 
                IntSecurity.FileDialogCustomization.Demand(); 

                title = value; 
            }
        }

        ///  
        /// 
        ///     
        ///       Gets or sets a value indicating whether the dialog box accepts only valid 
        ///       Win32 file names.
        ///     
        /// 
        [
        SRCategory(SR.CatBehavior),
        DefaultValue(true), 
        SRDescription(SR.FDvalidateNamesDescr)
        ] 
        public bool ValidateNames { 
            get {
                return !GetOption(NativeMethods.OFN_NOVALIDATE); 
            }
            set {
                Debug.WriteLineIf(IntSecurity.SecurityDemand.TraceVerbose, "FileDialogCustomization Demanded");
                IntSecurity.FileDialogCustomization.Demand(); 

                SetOption(NativeMethods.OFN_NOVALIDATE, !value); 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Occurs when the user clicks on the Open or Save button on a file dialog 
        ///       box.
        ///     
        ///  
        ///    
        ///       For information about handling events, see . 
        ///    
        /// 
        /// 
        [SRDescription(SR.FDfileOkDescr)] 
        public event CancelEventHandler FileOk {
            add { 
                Events.AddHandler(EventFileOk, value); 
            }
            remove { 
                Events.RemoveHandler(EventFileOk, value);
            }
        }
 
        /// 
        ///  
        ///     Processes the CDN_FILEOK notification. 
        /// 
        private bool DoFileOk(IntPtr lpOFN) { 
            NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(lpOFN, typeof(NativeMethods.OPENFILENAME_I));
            int saveOptions = options;
            int saveFilterIndex = filterIndex;
            string[] saveFileNames = fileNames; 
            bool saveSecurityCheckFileNames = securityCheckFileNames;
            bool ok = false; 
            try { 
                options = options & ~NativeMethods.OFN_READONLY |
                          ofn.Flags & NativeMethods.OFN_READONLY; 
                filterIndex = ofn.nFilterIndex;
                charBuffer.PutCoTaskMem(ofn.lpstrFile);

                // We are filling in the file names list with secure 
                // data.  Any access to this list now will require
                // a security demand.  We set this bit before actually 
                // setting the names; otherwise a thread ---- could 
                // expose them.
                securityCheckFileNames = true; 
                Thread.MemoryBarrier();

                if ((options & NativeMethods.OFN_ALLOWMULTISELECT) == 0) {
                    fileNames = new string[] {charBuffer.GetString()}; 
                }
                else { 
                    fileNames = GetMultiselectFiles(charBuffer); 
                }
 
                if (ProcessFileNames()) {
                    CancelEventArgs ceevent = new CancelEventArgs();
                    if (NativeWindow.WndProcShouldBeDebuggable) {
                        OnFileOk(ceevent); 
                        ok = !ceevent.Cancel;
                    } 
                    else { 
                        try
                        { 
                            OnFileOk(ceevent);
                            ok = !ceevent.Cancel;
                        }
                        catch (Exception e) 
                        {
                            Application.OnThreadException(e); 
                        } 
                    }
                } 
            }
            finally {
                if (!ok) {
                    securityCheckFileNames = saveSecurityCheckFileNames; 
                    Thread.MemoryBarrier();
                    fileNames = saveFileNames; 
 
                    options = saveOptions;
                    filterIndex = saveFilterIndex; 
                }
            }
            return ok;
        } 

        /// SECREVIEW: ReviewImperativeSecurity 
        ///   vulnerability to watch out for: A method uses imperative security and might be constructing the permission using state information or return values that can change while the demand is active. 
        ///   reason for exclude: filename is a local variable and not subject to race conditions.
        [SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity")] 
        internal static bool FileExists(string fileName)
        {
            bool fileExists = false;
            try { 
                // SECREVIEW : We must Assert just to check if the file exists. Since
                //           : we are doing this as part of the FileDialog, this is OK. 
                new FileIOPermission(FileIOPermissionAccess.Read, IntSecurity.UnsafeGetFullPath(fileName)).Assert(); 
                try {
                    fileExists = File.Exists(fileName); 
                }
                finally {
                    CodeAccessPermission.RevertAssert();
                } 
            }
            catch (System.IO.PathTooLongException) { 
            } 
            return fileExists;
        } 

        /// 
        /// 
        ///     Extracts the filename(s) returned by the file dialog. 
        /// 
        private string[] GetMultiselectFiles(CharBuffer charBuffer) { 
            string directory = charBuffer.GetString(); 
            string fileName = charBuffer.GetString();
            if (fileName.Length == 0) return new string[] { 
                    directory
                };
            if (directory[directory.Length - 1] != '\\') {
                directory = directory + "\\"; 
            }
            ArrayList names = new ArrayList(); 
            do { 
                if (fileName[0] != '\\' && (fileName.Length <= 3 ||
                                            fileName[1] != ':' || fileName[2] != '\\')) { 
                    fileName = directory + fileName;
                }
                names.Add(fileName);
                fileName = charBuffer.GetString(); 
            } while (fileName.Length > 0);
            string[] temp = new string[names.Count]; 
            names.CopyTo(temp, 0); 
            return temp;
        } 

        /// 
        /// 
        ///     Returns the state of the given option flag. 
        /// 
        ///  
 
        internal bool GetOption(int option) {
            return(options & option) != 0; 
        }

        /// 
        ///  
        ///    
        ///       Defines the common dialog box hook procedure that is overridden to add 
        ///       specific functionality to the file dialog box. 
        ///    
        ///  
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) {
            if (msg == NativeMethods.WM_NOTIFY) {
                dialogHWnd = UnsafeNativeMethods.GetParent(new HandleRef(null, hWnd)); 
                try {
                    UnsafeNativeMethods.OFNOTIFY notify = (UnsafeNativeMethods.OFNOTIFY)UnsafeNativeMethods.PtrToStructure(lparam, typeof(UnsafeNativeMethods.OFNOTIFY)); 
 
                    switch (notify.hdr_code) {
                        case -601: /* CDN_INITDONE */ 
                            MoveToScreenCenter(dialogHWnd);
                            break;
                        case -602: /* CDN_SELCHANGE */
                            NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(notify.lpOFN, typeof(NativeMethods.OPENFILENAME_I)); 
                            // Get the buffer size required to store the selected file names.
                            int sizeNeeded = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, dialogHWnd), 1124 /*CDM_GETSPEC*/, System.IntPtr.Zero, System.IntPtr.Zero); 
                            if (sizeNeeded > ofn.nMaxFile) { 
                                // A bigger buffer is required.
                                try { 
                                    int newBufferSize = sizeNeeded + (FILEBUFSIZE / 4);
                                    // Allocate new buffer
                                    CharBuffer charBufferTmp = CharBuffer.CreateBuffer(newBufferSize);
                                    IntPtr newBuffer = charBufferTmp.AllocCoTaskMem(); 
                                    // Free old buffer
                                    Marshal.FreeCoTaskMem(ofn.lpstrFile); 
                                    // Substitute buffer 
                                    ofn.lpstrFile = newBuffer;
                                    ofn.nMaxFile = newBufferSize; 
                                    this.charBuffer = charBufferTmp;
                                    Marshal.StructureToPtr(ofn, notify.lpOFN, true);
                                    Marshal.StructureToPtr(notify, lparam, true);
                                } 
                                catch {
                                    // intentionaly not throwing here. 
                                } 
                            }
                            this.ignoreSecondFileOkNotification = false; 
                            break;
                        case -604: /* CDN_SHAREVIOLATION */
                            // See VS Whidbey 95342. When the selected file is locked for writing,
                            // we get this notification followed by *two* CDN_FILEOK notifications. 
                            this.ignoreSecondFileOkNotification = true;  // We want to ignore the second CDN_FILEOK
                            this.okNotificationCount = 0;                // to avoid a second prompt by PromptFileOverwrite. 
                            break; 
                        case -606: /* CDN_FILEOK */
                            if (this.ignoreSecondFileOkNotification) 
                            {
                                // We got a CDN_SHAREVIOLATION notification and want to ignore the second CDN_FILEOK notification
                                if (this.okNotificationCount == 0)
                                { 
                                    this.okNotificationCount = 1;   // This one is the first and is all right.
                                } 
                                else 
                                {
                                    // This is the second CDN_FILEOK, so we want to ignore it. 
                                    this.ignoreSecondFileOkNotification = false;
                                    UnsafeNativeMethods.SetWindowLong(new HandleRef(null, hWnd), 0, new HandleRef(null, NativeMethods.InvalidIntPtr));
                                    return NativeMethods.InvalidIntPtr;
                                } 
                            }
                            if (!DoFileOk(notify.lpOFN)) { 
                                UnsafeNativeMethods.SetWindowLong(new HandleRef(null, hWnd), 0, new HandleRef(null, NativeMethods.InvalidIntPtr)); 
                                return NativeMethods.InvalidIntPtr;
                            } 
                            break;
                    }
                }
                catch { 
                    if (dialogHWnd != IntPtr.Zero) {
                        UnsafeNativeMethods.EndDialog(new HandleRef(this, dialogHWnd), IntPtr.Zero); 
                    } 
                    throw;
                } 
            }
            return IntPtr.Zero;
        }
 
        /// 
        ///  
        ///     Converts the given filter string to the format required in an OPENFILENAME_I 
        ///     structure.
        ///  
        private static string MakeFilterString(string s, bool dereferenceLinks) {
            if (s == null || s.Length == 0)
            {
                // Workaround for Whidbey bug #5165 
                // Apply the workaround only when DereferenceLinks is true and OS is at least WinXP.
                if (dereferenceLinks && System.Environment.OSVersion.Version.Major >= 5) 
                { 
                    s = " |*.*";
                } 
                else if (s == null)
                {
                    return null;
                } 
            }
            int length = s.Length; 
            char[] filter = new char[length + 2]; 
            s.CopyTo(0, filter, 0, length);
            for (int i = 0; i < length; i++) { 
                if (filter[i] == '|') filter[i] = (char)0;
            }
            filter[length + 1] = (char)0;
            return new string(filter); 
        }
 
        ///  
        /// 
        ///     
        ///       Raises the  event.
        ///    
        /// 
        protected void OnFileOk(CancelEventArgs e) { 
            CancelEventHandler handler = (CancelEventHandler)Events[EventFileOk];
            if (handler != null) handler(this, e); 
        } 

        ///  
        /// 
        ///     Processes the filenames entered in the dialog according to the settings
        ///     of the "addExtension", "checkFileExists", "createPrompt", and
        ///     "overwritePrompt" properties. 
        /// 
        private bool ProcessFileNames() { 
            if ((options & NativeMethods.OFN_NOVALIDATE) == 0) { 
                string[] extensions = FilterExtensions;
                for (int i = 0; i < fileNames.Length; i++) { 
                    string fileName = fileNames[i];
                    if ((options & OPTION_ADDEXTENSION) != 0 && !Path.HasExtension(fileName)) {
                        bool fileMustExist = (options & NativeMethods.OFN_FILEMUSTEXIST) != 0;
 
                        for (int j = 0; j < extensions.Length; j++) {
                            string currentExtension = Path.GetExtension(fileName); 
 
                            Debug.Assert(!extensions[j].StartsWith("."),
                                         "FileDialog.FilterExtensions should not return things starting with '.'"); 
                            Debug.Assert(currentExtension.Length == 0 || currentExtension.StartsWith("."),
                                         "File.GetExtension should return something that starts with '.'");

                            string s = fileName.Substring(0, fileName.Length - currentExtension.Length); 

                            // we don't want to append the extension if it contains wild cards 
                            if (extensions[j].IndexOfAny(new char[] { '*', '?' }) == -1) { 
                                s += "." + extensions[j];
                            } 

                            if (!fileMustExist || FileExists(s)) {
                                fileName = s;
                                break; 
                            }
                        } 
                        fileNames[i] = fileName; 
                    }
                    if (!PromptUserIfAppropriate(fileName)) 
                        return false;
                }
            }
            return true; 
        }
 
        ///  
        /// 
        ///     
        ///       Prompts the user with a 
        ///       with the given parameters. It also ensures that
        ///       the focus is set back on the window that had
        ///       the focus to begin with (before we displayed 
        ///       the MessageBox).
        ///     
        ///  
        internal bool MessageBoxWithFocusRestore(string message, string caption,
                MessageBoxButtons buttons, MessageBoxIcon icon) 
        {
            bool ret;
            IntPtr focusHandle = UnsafeNativeMethods.GetFocus();
            try { 
                ret = RTLAwareMessageBox.Show(null, message, caption, buttons, icon,
                        MessageBoxDefaultButton.Button1, 0) == DialogResult.Yes; 
            } 
            finally {
                UnsafeNativeMethods.SetFocus(new HandleRef(null, focusHandle)); 
            }
            return ret;
        }
 
        /// 
        ///  
        ///     
        ///       Prompts the user with a 
        ///       when a file 
        ///       does not exist.
        ///    
        /// 
        private void PromptFileNotFound(string fileName) { 
            MessageBoxWithFocusRestore(SR.GetString(SR.FileDialogFileNotFound, fileName), DialogCaption,
                    MessageBoxButtons.OK, MessageBoxIcon.Warning); 
        } 

        // If it's necessary to throw up a "This file exists, are you sure?" kind of 
        // MessageBox, here's where we do it
        // Return value is whether or not the user hit "okay".
        internal virtual bool PromptUserIfAppropriate(string fileName) {
            if ((options & NativeMethods.OFN_FILEMUSTEXIST) != 0) { 
                if (!FileExists(fileName)) {
                    PromptFileNotFound(fileName); 
                    return false; 
                }
            } 
            return true;
        }

        ///  
        /// 
        ///     
        ///       Resets all properties to their default values. 
        ///    
        ///  
        public override void Reset() {
            options = NativeMethods.OFN_HIDEREADONLY | NativeMethods.OFN_PATHMUSTEXIST |
                      OPTION_ADDEXTENSION;
            title = null; 
            initialDir = null;
            defaultExt = null; 
            fileNames = null; 
            filter = null;
            filterIndex = 1; 
            supportMultiDottedExtensions = false;
            this._customPlaces.Clear();
        }
 
        /// 
        ///  
        ///    Implements running of a file dialog. 
        /// 
        ///  
        protected override bool RunDialog(IntPtr hWndOwner) {
            // See VSWhidbey bug 107000. Shell APIs do not support multisthreaded apartment model.
            if (Control.CheckForIllegalCrossThreadCalls && Application.OleRequired() != System.Threading.ApartmentState.STA) {
                throw new System.Threading.ThreadStateException(SR.GetString(SR.DebuggingExceptionOnly, SR.GetString(SR.ThreadMustBeSTA))); 
            }
            EnsureFileDialogPermission(); 
            if (this.UseVistaDialogInternal) 
            {
                return RunDialogVista(hWndOwner); 
            }
            else
            {
                return RunDialogOld(hWndOwner); 
            }
        } 
 
        internal abstract void EnsureFileDialogPermission();
 
        private bool RunDialogOld(IntPtr hWndOwner)
        {
            NativeMethods.WndProc hookProcPtr = new NativeMethods.WndProc(this.HookProc);
            NativeMethods.OPENFILENAME_I ofn = new NativeMethods.OPENFILENAME_I(); 
            try {
                charBuffer = CharBuffer.CreateBuffer(FILEBUFSIZE); 
                if (fileNames != null) { 
                    charBuffer.PutString(fileNames[0]);
                } 
                ofn.lStructSize = Marshal.SizeOf(typeof(NativeMethods.OPENFILENAME_I));
                // Degrade to the older style dialog if we're not on Win2K.
                // We do this by setting the struct size to a different value
                // 
                if (Environment.OSVersion.Platform != System.PlatformID.Win32NT ||
                    Environment.OSVersion.Version.Major < 5) { 
                    ofn.lStructSize = 0x4C; 
                }
                ofn.hwndOwner = hWndOwner; 
                ofn.hInstance = Instance;
                ofn.lpstrFilter = MakeFilterString(filter, this.DereferenceLinks);
                ofn.nFilterIndex = filterIndex;
                ofn.lpstrFile = charBuffer.AllocCoTaskMem(); 
                ofn.nMaxFile = FILEBUFSIZE;
                ofn.lpstrInitialDir = initialDir; 
                ofn.lpstrTitle = title; 
                ofn.Flags = Options | (NativeMethods.OFN_EXPLORER | NativeMethods.OFN_ENABLEHOOK | NativeMethods.OFN_ENABLESIZING);
                ofn.lpfnHook = hookProcPtr; 
                ofn.FlagsEx = NativeMethods.OFN_USESHELLITEM;
                if (defaultExt != null && AddExtension) {
                    ofn.lpstrDefExt = defaultExt;
                } 
                //Security checks happen here
                return RunFileDialog(ofn); 
            } 
            finally {
                charBuffer = null; 
                if (ofn.lpstrFile != IntPtr.Zero) {
                    Marshal.FreeCoTaskMem(ofn.lpstrFile);
                }
            } 
        }
 
        ///  
        /// 
        ///     Implements the actual call to GetOPENFILENAME_I or GetSaveFileName. 
        /// 
        /// 
        internal abstract bool RunFileDialog(NativeMethods.OPENFILENAME_I ofn);
 
        /// 
        ///  
        ///     Sets the given option to the given boolean value. 
        /// 
        ///  
        internal void SetOption(int option, bool value) {
            if (value) {
                options |= option;
            } 
            else {
                options &= ~option; 
            } 
        }
 
        /// 
        /// 
        /// 
        ///     
        ///       Provides a string version of this Object.
        ///     
        ///  
        public override string ToString() {
            StringBuilder sb = new StringBuilder(base.ToString() + ": Title: " + Title + ", FileName: "); 
            try
            {
                sb.Append(FileName);
            } 
            catch (Exception e)
            { 
                sb.Append("<"); 
                sb.Append(e.GetType().FullName);
                sb.Append(">"); 
            }
            return sb.ToString();
        }
 

    } 
} 

 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK