title: How do you format an SD card using the Storage Manager API via Windows Mobile 6
body: <p>Background:</p>
  
  <p>I'm trying to create a utility that will allow our customers to easily format an SD card (actually mini-SD) directly on a Windows Mobile 6 device (Intermec CK3). This would be preferred over a thrid party tool such as <a href="http://download.cnet.com/Flash-Format/3000-2094_4-10060244.html" rel="nofollow noreferrer">FlashFormat</a> or having to provide card readers to the customers (which would require them to remove the battery, pull out the mini-SD card which is held in by a flimsy metal housing, and then run the Windows formatting utility via the file management control). Most of our customers are not very tech-savvy, so a utility that can be run automatically or via a couple clicks would be ideal.</p>
  
  <p>I've tried the following so far:</p>
  
  <ul>
  <li>Looked at <a href="https://stackoverflow.com/questions/1232398/how-to-programically-format-sd-card-on-fat16-on-windows-net">this</a> question. The answers in here do not seem to work for Windows Mobile (e.g. no WMI support or format.com utility).</li>
  <li>Tried using <a href="http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx" rel="nofollow noreferrer">CreateFile</a> and <a href="http://msdn.microsoft.com/en-us/library/ee481660%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">DeviceIoControlCE</a>. This one seemed promising, but the SD card would never seem to actually format. From what I could tell, it was because the card needed to be dismounted first.</li>
  <li>Tried using <a href="http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx" rel="nofollow noreferrer">CreatFile</a> and <a href="http://msdn.microsoft.com/en-us/library/ee489780%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">FormatVolumeEx</a> (along with the other variants, <a href="http://msdn.microsoft.com/en-us/library/ee490193%28v=winembedded.60%29.aspx" rel="nofollow noreferrer">FormatVolume</a> and <a href="http://msdn.microsoft.com/en-US/library/ee490011%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">FormateVolumeUI</a>). The result seemed to be similar in that I could not format the card unless it was first dismounted.</li>
  </ul>
  
  <p>After doing some searching an running into <a href="http://social.msdn.microsoft.com/forums/en-US/vssmartdevicesnative/thread/38c10d32-1e15-4877-9cc0-bd3ea4c56f15" rel="nofollow noreferrer">this thread</a> (answer near bottom by paraGOD) and <a href="http://geekswithblogs.net/BruceEitman/Default.aspx" rel="nofollow noreferrer">this blog</a>, I decided to go down a new path of using the <a href="http://msdn.microsoft.com/en-us/library/ee490420%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">Store Manager API</a>, which has such functions as <a href="http://msdn.microsoft.com/en-US/library/ee489983%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">FindFirstStore</a>, <a href="http://msdn.microsoft.com/en-US/library/ee489756%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">FindNextStore</a>, <a href="http://msdn.microsoft.com/en-US/library/ee489981%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">OpenStore</a>, <a href="http://msdn.microsoft.com/en-US/library/ee489534%28v=WinEmbedded.60%29.aspx" rel="nofollow noreferrer">DismountStore</a> and so on.</p>
  
  <p>I'm trying to do this in C#, so I created the necessary supporting structs to represent the typdefs used in the API. Here is a sample one:</p>
  
  <pre><code>using System.Runtime.InteropServices;
  
  // Try to match the struct typedef exactly (all caps, exact type names).
  using DWORD = System.UInt32;
  using TCHAR = System.String;
  
  namespace SDFormatter
  {
      // http://msdn.microsoft.com/en-us/library/ee490035(v=WinEmbedded.60).aspx
      // STORAGEDEVICEINFO (Storage Manager)
  
      [StructLayout(LayoutKind.Sequential)]
      public struct StorageDeviceInfo
      {
          public DWORD cbSize;
          [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
          public TCHAR szProfile;
          public DWORD dwDeviceClass;
          public DWORD dwDeviceType;
          public DWORD dwDeviceFlags;
      }
  }
  </code></pre>
  
  <p>Then I created a static storage manager class to hold all of the storage manager functions (which are supposed to be available in coredll for windows mobile 6... or so I thought):</p>
  
  <pre><code>using System.Runtime.InteropServices;
  
  // Try to match the Coredll functions exactly (all caps, exact type names, etc.).
  using BOOL = System.Boolean;
  using BYTE = System.Byte;
  using DWORD = System.UInt32;
  using HANDLE = System.IntPtr;
  using LPCE_VOLUME_INFO = System.IntPtr;
  using LPCSTR = System.String;
  using LPCTSTR = System.String;
  using LPCWSTR = System.String;
  using PPARTINFO = System.IntPtr;
  using PSTOREINFO = System.IntPtr;
  using SECTORNUM = System.UInt64;
  
  // ReSharper disable InconsistentNaming
  namespace SDFormatter
  {
      // http://msdn.microsoft.com/en-us/library/ee490420(v=WinEmbedded.60).aspx
  
      public static class StorageManager
      {
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern bool CeGetVolumeInfo(LPCWSTR pszRootPath, CE_VOLUME_INFO_LEVEL InfoLevel,
                                                    LPCE_VOLUME_INFO lpVolumeInfo);
  
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern bool CreatePartition(HANDLE hStore, LPCTSTR szPartitionName, SECTORNUM snNumSectors);
  
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern bool CreatePartitionEx(HANDLE hStore, LPCTSTR szPartitionName, BYTE bPartType,
                                                      SECTORNUM snNumSectors);
  
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern bool DeletePartition(HANDLE hStore, LPCTSTR szPartitionName);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool DismountPartition(HANDLE hPartition);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool DismountStore(HANDLE hStore);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FindClosePartition(HANDLE hSearch);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FindCloseStore(HANDLE hSearch);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern HANDLE FindFirstPartition(HANDLE hStore, PPARTINFO pPartInfo);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern HANDLE FindFirstStore(PSTOREINFO pStoreInfo);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FindNextPartition(HANDLE hSearch, PPARTINFO pPartInfo);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FindNextStore(HANDLE hSearch, PSTOREINFO pStoreInfo);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FormatPartition(HANDLE hPartition);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FormatPartitionEx(HANDLE hPartition, BYTE bPartType, BOOL bAuto);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool FormatStore(HANDLE hStore);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool GetPartitionInfo(HANDLE hPartition, PPARTINFO pPartInfo);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool GetStoreInfo(HANDLE hStore, PSTOREINFO pStoreInfo);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool MountPartition(HANDLE hPartition);
  
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern HANDLE OpenPartition(HANDLE hStore, LPCTSTR szPartitionName);
  
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern HANDLE OpenStore(LPCSTR szDeviceName);
  
          [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)]
          public static extern bool RenamePartition(HANDLE hPartition, LPCTSTR szNewName);
  
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool SetPartitionAttributes(HANDLE hPartition, DWORD dwAttrs);
  
          // http://msdn.microsoft.com/en-us/library/ee490442(v=winembedded.60).aspx
          [DllImport("Coredll.dll", SetLastError = true)]
          public static extern bool CloseHandle(HANDLE hObject);
      }
  
      public enum CE_VOLUME_INFO_LEVEL
      {
          CeVolumeInfoLevelStandard = 0
      }
  }
  // ReSharper restore InconsistentNaming
  </code></pre>
  
  <p>So I went to test some of these functions, such as simply enumerating through the stores via the FindFirstStore and FindNextStore functions and then I get the dreaded, <strong><em>Can't find an Entry Point 'FindFirstStore' in a PInvoke DLL 'Coredll.dll'</em></strong> error (in the debugger output I also get <strong><em>A first chance exception of type 'System.MissingMethodException' occurred in SDFormatter.exe</em></strong>, which makes sense). Some more research hinted that in Windows Mobile, these functions aren't exposed, even though they are part of Coredll. They are however part of Windows CE 6 and can be accessed via platform builder.</p>
  
  <p>So here are the main questions I have: </p>
  
  <ul>
  <li>Can I access the Storage Manager API via C# in Windows Mobile 6 some how?</li>
  <li>If not, can I write a utility via managed C++ (I'm don't know much, but I'll stumble through it if necessary), but without having to use platform builder (it's not free)?</li>
  <li>If it is only possible via platform builder, does that mean I'm either stuck building my own SDK or will have to ask Intermec to expose the functionality for me?</li>
  </ul>
  
  <p>I'm also open to doing this another way entirely (preferrably via C#) if anyone has suggestions. I was thinking maybe having the customer mount the device in the cradle and running a desktop utility. Not sure if this is possible and it can't rely on ActiveSync (we don't want to support yet another tool, so we send data to and from the SD card via a network adapter connected to the cradle using sockets to talk between our custom server program and our mobile application).</p>
  
  <p>Thanks</p>