// ShellPlatformInvokeDemo
// Version 0.1.using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;namespace ShellPlatformInvokeDemo
{
  public class Shell
  {
    private class Win32
    {
      public const int _MAX_PATH=260;
      public const uint BIF_EDITBOX=0x0010;
      public const uint BIF_NEWDIALOGSTYLE=0x0040;      public delegate int BFFCALLBACK(IntPtr/*HWND*/ hwnd, uint/*UINT*/ uMsg, IntPtr/*LPARAM*/ lParam, IntPtr/*LPARAM*/ lpData);      [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
      public struct BROWSEINFO
      {
        public IntPtr/*HWND*/ _hwndOwner;
        public IntPtr/*LPCITEMIDLIST*/ _pidlRoot;
        [MarshalAs(UnmanagedType.LPStr)] public string/*LPTSTR*/ _szDirectory;
        [MarshalAs(UnmanagedType.LPStr)] public string/*LPCTSTR*/ _lpszTitle;
        public uint/*UINT*/ _ulFlags;
        [MarshalAs(UnmanagedType.FunctionPtr)] public BFFCALLBACK/*BFFCALLBACK*/ _lpfn;
        public IntPtr/*LPARAM*/ _lParam;
        public int/*int*/ _iImage;    public BROWSEINFO(IntPtr parent, string title)
    {
      _hwndOwner=parent;
      _pidlRoot=(IntPtr)0;
      _szDirectory=null;
      _lpszTitle=title;
      _ulFlags=BIF_EDITBOX|BIF_NEWDIALOGSTYLE;
      _lpfn=(BFFCALLBACK)null;
      _lParam=(IntPtr)0;
      _iImage=0;
    }
  }     [ComImport]
  [Guid("00000002-0000-0000-C000-000000000046")]
  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  internal interface IMalloc
  {
    [PreserveSig] IntPtr/*void * */ Alloc(ulong/*ULONG*/ cb);
    [PreserveSig] IntPtr/*void * */ Realloc(IntPtr/*void * */ pv, ulong/*ULONG*/ cb);
    [PreserveSig] void/*void*/ Free(IntPtr/*void * */ pv);
    [PreserveSig] ulong/*ULONG*/ GetSize(IntPtr/*void * */ pv);
    [PreserveSig] int/*int*/ DidAlloc(IntPtr/*void * */ pv);
    [PreserveSig] void/*void*/ HeapMinimize();
  }  [DllImport("shell32.dll")]
  public static extern IntPtr/*LPITEMIDLIST*/ SHBrowseForFolder(ref BROWSEINFO/*LPBROWSEINFO*/ lpbi);

  [DllImport("shell32.dll")]
  public static extern bool/*BOOL*/ SHGetPathFromIDList(IntPtr/*LPCITEMIDLIST*/ pidl, StringBuilder/*LPTSTR*/ pszPath);[DllImport("Shell32.dll")]
public static extern int/*HRESULT*/ SHGetMalloc([MarshalAs(UnmanagedType.IUnknown)] out object /*LPMALLOC * */ ppMalloc);
  }/// <summary>
/// Browse for a shell folder.
/// </summary>
/// <param name="title">Title to display in dialogue box</param>
/// <param name="path">Return path</param>
/// <returns>DialogResult.OK if successful</returns>
public static DialogResult BrowseForFolder(string title, out string path)
{
  return BrowseForFolder((IntPtr)0, title, out path);
}public static DialogResult BrowseForFolder(IntPtr parent, string title, out string path)
{
  path=null;
  Win32.BROWSEINFO browseInfo=new Win32.BROWSEINFO(parent, title);
  IntPtr pidl=Win32.SHBrowseForFolder(ref browseInfo);
  if (pidl==IntPtr.Zero) {return DialogResult.Cancel;}
  try
  {
    StringBuilder stringBuilder=new StringBuilder(Win32._MAX_PATH);
    if (Win32.SHGetPathFromIDList(pidl, stringBuilder))
    {
      path=stringBuilder.ToString();
      return DialogResult.OK;
    }
    else
    {
      return DialogResult.Cancel;
    }
  }
  finally
  {
    // Free memory allocated by shell.
    object pMalloc=null;
    // Get the IMalloc interface and free the block of memory.
    if (Win32.SHGetMalloc(out pMalloc)==0/*NOERROR*/)
    {
      ((Win32.IMalloc)pMalloc).Free(pidl);
    }
  }
}
}
}