Split a .wim File into Multiple Parts

The following code example demonstrates how to split an image into multiple parts, by using the WIMSplitFile function.

Example

#include <stdio.h>
#include <windows.h>
#include <wimgapi.h>
#include <strsafe.h>

//
// Callback function:
//
DWORD
WINAPI
SampleSplitCallback(
    DWORD dwMsgId, // Message ID
    WPARAM wParam, // Usually a file name
    LPARAM lParam, // Usually an error codeb
    PVOID pvUnused
    )
{
    PLARGE_INTEGER pliChunkSize = NULL;
    PWSTR *ppszFileName = NULL;

    switch (dwMsgId)
    {
        case WIM_MSG_SPLIT:

            // This message is sent when each split .wim file is successful.
            // You can change a split .wim file name or size by using this message.
            //

            ppszFileName = (PWSTR*)wParam;
            pliChunkSize = (PLARGE_INTEGER)lParam;

            wprintf(L"Current chunk name: %s\n", *ppszFileName);
            wprintf(L"Current chunk size: %I64d\n", pliChunkSize->QuadPart);

            // Example that shows changing the chunk size to 5MB:
            // pliChunkSize->QuadPart = 5 * 1024 * 1024;

            // Example that shows changing the filename:
#if 0       // To use this code in the example, remove the #if block
            {
                static WCHAR szBuffer[MAX_PATH] = {0};
                static INT iCurrentPart = 0;

                StringCbPrintfW(szBuffer, sizeof(szBuffer), L"file%x.swm", iCurrentPart++);
                *ppszFileName = szBuffer;
            }
#endif

            break;
    }

    return WIM_MSG_SUCCESS;
}

//
// Main function:
//
int __cdecl
wmain(DWORD argc, PWSTR argv[])
{
    BOOL bRet = TRUE;
    HANDLE hWim = NULL;
    DWORD  dwCreateFlags = 0;
    DWORD  dwCreationResult = 0;
    LARGE_INTEGER liChunkSize = {0};
    DWORD dwError = 0;

    PWSTR pszSourceFile  = L"C:\\capture.wim";  // Source .wim file
    PWSTR pszTargetFile  = L"C:\\sample_split.swm";  // Destination split .wim file
    PWSTR pszTmpDir  = L"C:\\tmp";               // Temporary directory: OPTIONAL

    WIM_INFO WimInfo = {0};

    // Specify split chunk size in bytes.
    //
    if ((argc != 2) ||
        !(liChunkSize.QuadPart = _wtol(argv[1])))
    {
        wprintf(L"need split chunk size in bytes\n");
        dwError = ERROR_INVALID_PARAMETER;
        bRet = FALSE;
    }

    // Register the Callback function.
    //
    if (bRet &&
        WIMRegisterMessageCallback(NULL,
                                   (FARPROC)SampleSplitCallback,
                                   NULL) == INVALID_CALLBACK_VALUE)
    {
        dwError = GetLastError();
        bRet = FALSE;
        wprintf(L"Cannot set callback\n");
    }

    // If the image was captured with WIM_FLAG_VERIFY, you can use whole-file verification.
    // The verification will add time to the operation, but can be used to catch WIM file corruption.
    // To enable whole-file verification, use:    
//
    // dwCreateFlags |= WIM_FLAG_VERIFY;

    // Open the source .wim file.
    //
    if (bRet)
    {
        hWim = WIMCreateFile(pszSourceFile,
                             WIM_GENERIC_READ,
                             WIM_OPEN_EXISTING,
                             dwCreateFlags,
                             0,
                             &dwCreationResult);

        if (!hWim)
        {
            dwError = GetLastError();
            bRet = FALSE;

            wprintf(L"Cannot open src WIM file\n");
        }
    }

    if (bRet)
    {
        bRet = WIMGetAttributes(hWim, &WimInfo, sizeof(WimInfo));

        if (!bRet)
        {
            dwError = GetLastError();

            wprintf(L"WIMGetAttributes failed\n");
        }
    }

    // Verify if the .wim file has already been split.
    //
    if (bRet && WimInfo.TotalParts != 1)
    {
        dwError = ERROR_INVALID_PARAMETER;
        bRet = FALSE;

        wprintf(L"The .wim file has already been splitted. Cannot split it again.");
    }

    // Split the .wim file.
    //
    if (bRet)
    {
        bRet = WIMSplitFile(hWim, pszTargetFile, &liChunkSize, 0);
        if (!bRet)
        {
            dwError = GetLastError();

            wprintf(L"Split failed\n");

            if (dwError == ERROR_MORE_DATA)
            {
                wprintf(L"Need bigger chunk size to split\n");
            }
        }
    }

    // When you are finished, close the handle that you created in the previous steps.
    //
    if (hWim)
    {
        WIMCloseHandle(hWim);
    }

    WIMUnregisterMessageCallback(NULL, (FARPROC)SampleSplitCallback);

    wprintf(L"Returning status: 0x%x\n", dwError);

    return dwError;
}

See Also

Concepts

Imaging Reference