Apply an Image from a .wim File

The following code example demonstrates how to apply an image from a .wim file, by using the WIMApplyImage function.

Example

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

//
// Callback function:
//
DWORD
WINAPI
SampleApplyCallback(
    DWORD  dwMsgId,  // Message ID
    WPARAM wParam,   // Usually a file name
    LPARAM lParam,   // Usually an error code
    PVOID  pvIgnored // Used to maintain caller context. Not used in this code sample.
    )
{
    PBOOL pbCancel = NULL;

    switch (dwMsgId)
    {
        case WIM_MSG_PROGRESS:

            // Prints out the current progress percentage.
            //
            wprintf(L"%d %%\n", (DWORD)wParam);

            break;

        case WIM_MSG_PROCESS:

            // This message is sent for each file. It reports whether the calling client
            // is trying to apply the file.
            //

            // Prints out the file name that is being processed:
            //
            wprintf(L"FilePath: %s\n", (PWSTR)wParam);

            // To cancel processing on this file, use:
            //
            // pbCancel = (PBOOL)lParam;
            // *pbCancel = TRUE;

            break;

        case WIM_MSG_ERROR:

            // This message is sent when a failure error case is reported.
            //
            wprintf(L"ERROR: %s [err = %d]\n", (PWSTR)wParam, (DWORD)lParam);
            break;

        case WIM_MSG_RETRY:

            // This message is sent when the file is being reapplied because of a
            // network timeout. Retry is attempted up to five times.
            //
            wprintf(L"RETRY: %s [err = %d]\n", (PWSTR)wParam, (DWORD)lParam);
            break;

        case WIM_MSG_INFO:

            // This message is sent when an informational message is available.
            //
            wprintf(L"INFO: %s [err = %d]\n", (PWSTR)wParam, (DWORD)lParam);
            break;

        case WIM_MSG_WARNING:

            // This message is sent when a warning message is available.
            //
            wprintf(L"WARNING: %s [err = %d]\n", (PWSTR)wParam, (DWORD)lParam);
            break;
    }

    //
    // To abort image processing, return WIM_MSG_ABORT_IMAGE. Not all message types
    // check for this status. When you decide to cancel an image, it may take repeated
    // returns of this status before WIMGAPI can perform the cancelation.
    //

    return WIM_MSG_SUCCESS;
}

//
// Main Function:
//
int __cdecl
wmain(DWORD argc, PWSTR argv[])
{
    BOOL   bRet = TRUE;

    HANDLE hWim = NULL,
           hImage = NULL;

    DWORD  dwCreateFlags = 0,
           dwCreateResult = 0,
           dwImageIndex = 0,
           dwError = 0; 

    PWSTR pszWimFile  = L"C:\\capture.wim";  // Source .wim file
    PWSTR pszTmpDir   = L"C:\\tmp";          // Temporary directory
    PWSTR pszApplyDir = L"C:\\restore";      // The directory or drive to which the image is applied

    BOOL  bListOnly = FALSE;       // List the directories and files in the image.
    
    WIM_INFO WimInfo = {0};

    // An image index number is required to apply the image or to display the image info.
    //
    if (argc < 2 ||
        argc > 3 ||
        !(dwImageIndex = _wtoi(argv[1])))
    {
        wprintf(L"need image Index (1-based)\n");

        dwError = ERROR_INVALID_PARAMETER;
        bRet = FALSE;
    }

    // Display the list of directories and files in the image instead of applying the image.
    //
    if (bRet && 
        argc == 3)
    {
        if (*argv[2] != L'd')
        {
            wprintf(L"need 'd' for directory/file listing\n");

            dwError = ERROR_INVALID_PARAMETER;
            bRet = FALSE;
        }

        bListOnly = TRUE;
    }

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

    // Open the .wim file.
    //
    if (bRet)
    {
        // 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;

        hWim = WIMCreateFile(pszWimFile,          // Existing .wim file to append the image to
                             WIM_GENERIC_READ,    // Access mode
                             WIM_OPEN_EXISTING,   // Open disposition
                             dwCreateFlags,
                             0,                   // Compression type is ignored for WIM_OPEN_EXISTING.
                             &dwCreateResult);

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

            wprintf(L"Cannot open .wim file\n");
        }
    }

    //
    // Note: To attach split .wim files (SWM) to this session, use:
    //    WIMSetReferenceFile(hWim, pszFileName, dwFlags)
    //

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

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

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

    if (bRet)
    {
        if (WimInfo.ImageCount < dwImageIndex)
        {
            dwError = ERROR_INVALID_PARAMETER;
            bRet = FALSE;

            wprintf(L"There is no index %d in the WIM file\n", dwImageIndex);
        }
    }

    // Set the temporary working directory.
    //
    if (bRet)
    {
        bRet = WIMSetTemporaryPath(hWim, pszTmpDir);

        if (!bRet)
        {
            dwError = GetLastError();
            wprintf(L"cannot set temp path to work in\n");
        }
    }

    // Retrieve the image handle for the image at the given index.
    //
    if (bRet)
    {
        hImage = WIMLoadImage(hWim, dwImageIndex);
        if (!hImage)
        {
            dwError = GetLastError();
            bRet = FALSE;

            wprintf(L"Cannot load image %d from src WIM file\n", dwImageIndex);
        }
    }

    // Finally, apply the image.
    //
    if (bRet)
    {
        DWORD dwApplyFlags = 0;

        if (bListOnly)
        {
            dwApplyFlags |= WIM_FLAG_NO_APPLY;
        }

        // Optionally, you can enable per-file verification. Per-file verification will perform redundant
        // hash checks to detect .wim file corruption. The check will add time to the apply operation.
        // To enable per-file verification, use:
        //
        // dwApplyFlags |= WIM_FLAG_VERIFY;

        bRet = WIMApplyImage(hImage, pszApplyDir, dwApplyFlags);
        if (!bRet)
        {
            dwError = GetLastError()

            wprintf(L"Applying image failed\n");
        }
    }

    if (hImage) WIMCloseHandle(hImage);
    if (hWim)   WIMCloseHandle(hWim);

    WIMUnregisterMessageCallback(NULL, (FARPROC)SampleApplyCallback);

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

    return dwError;
}

See Also

Concepts

Imaging Reference