Part - 5

Read data from custom resource table
Now, we have done the compressed merge data file. But before we can further make it become self-extract, we must require another module (SetupEx.exe) to perform a series of reverse process. As listed at the begining of this article, and I'll not discuss more on this module. Because what it does is basically the reverse process of what we have discuss above. If you know how to build the merge data file, sure it will no a problem to understand the code (SetupEx.exe) that use to restore the original file from a single compressed merge data file.

But before I move further, I have an important note for those wish to modify the SetupEx.exe. Because the follow code snippet is the key code of the entire SetupEx.exe (restoring individual file from the merge data without distorted or lost it original contents).

PHP Code:
// Get the current data file size base on the information
// store in the lpefi:
//        lpefi[dwIndex1].dwFileSizeHigh
//        lpefi[dwIndex1].dwFileSizeLow 
//
dwDataSize = (lpefi[dwIndex1].dwFileSizeHigh*(MAXDWORD+1)) + 
              
lpefi[dwIndex1].dwFileSizeLow;

// Ensure the file size of not 0Byte
if (dwDataSize)
{
    
// Move the file pointer to the begin of the file
    
SetFilePointer(hFile00FILE_BEGIN);
    
// Write data into a temp file
    
WriteFile(hFile,
              &
lpBinData[dwDataPtr],
              
dwDataSize,
              &
dwByteWrite,
              
NULL);

    
// Ensure the byte write is equal to the calculated data size
    
if (dwByteWrite != dwDataSize)
    {
        
// Notify user about the error
        
MessageBox(hWnd"Writing data error, updating process aborted!"APP_TITLEMB_OK MB_ICONSTOP);
        
// Jump the the "RollBack" routine
        
goto RollBack;
    }

    
// Update the filetime information
    
SetFileTime(hFile,
                &
lpefi[dwIndex1].CreateTime,
                &
lpefi[dwIndex1].LastAcessTime,
                &
lpefi[dwIndex1].LastWriteTime); 

    
// Close the current open file handle
    
if (NULL != hFile) {CloseHandle(hFile);}
    
hFile NULL;

    
// Increate the local data pointer (dwDataPtr)
    
dwDataPtr += dwDataSize;

Since the SetupEx.exe was embedded inside the SelfExtact.exe (the program that will create the self-extract executable file). So, we must first spawn the SetupEx.exe by read it binary daat from the custom resource table under the SelfExtract.exe (as how in figure below), then write it into a new create file.



The code snippet below show how we can spawn the SetupEx.exe from the binary data (IDR_EXTRACTOR1) stored inside the custom resource table (EXTRACTOR).

PHP Code:
// Get the total resource size
dwResSize SizeofResource(hInsthResource);
// Load the resource content
hResData LoadResource(hInsthResource);
// Checking
if (hResData != NULL && dwResSize != 0)
{
    
// Ensure the lpData is NULL
    
lpData NULL;
    
// Obtain the string pointer from the loaded resource handle
    
lpData LockResource(hResData);
    
// Save the current read data into a file
    
hFile2 CreateFile(szTmpBinFile4,
                        
GENERIC_WRITE,
                        
FILE_SHARE_WRITE,
                        
NULL,
                        
CREATE_ALWAYS,
                        
FILE_ATTRIBUTE_NORMAL,
                        
NULL);

    
// Check the return handle value
    
if (NULL != hFile2 && INVALID_HANDLE_VALUE != hFile2)
    {
        
// Move the file pointer to the begin of the file
        
SetFilePointer(hFile200FILE_BEGIN);
        
// Write the read data into a temp file
        
WriteFile(hFile2,
                  (
LPBYTE)lpData,
                  
dwResSize,
                  &
dwByteWrite,
                  
NULL);
        
// Close the current open data file
        
if (NULL != hFile2) {CloseHandle(hFile2);}
        
hFile2 NULL;
    }
    else
    {
        
// Notify user about the error
        
MessageBox(hWnd"Fail to spawning the self-extract kernel!"APP_TITLEMB_OK MB_ICONSTOP);
        
// Jump the the "CleanExit" routine
        
goto CleanExit;
    }
}
else
{
    
// Notify user about the error
    
MessageBox(hWnd"Fail to read the self-extract kernel binary data!"APP_TITLEMB_OK MB_ICONSTOP);
    
// Jump the the "CleanExit" routine
    
goto CleanExit;