Part - 2

The format I adopted
The format I used to merge multiple file into a single file is simple. In general it will split into 3 parts:

First part will indicate how many file available in the merge data file. second and third part will then carry a multiple block of information, as this will varies with how many files (0,1,2,...N) you are going to distribute using the self-extract executable file.

In summary, the overview of the merge data file format will be like the figure show below:

Reason I adopted this format
The thousand and one reason I adopted this format is becuase it was so easy to build (write) and extract (read). All it need is refer to individual file information stored under the header block. So, you can say the header block is the heart of the entire merge data file in this project. Hence, a single silly mistake made in the header block, will cause the SetupEx.exe fail to extract each individual data and restore with it original file property.

What should stored inside header block
The original file information will store under this header block. As these information is subject to change for different application need. Some might need full range of original file information, and some may not. For this project, I stored the information which is just nice for distribute those file does not require extra process (like DLL Register) after deploy.

Again, all these informaiton must be stored in a pre-define structure which will be fully understand between both the SelfExtract.exe and SetupEx.exe. Other wise, you'll have no problem in building the merged data file. But later you'll have problem in extract it. As the data location pointer (memory location) was running out, which will cause the SetupEx.exe over-read or read less data as comapre with the original file. So, this structure is very important in the entire merge data file.

Below is the pre-define EXTRACTFILEINFO structure, which will stored under the header block and used throughout this project.

PHP Code:
typedef struct tagEXTRACTFILEINFO
DWORD        dwIndex;                // Running index value of the current file out of the
                                         // total distributed file count.
FILETIME     CreateTime;             // Original file created time.
FILETIME     LastAcessTime;          // Original file last read/written time.
FILETIME     LastWriteTime;          // Original file last written time.
DWORD        dwFileSizeHigh;         // Specifies the high-order DWORD value of the file size, in bytes.
DWORD        dwFileSizeLow;          // Specifies the low-order DWORD value of the file size, in bytes.
char         szBinFileName[MAX_PATH];// A null-terminated string that is the name of the original file.
The source of all these information is come from the WIN32_FIND_DATA structure as show below:

PHP Code:
typedef struct _WIN32_FIND_DATA {
DWORD            dwFileAttributes
FILETIME         ftCreationTime
FILETIME         ftLastAccessTime
FILETIME         ftLastWriteTime
DWORD            nFileSizeHigh
DWORD            nFileSizeLow
DWORD            dwReserved0
DWORD            dwReserved1
TCHAR            cFileNameMAX_PATH ]; 
TCHAR            cAlternateFileName14 ]; 
Others file information you can include into EXTRACTFILEINFO structure (to enchance the current project) are like those 2 show below. But like I say, this is subjected to your application need.

For instance, if you wish to distribute an ActiveX, then most likely you can not skip the Dll registeration (by execute the regsvr32.exe) process right after deploy to the target machine. Therefore, base on the bDllSelfRegister value; the self-extract executable will automate the register ActiveX Dll process for you.

While, if you wish to include sub-folder into the your distribution package. Then you will require to include the dwAttributes information. As this indication will instruct the self-extract executable file to create the respective sub-folder before it proceed to deploy those files which sit inside this sub-folder. Else, the entire process will fail.

PHP Code:
typedef struct tagEXTRACTFILEINFO
    DWORD        dwFileAttributes
;        // Original file attributes. 
BOOL         bDllSelfRegister;        // Indicate the file require (most likely is *.DLL)
                                          // is require register or not.