title: Constructing a FileStream from a handle produced by CreateFile gives an empty stream
body: <p>I'm attempting to write a simple program that would take a CSV consisting of two columns, and given a keyword from the first column, return the corresponding value from the second one. The problem is that I need the CSV to be in an alternate data stream to make the program as portable as possible (I want to make it so that when the user drops a CSV file on the executable, the CSV is overwritten). That is why I'm trying to use WinAPI's CreateFile function -- .NET doesn't support alternate data streams. Unfortunately, I'm failing miserably.</p>
  
  <p>In the current state, the program is supposed to read a file named test.csv. I want to do CreateFile on it, convert the intPtr handle to a SafeFileHandle and then pass the SafeFileHandle to a FileStream constructor. The best I've been able to achieve is an empty stream though. It doesn't seem to me that the program is actually getting the right handle. When I try "CREATE_ALWAYS" or "CREATE_NEW" instead of "OPEN_ALWAYS", I'm getting an "Invalid Handle" error, no matter what I do with the rest of the parameters. With "OPEN_ALWAYS", when I check the value of "stream.Name", I'm getting "Unknown".</p>
  
  <p>Here is the code:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  using System.IO;
  using System.Runtime.InteropServices;
  using Microsoft.Win32.SafeHandles;
  
  namespace Searcher
  {
      public partial class Searcher : Form
      {
          public static List&lt;string&gt; keywords;
          public static List&lt;string&gt; values;
  
          public Searcher()
          {
              InitializeComponent();
  
              //byte[] path = Encoding.UTF8.GetBytes("C:\\Users\\as\\Documents\\test.csv");
              SafeFileHandle safeADSHandle = NativeMethods.CreateFileW("test.csv",
              NativeConstants.GENERIC_READ,
              NativeConstants.FILE_SHARE_READ,
              IntPtr.Zero,
              NativeConstants.OPEN_ALWAYS,
              0,
              IntPtr.Zero);
              //var safeADSHandle = new SafeFileHandle(handle, true);
              if (safeADSHandle.IsInvalid)
              {
                  Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
              }
              var stream = new FileStream(safeADSHandle, FileAccess.Read);
              MessageBox.Show(stream.Name);
              var reader = new StreamReader(stream);
              Searcher.keywords = new List&lt;string&gt;();
              Searcher.values = new List&lt;string&gt;();
              while (!reader.EndOfStream)
              {
                  var line = reader.ReadLine();
                  var values = line.Split(',');
                  Searcher.keywords.Add(values[0]);
                  Searcher.values.Add(values[1]);
              }
              cbKeyword.DataSource = Searcher.keywords;
              cbKeyword.AutoCompleteSource = AutoCompleteSource.ListItems;
          }
  
          private void btnSearch_Click(object sender, EventArgs e)
          {
              tbResult.Text = Searcher.values[cbKeyword.SelectedIndex];
          }
      }
  }
  
  public partial class NativeMethods
  {
          [DllImportAttribute("kernel32.dll", SetLastError = true, EntryPoint = "CreateFile")]
          public static extern SafeFileHandle CreateFileW(
              [InAttribute()] [MarshalAsAttribute(UnmanagedType.LPWStr)] string lpFileName,
              uint dwDesiredAccess,
              uint dwShareMode,
              [InAttribute()] System.IntPtr lpSecurityAttributes,
              uint dwCreationDisposition,
              uint dwFlagsAndAttributes,
              [InAttribute()] System.IntPtr hTemplateFile
          );
  }
  
  
  public partial class NativeConstants
  {
  
          /// GENERIC_WRITE -&gt; (0x40000000L)
          public const int GENERIC_WRITE = 1073741824;
  
          public const uint GENERIC_READ = 2147483648;
  
          /// FILE_SHARE_DELETE -&gt; 0x00000004
          public const int FILE_SHARE_DELETE = 4;
  
          /// FILE_SHARE_WRITE -&gt; 0x00000002
          public const int FILE_SHARE_WRITE = 2;
  
          /// FILE_SHARE_READ -&gt; 0x00000001
          public const int FILE_SHARE_READ = 1;
  
          /// OPEN_ALWAYS -&gt; 4
          public const int OPEN_ALWAYS = 4;
          public const int CREATE_NEW = 1;
  }
  </code></pre>
  
  <p>Edit I've changed the code above slightly to reflect the changes after the comments. Now I'm not converting from IntPtr to SafeFileHandle. One thing to mention perhaps is that I before this change I tried reading the value of handle.ToString() to see if it was changing and it was -- it's a random number.</p>