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

## Chris

*Part - 4*

*How to build the merge data file*
At this stage, you have gain all the minimum knowledge on accessing the file I/O. Also, you get the idea how the final merge data file being structure. So, it is the big time for the core task of the entire project... building the merge data file. Before I start explain the most interesting part (program code) step by step, let recap some of the important step to build the merge data file.



*NOTE:*
In the following code snippet, I was filter out those code related to GUI update. These GUI update is mainly to keep the user inform about the status of the entire building self-extract executable file process. If you wish to get more about this GUI update code, you can always refer to the full source code enclosed together with this article.

Basically, the following code snippet will cover from step #1 and #4. Which is a do... while... loop to scan through the folder.



```

// Get the current user define source folder
GetDlgItemText(hWnd, IDC_EDIT1, szBuffer1, sizeof(szBuffer1));

// Format the full path for the source folder
sprintf(szBuffer2,
        "%s\\*.*",
        szBuffer1);

// Start scaning the directory
hFile = FindFirstFile(szBuffer2, &wfs);

// Check the return handle value
do
{
    // Check is the current found file is directory?
    if (!(FILE_ATTRIBUTE_DIRECTORY & wfs.dwFileAttributes))
    {
        // Save the information into data file
        WriteSelfExtractHeader (hWnd, &wfs);
        // Save the information into data file
        WriteSelfExtractBinData (hWnd, &wfs);
    }

    // Scan the next match item in the directory
    if (!FindNextFile(hFile, &wfs))
    {
        if (ERROR_NO_MORE_FILES == GetLastError()) {break;}
    }

} while (NULL != hFile || INVALID_HANDLE_VALUE != hFile);

// Close the search handle
if (NULL != hFile) {FindClose(hFile);}
hFile = NULL; 



```

Next block of code snippet will cover the reading & writing the file information into the header block. As well as the code for reading & writing the content of the current file.

*NOTE:*
The file size informatin is very important in the (SetupEx.exe) module, because this will be the key information that instruct the SetupEx.exe how much it should move the file pointer in order to get back to the original staring point of the each individual distributed file.



```

void WriteSelfExtractHeader (HWND hWnd, LPWIN32_FIND_DATA lpFindFileData)
{
    EXTRACTFILEINFO    efi = {NULL};
    
    HANDLE    hFile        = NULL;
    DWORD     dwByteWrite  = 0;

    __try
    {
        // Open the existing temporary data file
        hFile = CreateFile(szTmpBinFile1,
                           GENERIC_WRITE,
                           FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

        // Check the return handle value
        if (NULL == hFile || INVALID_HANDLE_VALUE == hFile)
        {
            // Open the existing temporary data file
            hFile = CreateFile(szTmpBinFile1,
                               GENERIC_WRITE,
                               FILE_SHARE_WRITE,
                               NULL,
                               CREATE_NEW,
                               FILE_ATTRIBUTE_NORMAL,
                               NULL);            
        }

        // Check the return handle value
        if (NULL != hFile && INVALID_HANDLE_VALUE != hFile)
        {
            // Reset the local EXTRACTFILEINFO structure
            ZeroMemory(&efi, sizeof(EXTRACTFILEINFO));

            // Initialize the EXTRACTFILEINFO structure
            efi.dwIndex = dwFileCount;
            CopyMemory(&efi.CreateTime,     &lpFindFileData->ftCreationTime,   sizeof(FILETIME));
            CopyMemory(&efi.LastAcessTime,  &lpFindFileData->ftLastAccessTime, sizeof(FILETIME));
            CopyMemory(&efi.LastWriteTime,  &lpFindFileData->ftLastWriteTime,  sizeof(FILETIME));
            CopyMemory(&efi.dwFileSizeHigh, &lpFindFileData->nFileSizeHigh ,   sizeof(DWORD));
            CopyMemory(&efi.dwFileSizeLow,  &lpFindFileData->nFileSizeLow,     sizeof(DWORD));
            CopyMemory(&efi.szBinFileName,  &lpFindFileData->cFileName,        strlen(lpFindFileData->cFileName));

            // Check current file count & move the file pointer
            if (0 == dwFileCount)
                SetFilePointer(hFile, sizeof(UPDATEINFO), 0, FILE_BEGIN);
            else
                SetFilePointer(hFile, 0, 0, FILE_END);

            // Write the data into setup list file
            WriteFile(hFile,
                      &efi,
                      sizeof(EXTRACTFILEINFO),
                      &dwByteWrite,
                      NULL);

            // Increate the counter
            dwFileCount++;
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        // PUT YOUR ERROR HANDLING CODE HERE

    }

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


void WriteSelfExtractBinData (HWND hWnd, LPWIN32_FIND_DATA lpFindFileData)
{
    HANDLE    hFile         = NULL;
    LPBYTE    lpData        = NULL;
    DWORD     dwSize        = 0;
    DWORD     dwByteRead    = 0;
    DWORD     dwByteWrite   = 0;

    char    szBuffer1[MAX_PATH] = {NULL};
    char    szBuffer2[MAX_PATH] = {NULL};

    __try
    {
        // Get the user define source folder
        GetDlgItemText(hWnd, IDC_EDIT1, szBuffer1, sizeof(szBuffer1));
        // Format the full file path
        sprintf(szBuffer2, 
            "%s\\%s",
            szBuffer1, lpFindFileData->cFileName); 
        
        // STAGE #1
        // Read the current binary file data
        hFile = CreateFile(szBuffer2,
                           GENERIC_READ,
                           FILE_SHARE_READ,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);
        // Check the return handle value
        if (NULL != hFile && INVALID_HANDLE_VALUE != hFile)
        {
            // Get the current file size
            dwSize = (lpFindFileData->nFileSizeHigh*(MAXDWORD+1)) + 
                      lpFindFileData->nFileSizeLow;
            // Allocate local data buffer
            lpData = (LPBYTE)LocalAlloc(LPTR, dwSize);
            // Reset local data buffer
            ZeroMemory(lpData, dwSize);
            
            // Move the file pointer to the begining
            SetFilePointer(hFile, 0, 0, FILE_BEGIN);
            // Read the binary data
            ReadFile(hFile, lpData, dwSize, &dwByteRead, NULL);
        }

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


        // STAGE #2
        // WRITE THE READ BINDARY DATA INTO THE TEMPORARY FILE
        // Open the existing setup data file (szTmpBinFile2)
        hFile = CreateFile(szTmpBinFile2,
                           GENERIC_WRITE,
                           FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

        // Check the return handle value
        if (NULL == hFile || INVALID_HANDLE_VALUE == hFile)
        {
            // Open the existing setup.lst data file
            hFile = CreateFile(szTmpBinFile2,
                               GENERIC_WRITE,
                               FILE_SHARE_WRITE,
                               NULL,
                               CREATE_NEW,
                               FILE_ATTRIBUTE_NORMAL,
                               NULL);            
        }

        // Check the return handle value
        if (NULL != hFile && INVALID_HANDLE_VALUE != hFile)
        {
            // Move the file pointer
            SetFilePointer(hFile, 0, 0, FILE_END);

            // Write the data into setup list file
            WriteFile(hFile,
                      lpData,
                      dwSize,
                      &dwByteWrite,
                      NULL);
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        // PUT YOUR ERROR HANDLING CODE HERE

    }

    // Release the allocated data buffer
    if (NULL != lpData){LocalFree((LPBYTE)lpData);}
    lpData = NULL;

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

} 



```

----------

