It's a very old format with a structure that is a total mess. I myself have spent a lot of time figuring how to properly read quotes in a jungle of different files and formats.
Here I present the actual C# code I use to interface with the database that I update every evening from my data vendor.
Information on the metastock data structure is scattered over the web. I've collected what seemed to work and implemented as a C# class. A special thank to Julian M Bucknall for providing the code to convert from MBF4 (Microsoft Binary Format single precision) to standard floating point IEEE number.
The library is organized as follows:
- the struct MetaStockRow stores one day of data
 
public struct MetaStockRow { public DateTime Day; public double Open; public double High; public double Low; public double Close; public double Volume; public double OpenInterest; }
- a set of MetaStockRow(s) forms a MetaStockTable, that is, the whole data for a stock symbol
 - a set of MetaStockTable(s) forms a MetaStockCollection, which is useful when you have to work with more than one stock at a time. A special feature of MetaStockCollection is the capability to intersect dates, that is, making sure that the stocks you are working with have the same data points (days).
 - MetaStockTables and MetaStockCollections are generated by the class MetaStockReader which is the main object that performs the low-level reading on the database files.
 
- Create a MetaStockReader object
 - Use AddPath() to tell it where your metastock folders are located (usually there are more than one).
 - Create a MetaStockCollection object
 - Insert stocks in the collection with AddSymbol()
 - Trim and synch dates in the collection with FilterPeriod() and IntersectDates()
 - Get daily closes with GetCloseArray()
 
An example:
 MetaStockReader MR = new MetaStockReader();       
 MR.AddPath(@"C:\MetaStock\NYSE");   
 MR.AddPath(@"C:\MetaStock\AMEX");   
   
 MetaStockCollection ML = new MetaStockCollection();                
 ML.AddSymbol("MSFT",MR);  
 ML.AddSymbol("BRK.A",MR);  
   
 ML = ML.FilterPeriod(DateTime.Parse("01/01/2000"),DateTime.Parse("31/12/2011"));  
 ML = ML.IntersectDates();  
   
 double[] s1 = ML[0].GetCloseArray();  
 double[] s2 = ML[1].GetCloseArray();  
If you need to work with just one stock, you can avoid using MetaStockCollection and work directly with MetaStockTable objects and access to its MetaStockRow(s).
There is a little more in the code of what I've shown here, but if you have a look at the sources you can easily discover by yourself all the other features. I must warn you the code quality is rather poor, because I haven't spent much time in improving it. I stopped when it "worked" (shame on me!).
Download the C# source code here.