title: Getting Icon Of Special Folders Such As My Computer And Libraries
body: <p>I have been trying to construct a class to simply grab the current icons of special folders such as "My Computer" AKA "Computer", "Libraries", etc.  I'm currently trying to use the SHGetFileInfo() API to achieve this.</p>
  
  <p>The original SHGetFileInfo Function on Microsoft's page...</p>
  
  <p><strong>#1 Code Block</strong></p>
  
  <pre><code>DWORD_PTR SHGetFileInfo(
    _In_     LPCTSTR pszPath,
    DWORD dwFileAttributes,
    _Inout_  SHFILEINFO *psfi,
    UINT cbFileInfo,
    UINT uFlags
  );
  </code></pre>
  
  <p>(above referenced from: <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179%28v=vs.85%29.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/library/windows/desktop/bb762179%28v=vs.85%29.aspx</a>)</p>
  
  <p>On another SO question I found this as an example...</p>
  
  <p><strong>#2 Code Block</strong></p>
  
  <pre><code>IntPtr pidl;
  SHGetSpecialFolderLocation(0, CSIDL_DRIVES, pidl);
  SHGetFileInfo(pidl, 0, shinfo, Marshal.SizeOf(shinfo), (SHGFI_PIDL | SHGFI_DISPLAYNAME | SHGFI_ICON | SHGFI_SMALLICON));
  </code></pre>
  
  <p>(above referenced from: <a href="https://stackoverflow.com/a/14293350/1039753">https://stackoverflow.com/a/14293350/1039753</a>)</p>
  
  <p>That describes to use SHGetFileInfo in a way that requires the first parameter to be an IntPtr.  I was under the impression that the first parameter needed to be a string based off this...</p>
  
  <p><strong>#3 Code Block</strong></p>
  
  <pre><code>[DllImport("shell32.dll", CharSet=CharSet.Auto)]
  public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
  </code></pre>
  
  <p>(above referenced from: <a href="http://pinvoke.net/default.aspx/shell32.SHGetFileInfo" rel="nofollow noreferrer">http://pinvoke.net/default.aspx/shell32.SHGetFileInfo</a>)</p>
  
  <p>Furthermore, looking around SO I also found this answer...</p>
  
  <p><strong>#4 Code Block</strong></p>
  
  <pre><code>[DllImport("Pdh.dll")]
  static extern int PdhOpenQueryW(
      [MarshalAs(UnmanagedType.LPWStr)] string szDataSource, 
      UIntPtr dwUserData,
      out IntPtr phQuery);
  </code></pre>
  
  <p>(above referenced from: <a href="https://stackoverflow.com/a/3598417/1039753">https://stackoverflow.com/a/3598417/1039753</a>)</p>
  
  <p>In the above answer the user tells the original poster to use...</p>
  
  <p><strong>#5 Code Block</strong></p>
  
  <pre><code>[MarshalAs(UnmanagedType.LPWStr)] string
  </code></pre>
  
  <p>to map to the</p>
  
  <p><strong>#6 Code Block</strong></p>
  
  <pre><code>"_In_     LPCTSTR pszPath,"
  </code></pre>
  
  <p>param.  Found in the MSDN c++ constructor at the top.  That makes more sense to me than any of it.  But what I can't wrap my head around is the answer (#2 Code Block) above that tells the original poster to use an IntPtr when the pinvoke.net site says define it as a string.</p>
  
  <p>Any idea how I can make SHGetFileInfo() work to get me that icon?  Thanks!</p>
  
  <hr>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Here is an example of how I tried to use it...</p>
  
  <pre><code>[DllImport("Shell32.dll")]
  public static extern IntPtr SHGetFileInfo(
    string pszPath,
    uint dwFileAttributes,
    ref SHFILEINFO psfi,
    uint cbFileInfo,
    uint uFlags
  );
  
  SHGetFileInfo((IntPtr)oTarget, 0, ref shfi, (uint)Marshal.SizeOf(shfi), flags);
  </code></pre>
  
  <p>Then I get two errors...</p>
  
  <pre><code>Error   1   The best overloaded method match for 'SHGetFileInfo(string, uint, ref SHFILEINFO, uint, uint)' has some invalid arguments   C:\FakePath\ImageWorker.cs  67  25  ImageWorker
  
  Error   2   Argument 1: cannot convert from 'System.IntPtr' to 'string' C:\FakePath\ImageTool.cs    67  47  ImageWorker
  </code></pre>