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.