# VBForums CodeBank > CodeBank - C++ >  C++ - Pure WIN32 Self-Extract EXE Builder (Part - 5)

## Chris

*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).



```

// 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 (0 < dwDataSize)
{
    // Move the file pointer to the begin of the file
    SetFilePointer(hFile, 0, 0, FILE_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_TITLE, MB_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).



```

// Get the total resource size
dwResSize = SizeofResource(hInst, hResource);
// Load the resource content
hResData = LoadResource(hInst, hResource);
// 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(hFile2, 0, 0, FILE_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_TITLE, MB_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_TITLE, MB_OK | MB_ICONSTOP);
    // Jump the the "CleanExit" routine
    goto CleanExit;
} 



```

----------

