[9989] Use unix styoe line ends in soem files

This commit is contained in:
VladimirMangos 2010-05-28 02:26:00 +04:00
parent 2cd5a6bbf2
commit 5cd5462e17
7 changed files with 656 additions and 656 deletions

View file

@ -1,318 +1,318 @@
THE MOPAQ ARCHIVE FORMAT THE MOPAQ ARCHIVE FORMAT
v0.9 (Thursday, June 30, 2005) v0.9 (Thursday, June 30, 2005)
by Justin Olbrantz(Quantam) by Justin Olbrantz(Quantam)
Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quoting Distribution and reproduction of this specification are allowed without limitation, as long as it is not altered. Quoting
in other works is freely allowed, as long as the source and author of the quote is stated. in other works is freely allowed, as long as the source and author of the quote is stated.
TABLE OF CONTENTS TABLE OF CONTENTS
1. Introduction to the MoPaQ Format 1. Introduction to the MoPaQ Format
2. The MoPaQ Format 2. The MoPaQ Format
2.1 General Archive Layout 2.1 General Archive Layout
2.2 Archive Header 2.2 Archive Header
2.3 Block Table 2.3 Block Table
2.4 Hash Table 2.4 Hash Table
2.5 File Data 2.5 File Data
2.6 Listfile 2.6 Listfile
2.7 Extended Attributes 2.7 Extended Attributes
2.8 Weak (Old) Digital Signature 2.8 Weak (Old) Digital Signature
2.9 Strong (New) Digital Signature 2.9 Strong (New) Digital Signature
3. Algorithm Source Code 3. Algorithm Source Code
3.1 Encryption/Decryption 3.1 Encryption/Decryption
3.2 Hashing 3.2 Hashing
3.3 Conversion of FILETIME and time_t 3.3 Conversion of FILETIME and time_t
1. INTRODUCTION TO THE MOPAQ FORMAT 1. INTRODUCTION TO THE MOPAQ FORMAT
The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard The MoPaQ (or MPQ) format is an archive file format designed by Mike O'Brien (hence the name Mike O'brien PaCK) at Blizzard
Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be Entertainment. The format has been used in all Blizzard games since (and including) Diablo. It is heavily optimized to be
a read-only game archive format, and excels at this role. a read-only game archive format, and excels at this role.
The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked. The Blizzard MoPaQ-reading functions are contained in the Storm module, which my be either statically or dynamically linked.
The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked. The Blizzard MoPaQ-writing functions are contained in the MPQAPI module, which is always statically linked.
2. THE MOPAQ FORMAT 2. THE MOPAQ FORMAT
All numbers in the MoPaQ format are in little endian. Data types are listed either as int (integer, the number of bits specified), All numbers in the MoPaQ format are in little endian. Data types are listed either as int (integer, the number of bits specified),
byte (8 bits), and char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise. byte (8 bits), and char (bytes which contain ASCII characters). All sizes and offsets are in bytes, unless specified otherwise.
Structure members are listed in the following general form: Structure members are listed in the following general form:
offset from the beginning of the structure: data type(array size) member name : member description offset from the beginning of the structure: data type(array size) member name : member description
2.1 GENERAL ARCHIVE LAYOUT 2.1 GENERAL ARCHIVE LAYOUT
- Archive Header - Archive Header
- File Data - File Data
- File Data - Special Files - File Data - Special Files
- Hash Table - Hash Table
- Block Table - Block Table
- Strong Digital signature - Strong Digital signature
This is the usual archive format, and is not absolutely essential. Some archives have been observed placing the hash table This is the usual archive format, and is not absolutely essential. Some archives have been observed placing the hash table
and file table after the archive header, and before the file data. and file table after the archive header, and before the file data.
2.2 ARCHIVE HEADER 2.2 ARCHIVE HEADER
00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah. 00h: char(4) Magic : Indicates that the file is a MoPaQ archive. Must be ASCII "MPQ" 1Ah.
04h: int32 HeaderSize : Size of the archive header. Should be 32. 04h: int32 HeaderSize : Size of the archive header. Should be 32.
08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present. 08h: int32 ArchiveSize : Size of the whole archive, including the header. Does not include the strong digital signature, if present.
This size is used, among other things, for determining the region to hash in computing the digital signature. This size is used, among other things, for determining the region to hash in computing the digital signature.
0Ch: int16 Unknown : Unknown 0Ch: int16 Unknown : Unknown
0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector 0Eh: int8 SectorSizeShift : Power of two exponent specifying the number of 512-byte disk sectors in each logical sector
in the archive. The size of each logical sector the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate in the archive. The size of each logical sector the archive is 512 * 2^SectorSizeShift. Bugs in the Storm library dictate
that this should always be 3 (4096 byte sectors). that this should always be 3 (4096 byte sectors).
10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive. 10h: int32 HashTableOffset : Offset to the beginning of the hash table, relative to the beginning of the archive.
14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive. 14h: int32 BlockTableOffset : Offset to the beginning of the block table, relative to the beginning of the archive.
18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16. 18h: int32 HashTableEntries : Number of entries in the hash table. Must be a power of two, and must be less than 2^16.
1Ch: int32 BlockTableEntries : Number of entries in the block table. 1Ch: int32 BlockTableEntries : Number of entries in the block table.
The archive header is the first structure in the archive, at archive offset 0, but the archive does not need to be at offset The archive header is the first structure in the archive, at archive offset 0, but the archive does not need to be at offset
0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not 0 of the containing file. The offset of the archive in the file is referred to here as ArchiveOffset. If the archive is not
at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the at the beginning of the file, it must begin at a disk sector boundary (512 bytes). Early versions of Storm require that the
archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer archive be at the end of the containing file (ArchiveOffset + ArchiveSize = file size), but this is not required in newer
versions (due to the strong digital signature not being considered a part of the archive). versions (due to the strong digital signature not being considered a part of the archive).
2.3 BLOCK TABLE 2.3 BLOCK TABLE
The block table contains entries for each region in the archive. Regions may be either files or empty space, which may be The block table contains entries for each region in the archive. Regions may be either files or empty space, which may be
overwritten by new files (typically this space is from deleted file data). The block table is encrypted, using the hash overwritten by new files (typically this space is from deleted file data). The block table is encrypted, using the hash
of "(block table)" as the key. Each entry is structured as follows: of "(block table)" as the key. Each entry is structured as follows:
00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. Meaningless if the block size is 0. 00h: int32 BlockOffset : Offset of the beginning of the block, relative to the beginning of the archive. Meaningless if the block size is 0.
04h: int32 BlockSize : Size of the block in the archive. 04h: int32 BlockSize : Size of the block in the archive.
08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file, otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data. 08h: int32 FileSize : Size of the file data stored in the block. Only valid if the block is a file, otherwise meaningless, and should be 0. If the file is compressed, this is the size of the uncompressed file data.
0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified: 0Ch: int32 Flags : Bit mask of the flags for the block. The following values are conclusively identified:
80000000h: Block is a file, and follows the file data format; otherwise, block is free space, and may be overwritten. If the block is not a file, all other flags should be cleared. 80000000h: Block is a file, and follows the file data format; otherwise, block is free space, and may be overwritten. If the block is not a file, all other flags should be cleared.
01000000h: File is stored as a single unit, rather than split into sectors. 01000000h: File is stored as a single unit, rather than split into sectors.
00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted. 00020000h: The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
00010000h: File is encrypted. 00010000h: File is encrypted.
00000200h: File is compressed. Mutually exclusive to file imploded. 00000200h: File is compressed. Mutually exclusive to file imploded.
00000100h: File is imploded. Mutually exclusive to file compressed. 00000100h: File is imploded. Mutually exclusive to file compressed.
2.4 HASH TABLE 2.4 HASH TABLE
Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows: Instead of storing file names, for quick access MoPaQs use a fixed, power of two-size hash table of files in the archive. A file is uniquely identified by its file path, its language, and its platform. The home entry for a file in the hash table is computed as a hash of the file path. In the event of a collision (the home entry is occupied by another file), progressive overflow is used, and the file is placed in the next available hash table entry. Searches for a desired file in the hash table proceed from the home entry for the file until either the file is found, the entire hash table is searched, or an empty hash table entry (FileBlockIndex of FFFFFFFFh) is encountered. The hash table is encrypted using the hash of "(hash table)" as the key. Each entry is structured as follows:
00h: int32 FilePathHashA : The hash of the file path, using method A. 00h: int32 FilePathHashA : The hash of the file path, using method A.
04h: int32 FilePathHashB : The hash of the file path, using method B. 04h: int32 FilePathHashB : The hash of the file path, using method B.
08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral. 08h: int16 Language : The language of the file. This is a Windows LANGID data type, and uses the same values. 0 indicates the default language (American English), or that the file is language-neutral.
0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed. 0Ah: int8 Platform : The platform the file is used for. 0 indicates the default platform. No other values have been observed.
0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values: 0Ch: int32 FileBlockIndex : If the hash table entry is valid, this is the index into the block table of the file. Otherwise, one of the following two values:
FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file. FFFFFFFFh: Hash table entry is empty, and has always been empty. Terminates searches for a given file.
FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file. FFFFFFFEh: Hash table entry is empty, but was valid at some point (in other words, the file was deleted). Does not terminate searches for a given file.
2.5 FILE DATA 2.5 FILE DATA
00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector's data, relative to the beginning of the file data. Not present if this information is calculatable (see details below). 00h: int32(SectorsInFile + 1) SectorOffsetTable : Offsets to the start of each sector's data, relative to the beginning of the file data. Not present if this information is calculatable (see details below).
immediately following SectorOffsetTable: SectorData : Data of each sector in the file, packed end to end (see details below). immediately following SectorOffsetTable: SectorData : Data of each sector in the file, packed end to end (see details below).
Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may be smaller than this, depending on the size of the file data. This sector size is the size of the raw file data; if the file is compressed, the compressed sector will be smaller or the same size as the uncompressed sector size. Individual sectors in a compressed file may be stored uncompressed; this occurs if and only if the sector could not be compressed by the algorithm used (if the compressed sector size was greater than or equal to the size of the raw data), and is indicated by the sector's compressed size in SectorOffsetTable being equal to the uncompressed size of the sector (which may be calculated from the FileSize). Normally, file data is split up into sectors, for simple streaming. All sectors, save for the last, will contain as many bytes of file data as specified in the archive header's SectorSizeShift; the last sector may be smaller than this, depending on the size of the file data. This sector size is the size of the raw file data; if the file is compressed, the compressed sector will be smaller or the same size as the uncompressed sector size. Individual sectors in a compressed file may be stored uncompressed; this occurs if and only if the sector could not be compressed by the algorithm used (if the compressed sector size was greater than or equal to the size of the raw data), and is indicated by the sector's compressed size in SectorOffsetTable being equal to the uncompressed size of the sector (which may be calculated from the FileSize).
If the sector is compressed (but not imploded), a bit mask byte of the compression algorithm(s) used to compress the sector is appended to the beginning of the compressed sector data. This additional byte counts towards the total size of the sector; if the size of the sector (including this byte) exceeds or matches the uncompressed size of the sector data, the sector will be stored uncompressed, and this byte omitted. Multiple compression algorithms may be used on the same sector; in this case, successive compression occurs in the order the algorithms are listed below, and decompression occurs in the opposite order. For implimentations of all of these algorithms, see StormLib. If the sector is compressed (but not imploded), a bit mask byte of the compression algorithm(s) used to compress the sector is appended to the beginning of the compressed sector data. This additional byte counts towards the total size of the sector; if the size of the sector (including this byte) exceeds or matches the uncompressed size of the sector data, the sector will be stored uncompressed, and this byte omitted. Multiple compression algorithms may be used on the same sector; in this case, successive compression occurs in the order the algorithms are listed below, and decompression occurs in the opposite order. For implimentations of all of these algorithms, see StormLib.
40h: IMA ADPCM mono 40h: IMA ADPCM mono
80h: IMA ADPCM stereo 80h: IMA ADPCM stereo
01h: Huffman encoded 01h: Huffman encoded
02h: Deflated (see ZLib) 02h: Deflated (see ZLib)
08h: Imploded (see PKWare Data Compression Library) 08h: Imploded (see PKWare Data Compression Library)
10h: BZip2 compressed (see BZip2) 10h: BZip2 compressed (see BZip2)
If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which If the file is stored as a single unit (indicated in the file's Flags), there is effectively only a single sector, which
contains the entire file. contains the entire file.
If the file is encrypted, each sector (after compression and appendage of the compression type byte, if applicable) If the file is encrypted, each sector (after compression and appendage of the compression type byte, if applicable)
is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the is encrypted with the file's key. The base key for a file is determined by a hash of the file name stripped of the
directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is directory (i.e. the key for a file named "directory\file" would be computed as the hash of "file"). If this key is
adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset) adjusted, as indicated in the file's Flags, the final key is calculated as ((base key + BlockOffset - ArchiveOffset)
XOR FileSize) (StormLib - an open-source implementation of the MoPaQ reading and writing functions, XOR FileSize) (StormLib - an open-source implementation of the MoPaQ reading and writing functions,
by Ladislav Zezula - incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the by Ladislav Zezula - incorrectly uses an AND in place of the XOR). Each sector is encrypted using the key + the
0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1. 0-based index of the sector in the file. The SectorOffsetTable, if present, is encrypted using the key - 1.
The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize. The SectorOffsetTable is omitted when the sizes and offsets of all sectors in the file are calculatable from the FileSize.
This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors This can happen in several circumstances. If the file is not compressed/imploded, then the size and offset of all sectors
is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the is known, based on the archive's SectorSizeShift. If the file is stored as a single unit compressed/imploded, then the
SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously. SectorOffsetTable is omitted, as the single file "sector" corresponds to BlockSize and FileSize, as mentioned previously.
Note that the SectorOffsetTable will always be present if the file is compressed/imploded and the file is not stored as Note that the SectorOffsetTable will always be present if the file is compressed/imploded and the file is not stored as
a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the a single unit, even if there is only a single sector in the file (the size of the file is less than or equal to the
archive's sector size). archive's sector size).
2.6 LISTFILE 2.6 LISTFILE
The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive. The listfile is a very simple extension to the MoPaQ format that contains the file paths of (most) files in the archive.
The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)", The languages and platforms of the files are not stored in the listfile. The listfile is contained in the file "(listfile)",
and is simply a non-Unix-style text file with one file path on each line, lines terminated with the bytes 0Dh 0Ah. The file and is simply a non-Unix-style text file with one file path on each line, lines terminated with the bytes 0Dh 0Ah. The file
"(listfile)" may not be listed in the listfile. "(listfile)" may not be listed in the listfile.
2.7 EXTENDED ATTRIBUTES 2.7 EXTENDED ATTRIBUTES
The extended attributes are optional file attributes for files in the block table. These attributes were added at times after The extended attributes are optional file attributes for files in the block table. These attributes were added at times after
the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes. the MoPaQ format was already finalized, and it is not necessary for every archive to have all (or any) of the extended attributes.
If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although If an archive contains a given attribute, there will be an instance of that attribute for every block in the block table, although
the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the the attribute will be meaningless if the block is not a file. The order of the attributes for blocks correspond to the order of the
blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file, blocks in the block table, and are of the same number. The attributes are stored in parallel arrays in the "(attributes)" file,
in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other in the archive. The attributes corresponding to this file need not be valid (and logically cannot be). Unlike all the other
structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some structures in the MoPaQ format, entries in the extended attributes are NOT guaranteed to be aligned. Also note that in some
archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This archives, malicious zeroing of the attributes has been observed, perhaps with the intent of breaking archive viewers. This
file is structured as follows: file is structured as follows:
00h: int32 Version : Specifies the extended attributes format version. For now, must be 100. 00h: int32 Version : Specifies the extended attributes format version. For now, must be 100.
04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive: 04h: int32 AttributesPresent : Bit mask of the extended attributes present in the archive:
00000001h: File CRC32s. 00000001h: File CRC32s.
00000002h: File timestamps. 00000002h: File timestamps.
00000004h: File MD5s. 00000004h: File MD5s.
08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the 08h: int32(BlockTableEntries) CRC32s : CRC32s of the (uncompressed) file data for each block in the archive. Omitted if the
archive does not have CRC32s. immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block archive does not have CRC32s. immediately after CRC32s: FILETIME(BlockTableEntries) Timestamps : Timestamps for each block
in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps. in the archive. The format is that of the Windows FILETIME structure. Omitted if the archive does not have timestamps.
immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive. immediately after Timestamps: MD5(BlockTableEntries) MD5s : MD5s of the (uncompressed) file data for each block in the archive.
Omitted if the archive does not have MD5s. Omitted if the archive does not have MD5s.
2.8 WEAK DIGITAL SIGNATURE 2.8 WEAK DIGITAL SIGNATURE
The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5 The weak digital signature is a digital signature using Microsoft CryptoAPI. It is an implimentation of the RSASSA-PKCS1-v1_5
digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this digital signature protocol, using the MD5 hashing algorithm and a 512-bit (weak) RSA key (for more information about this
protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm. The signature protocol, see the RSA Labs PKCS1 specification). The public key and exponent are stored in a resource in Storm. The signature
is stored uncompressed, unencrypted in the file "(signature)" in the archive. The archive is hashed from the beginning of the is stored uncompressed, unencrypted in the file "(signature)" in the archive. The archive is hashed from the beginning of the
archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize); the signature archive (ArchiveOffset in the containing file) to the end of the archive (the length indicated by ArchiveSize); the signature
file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during file is added to the archive before signing, and the space occupied by the file is considered to be all binary 0s during
signing/verification. This file is structured as follows: signing/verification. This file is structured as follows:
00h: int32 Unknown : Must be 0. 00h: int32 Unknown : Must be 0.
04h: int32 Unknown : must be 0. 04h: int32 Unknown : must be 0.
08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order. 08h: int512 Signature : The digital signature. Like all other numbers in the MoPaQ format, this is stored in little-endian order.
2.9 STRONG DIGITAL SIGNATURE 2.9 STRONG DIGITAL SIGNATURE
The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and The strong digital signature uses a simple proprietary implementation of RSA signing, using the SHA-1 hashing algorithm and
a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well. a 2048-bit (strong) RSA key. The default public key and exponent are stored in Storm, but other keys may be used as well.
The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize The strong digital signature is stored immediately after the archive, in the containing file; the entire archive (ArchiveSize
bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format: bytes, starting at ArchiveOffset in the containing file) is hashed as a single block. The signature has the following format:
00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards). 00h: char(4) Magic : Indicates the presence of a digital signature. Must be "NGIS" ("SIGN" backwards).
04h: int2048 Signature : The digital signature, stored in little-endian format. 04h: int2048 Signature : The digital signature, stored in little-endian format.
When the Signature field is decrypted with the public key and exponent, and the result stored in little-endian order, it is structured as follows: When the Signature field is decrypted with the public key and exponent, and the result stored in little-endian order, it is structured as follows:
00h: byte Padding : Must be 0Bh. 00h: byte Padding : Must be 0Bh.
01h: byte(235) Padding : Must be BBh. 01h: byte(235) Padding : Must be BBh.
ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 format. ECh: byte(20) SHA-1 : SHA-1 hash of the archive, in standard SHA-1 format.
3. ALGORITHM SOURCE CODE 3. ALGORITHM SOURCE CODE
3.1 ENCRYPTION/DECRYPTION 3.1 ENCRYPTION/DECRYPTION
I believe this was derived at some point from code in StormLib. Assumes the long type to be 32 bits, and the machine to be little endian order. I believe this was derived at some point from code in StormLib. Assumes the long type to be 32 bits, and the machine to be little endian order.
unsigned long dwCryptTable[0x500]; unsigned long dwCryptTable[0x500];
void InitializeCryptTable() void InitializeCryptTable()
{ {
unsigned long seed = 0x00100001; unsigned long seed = 0x00100001;
unsigned long index1 = 0; unsigned long index1 = 0;
unsigned long index2 = 0; unsigned long index2 = 0;
int i; int i;
for (index1 = 0; index1 < 0x100; index1++) for (index1 = 0; index1 < 0x100; index1++)
{ {
for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100) for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
{ {
unsigned long temp1, temp2; unsigned long temp1, temp2;
seed = (seed * 125 + 3) % 0x2AAAAB; seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10; temp1 = (seed & 0xFFFF) << 0x10;
seed = (seed * 125 + 3) % 0x2AAAAB; seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF); temp2 = (seed & 0xFFFF);
dwCryptTable[index2] = (temp1 | temp2); dwCryptTable[index2] = (temp1 | temp2);
} }
} }
} }
void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey) void EncryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
{ {
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer; unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
unsigned long seed = 0xEEEEEEEE; unsigned long seed = 0xEEEEEEEE;
unsigned long ch; unsigned long ch;
assert(lpbyBuffer); assert(lpbyBuffer);
dwLength /= sizeof(unsigned long); dwLength /= sizeof(unsigned long);
while(dwLength-- > 0) while(dwLength-- > 0)
{ {
seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
ch = *lpdwBuffer ^ (dwKey + seed); ch = *lpdwBuffer ^ (dwKey + seed);
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
seed = *lpdwBuffer + seed + (seed << 5) + 3; seed = *lpdwBuffer + seed + (seed << 5) + 3;
*lpdwBuffer++ = ch; *lpdwBuffer++ = ch;
} }
} }
void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey) void DecryptData(void *lpbyBuffer, unsigned long dwLength, unsigned long dwKey)
{ {
unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer; unsigned long *lpdwBuffer = (unsigned long *)lpbyBuffer;
unsigned long seed = 0xEEEEEEEE; unsigned long seed = 0xEEEEEEEE;
unsigned long ch; unsigned long ch;
assert(lpbyBuffer); assert(lpbyBuffer);
dwLength /= sizeof(unsigned long); dwLength /= sizeof(unsigned long);
while(dwLength-- > 0) while(dwLength-- > 0)
{ {
seed += dwCryptTable[0x400 + (dwKey & 0xFF)]; seed += dwCryptTable[0x400 + (dwKey & 0xFF)];
ch = *lpdwBuffer ^ (dwKey + seed); ch = *lpdwBuffer ^ (dwKey + seed);
dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B); dwKey = ((~dwKey << 0x15) + 0x11111111) | (dwKey >> 0x0B);
seed = ch + seed + (seed << 5) + 3; seed = ch + seed + (seed << 5) + 3;
*lpdwBuffer++ = ch; *lpdwBuffer++ = ch;
} }
} }
3.2 HASHING 3.2 HASHING
Based on code from StormLib. Based on code from StormLib.
// Different types of hashes to make with HashString // Different types of hashes to make with HashString
#define MPQ_HASH_TABLE_OFFSET 0 #define MPQ_HASH_TABLE_OFFSET 0
#define MPQ_HASH_NAME_A 1 #define MPQ_HASH_NAME_A 1
#define MPQ_HASH_NAME_B 2 #define MPQ_HASH_NAME_B 2
#define MPQ_HASH_FILE_KEY 3 #define MPQ_HASH_FILE_KEY 3
unsigned long HashString(const char *lpszString, unsigned long dwHashType) unsigned long HashString(const char *lpszString, unsigned long dwHashType)
{ {
unsigned long seed1 = 0x7FED7FED; unsigned long seed1 = 0x7FED7FED;
unsigned long seed2 = 0xEEEEEEEE; unsigned long seed2 = 0xEEEEEEEE;
int ch; int ch;
while (*lpszString != 0) while (*lpszString != 0)
{ {
ch = toupper(*lpszString++); ch = toupper(*lpszString++);
seed1 = dwCryptTable[(dwHashType * 0xFF) + ch] ^ (seed1 + seed2); seed1 = dwCryptTable[(dwHashType * 0xFF) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
} }
return seed1; return seed1;
} }
3.3 CONVERSION OF FILETIME AND time_t 3.3 CONVERSION OF FILETIME AND time_t
#define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970 #define EPOCH_OFFSET 116444736000000000ULL // Number of 100 ns units between 01/01/1601 and 01/01/1970
bool GetTimeFromFileTime(FILETIME &fileTime, time_t &time) bool GetTimeFromFileTime(FILETIME &fileTime, time_t &time)
{ {
// The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601 // The FILETIME represents a 64-bit integer: the number of 100 ns units since January 1, 1601
unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime; unsigned long long nTime = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime;
if (nTime < EPOCH_OFFSET) if (nTime < EPOCH_OFFSET)
return false; return false;
nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970 nTime -= EPOCH_OFFSET; // Convert the time base from 01/01/1601 to 01/01/1970
nTime /= 10000000ULL; // Convert 100 ns to sec nTime /= 10000000ULL; // Convert 100 ns to sec
time = (time_t)nTime; time = (time_t)nTime;
// Test for overflow (FILETIME is 64 bits, time_t is 32 bits) // Test for overflow (FILETIME is 64 bits, time_t is 32 bits)
if ((nTime - (unsigned long long)time) > 0) if ((nTime - (unsigned long long)time) > 0)
return false; return false;
return true; return true;
} }
void GetFileTimeFromTime(time_t &time, FILETIME &fileTime) void GetFileTimeFromTime(time_t &time, FILETIME &fileTime)
{ {
unsigned long long nTime = (unsigned long long)time; unsigned long long nTime = (unsigned long long)time;
nTime *= 10000000ULL; nTime *= 10000000ULL;
nTime += EPOCH_OFFSET; nTime += EPOCH_OFFSET;
fileTime.dwLowDateTime = (DWORD)nTime; fileTime.dwLowDateTime = (DWORD)nTime;
fileTime.dwHighDateTime = (DWORD)(nTime >> 32); fileTime.dwHighDateTime = (DWORD)(nTime >> 32);
} }

View file

@ -1,25 +1,25 @@
; Storm definition file with alternate Storm.dll names ; Storm definition file with alternate Storm.dll names
LIBRARY "Storm" LIBRARY "Storm"
EXPORTS EXPORTS
StormCloseArchive @252 ; 0x0FC StormCloseArchive @252 ; 0x0FC
StormCloseFile @253 ; 0x0FD StormCloseFile @253 ; 0x0FD
StormDestroy @262 ; 0x106 StormDestroy @262 ; 0x106
StormGetFileArchive @264 ; 0x108 StormGetFileArchive @264 ; 0x108
StormGetFileSize @265 ; 0x109 StormGetFileSize @265 ; 0x109
StormOpenArchive @266 ; 0x10A StormOpenArchive @266 ; 0x10A
StormOpenFile @267 ; 0x10B StormOpenFile @267 ; 0x10B
StormOpenFileEx @268 ; 0x10C StormOpenFileEx @268 ; 0x10C
StormReadFile @269 ; 0x10D StormReadFile @269 ; 0x10D
StormSetBasePath @270 ; 0x10E StormSetBasePath @270 ; 0x10E
StormSetFilePointer @271 ; 0x10F StormSetFilePointer @271 ; 0x10F
StormSetLocale @272 ; 0x110 StormSetLocale @272 ; 0x110
StormGetBasePath @273 ; 0x111 StormGetBasePath @273 ; 0x111
StormGetArchiveName @275 ; 0x113 StormGetArchiveName @275 ; 0x113
StormGetFileName @276 ; 0x114 StormGetFileName @276 ; 0x114
; StormSetLastError @465 ; 0x ; StormSetLastError @465 ; 0x
StormCompress @551 ; 0x227 StormCompress @551 ; 0x227
StormDecompress @552 ; 0x228 StormDecompress @552 ; 0x228

View file

@ -1,93 +1,93 @@
# Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4> # Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00 # Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** 編集しないでください ** # ** 編集しないでください **
# TARGTYPE "Win32 (x86) Console Application" 0x0103 # TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=dlltest - Win32 Debug CFG=dlltest - Win32 Debug
!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 !MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。
!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください !MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "dlltest.mak". !MESSAGE NMAKE /f "dlltest.mak".
!MESSAGE !MESSAGE
!MESSAGE NMAKE の実行時に構成を指定できます !MESSAGE NMAKE の実行時に構成を指定できます
!MESSAGE コマンド ライン上でマクロの設定を定義します。例: !MESSAGE コマンド ライン上でマクロの設定を定義します。例:
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug" !MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug"
!MESSAGE !MESSAGE
!MESSAGE 選択可能なビルド モード: !MESSAGE 選択可能なビルド モード:
!MESSAGE !MESSAGE
!MESSAGE "dlltest - Win32 Release" ("Win32 (x86) Console Application" 用) !MESSAGE "dlltest - Win32 Release" ("Win32 (x86) Console Application" 用)
!MESSAGE "dlltest - Win32 Debug" ("Win32 (x86) Console Application" 用) !MESSAGE "dlltest - Win32 Debug" ("Win32 (x86) Console Application" 用)
!MESSAGE !MESSAGE
# Begin Project # Begin Project
# PROP Scc_ProjName "" # PROP Scc_ProjName ""
# PROP Scc_LocalPath "" # PROP Scc_LocalPath ""
CPP=cl.exe CPP=cl.exe
RSC=rc.exe RSC=rc.exe
!IF "$(CFG)" == "dlltest - Win32 Release" !IF "$(CFG)" == "dlltest - Win32 Release"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release" # PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x411 /d "NDEBUG" # ADD BASE RSC /l 0x411 /d "NDEBUG"
# ADD RSC /l 0x411 /d "NDEBUG" # ADD RSC /l 0x411 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"minibz2.exe" # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"minibz2.exe"
!ELSEIF "$(CFG)" == "dlltest - Win32 Debug" !ELSEIF "$(CFG)" == "dlltest - Win32 Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "dlltest_" # PROP BASE Output_Dir "dlltest_"
# PROP BASE Intermediate_Dir "dlltest_" # PROP BASE Intermediate_Dir "dlltest_"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "dlltest_" # PROP Output_Dir "dlltest_"
# PROP Intermediate_Dir "dlltest_" # PROP Intermediate_Dir "dlltest_"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x411 /d "_DEBUG" # ADD BASE RSC /l 0x411 /d "_DEBUG"
# ADD RSC /l 0x411 /d "_DEBUG" # ADD RSC /l 0x411 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"minibz2.exe" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"minibz2.exe" /pdbtype:sept
!ENDIF !ENDIF
# Begin Target # Begin Target
# Name "dlltest - Win32 Release" # Name "dlltest - Win32 Release"
# Name "dlltest - Win32 Debug" # Name "dlltest - Win32 Debug"
# Begin Source File # Begin Source File
SOURCE=.\bzlib.h SOURCE=.\bzlib.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\dlltest.c SOURCE=.\dlltest.c
# End Source File # End Source File
# End Target # End Target
# End Project # End Project

View file

@ -1,27 +1,27 @@
LIBRARY LIBBZ2 LIBRARY LIBBZ2
DESCRIPTION "libbzip2: library for data compression" DESCRIPTION "libbzip2: library for data compression"
EXPORTS EXPORTS
BZ2_bzCompressInit BZ2_bzCompressInit
BZ2_bzCompress BZ2_bzCompress
BZ2_bzCompressEnd BZ2_bzCompressEnd
BZ2_bzDecompressInit BZ2_bzDecompressInit
BZ2_bzDecompress BZ2_bzDecompress
BZ2_bzDecompressEnd BZ2_bzDecompressEnd
BZ2_bzReadOpen BZ2_bzReadOpen
BZ2_bzReadClose BZ2_bzReadClose
BZ2_bzReadGetUnused BZ2_bzReadGetUnused
BZ2_bzRead BZ2_bzRead
BZ2_bzWriteOpen BZ2_bzWriteOpen
BZ2_bzWrite BZ2_bzWrite
BZ2_bzWriteClose BZ2_bzWriteClose
BZ2_bzWriteClose64 BZ2_bzWriteClose64
BZ2_bzBuffToBuffCompress BZ2_bzBuffToBuffCompress
BZ2_bzBuffToBuffDecompress BZ2_bzBuffToBuffDecompress
BZ2_bzlibVersion BZ2_bzlibVersion
BZ2_bzopen BZ2_bzopen
BZ2_bzdopen BZ2_bzdopen
BZ2_bzread BZ2_bzread
BZ2_bzwrite BZ2_bzwrite
BZ2_bzflush BZ2_bzflush
BZ2_bzclose BZ2_bzclose
BZ2_bzerror BZ2_bzerror

View file

@ -1,130 +1,130 @@
# Microsoft Developer Studio Project File - Name="libbz2" - Package Owner=<4> # Microsoft Developer Studio Project File - Name="libbz2" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00 # Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** 編集しないでください ** # ** 編集しないでください **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=libbz2 - Win32 Debug CFG=libbz2 - Win32 Debug
!MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 !MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。
!MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください !MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "libbz2.mak". !MESSAGE NMAKE /f "libbz2.mak".
!MESSAGE !MESSAGE
!MESSAGE NMAKE の実行時に構成を指定できます !MESSAGE NMAKE の実行時に構成を指定できます
!MESSAGE コマンド ライン上でマクロの設定を定義します。例: !MESSAGE コマンド ライン上でマクロの設定を定義します。例:
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "libbz2.mak" CFG="libbz2 - Win32 Debug" !MESSAGE NMAKE /f "libbz2.mak" CFG="libbz2 - Win32 Debug"
!MESSAGE !MESSAGE
!MESSAGE 選択可能なビルド モード: !MESSAGE 選択可能なビルド モード:
!MESSAGE !MESSAGE
!MESSAGE "libbz2 - Win32 Release" ("Win32 (x86) Dynamic-Link Library" 用) !MESSAGE "libbz2 - Win32 Release" ("Win32 (x86) Dynamic-Link Library" 用)
!MESSAGE "libbz2 - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" 用) !MESSAGE "libbz2 - Win32 Debug" ("Win32 (x86) Dynamic-Link Library" 用)
!MESSAGE !MESSAGE
# Begin Project # Begin Project
# PROP Scc_ProjName "" # PROP Scc_ProjName ""
# PROP Scc_LocalPath "" # PROP Scc_LocalPath ""
CPP=cl.exe CPP=cl.exe
MTL=midl.exe MTL=midl.exe
RSC=rc.exe RSC=rc.exe
!IF "$(CFG)" == "libbz2 - Win32 Release" !IF "$(CFG)" == "libbz2 - Win32 Release"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release" # PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x411 /d "NDEBUG" # ADD BASE RSC /l 0x411 /d "NDEBUG"
# ADD RSC /l 0x411 /d "NDEBUG" # ADD RSC /l 0x411 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"libbz2.dll" # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /out:"libbz2.dll"
!ELSEIF "$(CFG)" == "libbz2 - Win32 Debug" !ELSEIF "$(CFG)" == "libbz2 - Win32 Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug" # PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD BASE RSC /l 0x411 /d "_DEBUG" # ADD BASE RSC /l 0x411 /d "_DEBUG"
# ADD RSC /l 0x411 /d "_DEBUG" # ADD RSC /l 0x411 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"libbz2.dll" /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"libbz2.dll" /pdbtype:sept
!ENDIF !ENDIF
# Begin Target # Begin Target
# Name "libbz2 - Win32 Release" # Name "libbz2 - Win32 Release"
# Name "libbz2 - Win32 Debug" # Name "libbz2 - Win32 Debug"
# Begin Source File # Begin Source File
SOURCE=.\blocksort.c SOURCE=.\blocksort.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\bzlib.c SOURCE=.\bzlib.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\bzlib.h SOURCE=.\bzlib.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\bzlib_private.h SOURCE=.\bzlib_private.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\compress.c SOURCE=.\compress.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\crctable.c SOURCE=.\crctable.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\decompress.c SOURCE=.\decompress.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\huffman.c SOURCE=.\huffman.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\libbz2.def SOURCE=.\libbz2.def
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\randtable.c SOURCE=.\randtable.c
# End Source File # End Source File
# End Target # End Target
# End Project # End Project

View file

@ -1,63 +1,63 @@
# Makefile for Microsoft Visual C++ 6.0 # Makefile for Microsoft Visual C++ 6.0
# usage: nmake -f makefile.msc # usage: nmake -f makefile.msc
# K.M. Syring (syring@gsf.de) # K.M. Syring (syring@gsf.de)
# Fixed up by JRS for bzip2-0.9.5d release. # Fixed up by JRS for bzip2-0.9.5d release.
CC=cl CC=cl
CFLAGS= -DWIN32 -MD -Ox -D_FILE_OFFSET_BITS=64 -nologo CFLAGS= -DWIN32 -MD -Ox -D_FILE_OFFSET_BITS=64 -nologo
OBJS= blocksort.obj \ OBJS= blocksort.obj \
huffman.obj \ huffman.obj \
crctable.obj \ crctable.obj \
randtable.obj \ randtable.obj \
compress.obj \ compress.obj \
decompress.obj \ decompress.obj \
bzlib.obj bzlib.obj
all: lib bzip2 test all: lib bzip2 test
bzip2: lib bzip2: lib
$(CC) $(CFLAGS) -o bzip2 bzip2.c libbz2.lib setargv.obj $(CC) $(CFLAGS) -o bzip2 bzip2.c libbz2.lib setargv.obj
$(CC) $(CFLAGS) -o bzip2recover bzip2recover.c $(CC) $(CFLAGS) -o bzip2recover bzip2recover.c
lib: $(OBJS) lib: $(OBJS)
lib /out:libbz2.lib $(OBJS) lib /out:libbz2.lib $(OBJS)
test: bzip2 test: bzip2
type words1 type words1
.\\bzip2 -1 < sample1.ref > sample1.rb2 .\\bzip2 -1 < sample1.ref > sample1.rb2
.\\bzip2 -2 < sample2.ref > sample2.rb2 .\\bzip2 -2 < sample2.ref > sample2.rb2
.\\bzip2 -3 < sample3.ref > sample3.rb2 .\\bzip2 -3 < sample3.ref > sample3.rb2
.\\bzip2 -d < sample1.bz2 > sample1.tst .\\bzip2 -d < sample1.bz2 > sample1.tst
.\\bzip2 -d < sample2.bz2 > sample2.tst .\\bzip2 -d < sample2.bz2 > sample2.tst
.\\bzip2 -ds < sample3.bz2 > sample3.tst .\\bzip2 -ds < sample3.bz2 > sample3.tst
@echo All six of the fc's should find no differences. @echo All six of the fc's should find no differences.
@echo If fc finds an error on sample3.bz2, this could be @echo If fc finds an error on sample3.bz2, this could be
@echo because WinZip's 'TAR file smart CR/LF conversion' @echo because WinZip's 'TAR file smart CR/LF conversion'
@echo is too clever for its own good. Disable this option. @echo is too clever for its own good. Disable this option.
@echo The correct size for sample3.ref is 120,244. If it @echo The correct size for sample3.ref is 120,244. If it
@echo is 150,251, WinZip has messed it up. @echo is 150,251, WinZip has messed it up.
fc sample1.bz2 sample1.rb2 fc sample1.bz2 sample1.rb2
fc sample2.bz2 sample2.rb2 fc sample2.bz2 sample2.rb2
fc sample3.bz2 sample3.rb2 fc sample3.bz2 sample3.rb2
fc sample1.tst sample1.ref fc sample1.tst sample1.ref
fc sample2.tst sample2.ref fc sample2.tst sample2.ref
fc sample3.tst sample3.ref fc sample3.tst sample3.ref
clean: clean:
del *.obj del *.obj
del libbz2.lib del libbz2.lib
del bzip2.exe del bzip2.exe
del bzip2recover.exe del bzip2recover.exe
del sample1.rb2 del sample1.rb2
del sample2.rb2 del sample2.rb2
del sample3.rb2 del sample3.rb2
del sample1.tst del sample1.tst
del sample2.tst del sample2.tst
del sample3.tst del sample3.tst
.c.obj: .c.obj:
$(CC) $(CFLAGS) -c $*.c -o $*.obj $(CC) $(CFLAGS) -c $*.c -o $*.obj

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9988" #define REVISION_NR "9989"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__