
Microsoft Archive Files Format

Written by Lloyd Kinsella, lloydk@iname.com

The Microsoft Archive Files remain the exclusive property
of Microsoft Corp.

*****************************************************************************

After seeing MSN Explorer on the news I decided to download it and liked it's
jazzy interface and graphics. But a question lingered in my mind, where were
these graphics stored.

Being a programmer I naturally picked up a resource hacker and began to scour
through MSN Explorer's program files, but none of them contained the graphics
I saw in the interface, so I began to look at the *.mar files.

At first it all looked like mumbo jumbo data, but I noticed some familiar
data like the GIF89a marker which donates the beginning of a GIF file and
also plain HTML code, so I looked to the top of the file to see if there was
a tree or some sort of file directory structure to work on, and there was.

Below is the description of the format so far, and is the first I know of
to be released by anyone.

I've also included some Borland Delphi (PASCAL) code to show you how to
traverse the file.

*****************************************************************************

I'll be using ui.mar in this description, as it comes with MSN Explorer and
is located in the MSNCoreFiles folder.

1. Header

The *.mar header is a simple twelve byte header, that contains the file
signiture, MARC, also what I beleive to be the version and the number of files
the archive holds.

UI.MAR Header Hex Dump
-------------------------------------------------------------------------
00000000 4D 41 52 43 03 00 00 00 F4 00 00 00             MARC........

Header Format
-------------------------------------------------------------------------
Length		Type		Description		UI.MAR
-------------------------------------------------------------------------
4 Bytes		CHAR		MARC File Signature	MARC
4 Bytes		LONG		MARC File Version?	3
4 Bytes		LONG		Number of files		224
-------------------------------------------------------------------------
12 Bytes Total

2. File Directory

Following straight on from the header is the table of the files
contained within the header.

This table contains the file name, offset and size, though not in that order.

UI.MAR File Table Hex Dump (First three files)
-------------------------------------------------------------------------
00000012 61 64 73 70 61 63 65 2E 68 74 6D 00 00 00 00 00 adspace.htm.....
00000028 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000044 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00 29 03 00 00 34 B4 F1 FF ........)...4...
00000076 DC 40 00 00 63 6F 6F 6B 69 65 69 6E 66 6F 2E 68 .@..cookieinfo.h
00000092 74 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 tm..............
00000108 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000124 00 00 00 00 00 00 00 00 00 00 00 00 37 08 00 00 ............7...
00000140 91 52 FA 4A 05 44 00 00 66 61 76 6F 72 69 74 65 .R.J.D..favorite
00000156 73 2F 66 61 76 6F 72 69 74 65 73 2D 64 69 61 6C s/favorites-dial
00000172 6F 67 2E 68 74 6D 00 00 00 00 00 00 00 00 00 00 og.htm..........
00000188 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000204 BB 09 00 00 6A 9F B9 3B 62 4D 00 00             ....j..;bM..

Table Format
-------------------------------------------------------------------------
Length		Type		Description		UI.MAR
-------------------------------------------------------------------------
56 Bytes	CHAR		Filename of the File	adspace.htm
4 Bytes		LONG		Size of the File Data	809
4 Bytes		LONG		CRC-32 Checksum		????
4 Bytes		LONG		Offset of the File Data 16604
-------------------------------------------------------------------------
68 Bytes Total

And thats basically it, except for the raw data...

3. Example Code (Borland Delphi)

Below is a simple unit you can copy and create to let you navigate the
files, it is only a reader and does not write MARC files.

MARC.PAS
-------------------------------------------------------------------------

unit MARC;

{***********************************************************}
{                                                           }
{  Microsoft Archive (MARC)                                 }
{                                                           }
{  File Format is Copyright 2000 Microsoft Corp.           }
{  This code is Copyright 2000 Lloyd Kinsella.             }
{                                                           }
{  E - Mai: lloydk@iname.com                                }
{                                                           }
{***********************************************************}
{                                                           }
{  Developer Notes:                                         }
{                                                           }
{  At present this unit will only allow you to "read" the   }
{  *.mar files due to an "unknown" peice of data required   }
{  in order to write a MARC true file.                      }
{                                                           }
{***********************************************************}

interface

uses Windows, SysUtils, Classes;

type
 TMARCHeaderStruct = record
  Signature: array [1..4] of Byte;
  Version: LongInt;
  FileCount: LongInt;
 end;

type
 TMARCFileStruct = record
  Filename: array [1..56] of Char;
  Size: LongInt;
  CRC: LongInt;
  Offset: LongInt;
 end;

type
 TMARC = class(TObject)
  private
   FFilename: String;
   FVersion: LongInt;
   procedure LoadFromFile(Filename: String);
  public
   Files: TList;
   constructor Create(Filename: String);
   destructor Destroy; override;
   property Filename: String read FFilename;
   property Version: LongInt read FVersion;
  end;

type
 TMARCFile = class
  private
   FFilename: String;
   FSize: LongInt;
   FCRC: LongInt;
   FOffset: LongInt;
  public
   Data: TMemoryStream;
   constructor Create(FileInfo: TMARCFileStruct);
   destructor Destroy; override;
   procedure SaveToFile(Filename: String);
   property Filename: String read FFilename;
   property Size: LongInt read FSize;
   property CRC: LongInt read FCRC;
   property Offset: LongInt read FOffset;
  end;

implementation

constructor TMARC.Create(Filename: String);
begin
 inherited Create;
 FFilename := '';
 FVersion := 0;
 Files := TList.Create;
 LoadFromFile(Filename);
end;

destructor TMARC.Destroy;
begin
 Files.Free;
 inherited Destroy;
end;

procedure TMARC.LoadFromFile(Filename: String);
var
 F: TFileStream;
 Header: TMARCHeaderStruct;
 I: Integer;
 FileInfo: TMARCFileStruct;
 MarcFile: TMARCFile;
 CurrentPos: LongInt;
begin
 F := TFileStream.Create(Filename,fmOpenRead or fmShareDenyWrite);
 F.Read(Header,SizeOf(TMARCHeaderStruct));
 FFilename := Filename;
 FVersion := Header.Version;
  for I := 1 to Header.FileCount do
   begin
    F.Read(FileInfo,SizeOf(TMARCFileStruct));
    MarcFile := TMARCFile.Create(FileInfo);
    CurrentPos := F.Position;
    F.Seek(FileInfo.Offset,soFromBeginning);
    MarcFile.Data.CopyFrom(F,FileInfo.Size);
    MarcFile.Data.Seek(0,soFromBeginning);
    F.Seek(CurrentPos,soFromBeginning);
    Files.Add(MarcFile);
   end;
 F.Free;
end;

constructor TMARCFile.Create(FileInfo: TMARCFileStruct);
begin
 inherited Create;
 FFilename := FileInfo.Filename;
 FSize := FileInfo.Size;
 FCRC := FileInfo.CRC;
 FOffset := FileInfo.Offset;
 Data := TMemoryStream.Create;
end;

destructor TMARCFile.Destroy;
begin
 Data.Free;
 inherited Destroy;
end;

procedure TMARCFile.SaveToFile(Filename: String);
var
 CurrentPos: LongInt;
 F: TFileStream;
begin
 CurrentPos := Data.Position;
 Data.Seek(0,soFromBeginning);
 F := TFileStream.Create(Filename,fmCreate);
 F.CopyFrom(Data,0);
 F.Free;
 Data.Seek(CurrentPos,soFromBeginning);
end;

end.
