LAST VERSION - 1.0 22-Mar-12 I think many of you would like to combine any data of your project, for example skin images, into a single file (package), and as necessary extract them from it. Moreover, it would be better to avoid creating temporary files on the disk. Yes, of course, you can use a resources of the executable file or native FileInstall() function, but in the first case you can not add data after compilation the script, the second case leads inevitably to write data to disk that is not good. Alternatively, you can use, for example, .zip archives, but here again you are limited to using only the files. For this reason, I decided to invent their own file format (.pkr) for storing any data (it can be a files or a memory data directly), and devoid of all the above shortcomings. Below is the detailed structure of the .pkr file (package). As you can see from the screenshot, the package consists of a header and one or more data packets following one another. The package header has a length of 256 bytes and represents PKHEADER structure that contains a basic information about .pkr file, including a short text comment. Here is a description of the PKHEADER structure. --------------------------------------------------------------------------------------------------
| PKHEADER |
|--------------------------------------------------------------------------------------------------|
| Offset | Length | Purpose |
|--------|--------|--------------------------------------------------------------------------------|
| 0 | 4 | The file signature (0x504B5221) |
|--------|--------|--------------------------------------------------------------------------------|
| 4 | 4 | The package version, 1.0 |
|--------|--------|--------------------------------------------------------------------------------|
| 8 | 8 | The file size, in bytes |
|--------|--------|--------------------------------------------------------------------------------|
| 16 | 4 | The number of packets in the package |
|--------|--------|--------------------------------------------------------------------------------|
| 20 | 4 | Reserved |
|--------|--------|--------------------------------------------------------------------------------|
| 24 | 8 | The absolute offset, in bytes, of the first packet in package |
|--------|--------|--------------------------------------------------------------------------------|
| 32 | 224 | The package comment, max 224 bytes (112 characters) |
--------------------------------------------------------------------------------------------------The first four bytes of the .pkr file always contain the same sequence of bytes (signature) - 0x504B5221 ("PKR!" in ASCII characters). This allows to uniquely identify the package. Then follows a DWORD value representing the package version, currently 1.0 (0x00000100). Next is the size of the package file (INT64), in bytes. Although the size of the .pkr file is not limited, the length of one packet may not exceed a little more than 4 gigabytes (see below). Note that the value of this member should be equal to the actual file size, otherwise it is assumed that the package is damaged. The next member (DWORD) of the structure contains the number of packets in the package. It should not be zero, since it is not allowed to create empty packages. The next four bytes are reserved for future use. The sixth member (INT64) of the PKHEADER structure is the most important and contains an offset of the first packet in the package from the beginning of a file, in bytes. This means that the first packet does not necessarily follow immediately after the header. The latest in the package header is a comment. The length of the comment is limited to 224 bytes (112 wide characters, including the null-terminating character). After the packet header may be located a Packet Relocation Table (PRT) of variable size that contains information for fast packets searching, but is not currently used and has a zero length. Following the PKHEADER and PRT begins a packets. Each packet consists of its own header and three data sections: Description, Info, and Data. Why three? Because so much easier to classify the data within the package. You will understand this when you try to use the library for their projects. A description of the packet (PKPACKET structure) shown in the following table. --------------------------------------------------------------------------------------------------
| PKPACKET |
|--------------------------------------------------------------------------------------------------|
| Offset | Length | Purpose |
|--------|--------|--------------------------------------------------------------------------------|
| 0 | 4 | The size, in bytes, of the packet header structure (40 bytes) |
|--------|--------|--------------------------------------------------------------------------------|
| 4 | 4 | The size, in bytes, of the description block, max 8192 bytes (4096 characters) |
|--------|--------|--------------------------------------------------------------------------------|
| 8 | 4 | The size, in bytes, of the information block, max 64 KB |
|--------|--------|--------------------------------------------------------------------------------|
| 12 | 4 | The size, in bytes, of the data block, max 4 GB |
|--------|--------|--------------------------------------------------------------------------------|
| 16 | 8 | The 64-bit unique identifier of the packet |
|--------|--------|--------------------------------------------------------------------------------|
| 24 | 4 | The checksum (CRC32) of the compressed data, or zero if no compression |
|--------|--------|--------------------------------------------------------------------------------|
| 28 | 4 | The uncompressed data size, in bytes, or zero if no compression |
|--------|--------|--------------------------------------------------------------------------------|
| 32 | 8 | Reserved |
|--------------------------------------------------------------------------------------------------|
| Description |
|--------------------------------------------------------------------------------------------------|
| Information |
|--------------------------------------------------------------------------------------------------|
| Data |
--------------------------------------------------------------------------------------------------The first member (DWORD) of the PKPACKET structure always contains the length, in bytes, of the packet header and currently is 40 bytes, but can be changed in the future. The second, third, and fourth members (DWORD) of the structure contains the lengths of the corresponding data sections, in bytes. If any section is missing, the value of its length is zero. A full packet length, in bytes, can be calculated by summing the four values is listed above. The fifth member (INT64) of the structure represents a unique packet identifier (ID). It is a 64-bit positive number that uniquely identifies a packet within the package. The sixth and seventh members (DWORD) of the PKPACKET structure is used only if a data of the Data sections are compressed, otherwise have a zero values. In the case of compression, the sixth member of the structure contains the exact data size of the Data section, in bytes, after uncompression. The last member (INT64) of the packet header is reserved for future use. Immediately after the packet header begins a three data sections that are described in more detail below. The Description section is the first in the packet and designed to store any text information. It may be, for example, the name of the file, in the case of adding a file into the packet, or just a short description of the data that is in the packet. The maximum length of the this section is 8 kilobytes (8,192 bytes) or 4096 wide characters (including the null-terminating character). The Info section immediately follows after the Description section. Here you can store any auxiliary binary data, for example, the attributes of the file, the date and time that a file was created, last accessed, and last modified., or something else. Alternatively, you can store in this section are small files such as cursors, icons, etc. The length of this section is limited to 64 kilobytes (65,535 bytes). The Data section is the third in the packet, and used to store main packet data. The maximum length of this section may be up to 4 gigabytes (4,294,967,295 bytes). Moreover, the data of this section can be compressed by using the native LZ algorithm (not the most optimal but fast enough). These three data sections represents a one packet, and must follow continuously each other that as shown above. Furthermore, any or all of these sections can be missing in the packet. Then after the first packet immediately begins another packet, if any, etc. As you can see, the .pkr files have a simple structure consisting of the sequential blocks of data. Especially for ease of use of packages, I wrote the UDF library which you can download below. A detailed description of each function you can find inside the library. Also, the archive includes all the examples and supporting files. As an additional example, you can download the Package.pkr file containing the same files as the .zip archive, but only created by using this library. I hope this UDF library will be useful for your projects. Also, if anyone have any questions or comments, please post it in this thread. I will be glad to any feedback and constructive suggestions. Almost forgot, this library requires >WinAPIEx UDF library version 3.7 or later. Available functions Package UDF Library v1.0 Package.zip Examples Extracting file (Simple) Adding binary data (Simple) Extracting binary data (Simple) Addition Extraction GUI (Advanced)