public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, out CoTaskMemSafeHandle ppidl);
 private static extern HResult PropVariantToStringVectorAlloc(PropVariantSafeHandle propvar, out CoTaskMemSafeHandle pprgsz, out uint pcElem);
Exemplo n.º 3
0
        private unsafe bool RunDialogOld(IntPtr hWndOwner)
        {
            CoTaskMemSafeHandle listHandle;

            Interop.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)rootFolder, out listHandle);
            if (listHandle.IsInvalid)
            {
                Interop.Shell32.SHGetSpecialFolderLocation(hWndOwner, (int)Environment.SpecialFolder.Desktop, out listHandle);
                if (listHandle.IsInvalid)
                {
                    throw new InvalidOperationException(SR.FolderBrowserDialogNoRootFolder);
                }
            }

            using (listHandle)
            {
                uint mergedOptions = Interop.Shell32.BrowseInfoFlags.BIF_NEWDIALOGSTYLE;
                if (!showNewFolderButton)
                {
                    mergedOptions |= Interop.Shell32.BrowseInfoFlags.BIF_NONEWFOLDERBUTTON;
                }

                // The SHBrowserForFolder dialog is OLE/COM based, and documented as only being safe to use under the STA
                // threading model if the BIF_NEWDIALOGSTYLE flag has been requested (which we always do in mergedOptions
                // above). So make sure OLE is initialized, and throw an exception if caller attempts to invoke dialog
                // under the MTA threading model (...dialog does appear under MTA, but is totally non-functional).
                if (Control.CheckForIllegalCrossThreadCalls && Application.OleRequired() != System.Threading.ApartmentState.STA)
                {
                    throw new System.Threading.ThreadStateException(string.Format(SR.DebuggingExceptionOnly, SR.ThreadMustBeSTA));
                }

                var    callback    = new Interop.Shell32.BrowseCallbackProc(FolderBrowserDialog_BrowseCallbackProc);
                char[] displayName = ArrayPool <char> .Shared.Rent(Interop.Kernel32.MAX_PATH + 1);

                try
                {
                    fixed(char *pDisplayName = displayName)
                    {
                        var bi = new Interop.Shell32.BROWSEINFO();

                        bi.pidlRoot       = listHandle;
                        bi.hwndOwner      = hWndOwner;
                        bi.pszDisplayName = pDisplayName;
                        bi.lpszTitle      = descriptionText;
                        bi.ulFlags        = mergedOptions;
                        bi.lpfn           = callback;
                        bi.lParam         = IntPtr.Zero;
                        bi.iImage         = 0;

                        // Show the dialog
                        using (CoTaskMemSafeHandle browseHandle = Interop.Shell32.SHBrowseForFolderW(ref bi))
                        {
                            if (browseHandle.IsInvalid)
                            {
                                return(false);
                            }

                            // Retrieve the path from the IDList.
                            Interop.Shell32.SHGetPathFromIDListLongPath(browseHandle.DangerousGetHandle(), out selectedPath);
                            GC.KeepAlive(callback);
                            return(true);
                        }
                    }
                }
                finally
                {
                    ArrayPool <char> .Shared.Return(displayName);
                }
            }
        }