Capture a Directory into a New .wim File

The following code example demonstrates how to capture a directory into a new .wim file, by using the WIMCaptureImage function.

Example

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

//
// Callback function:
//
DWORD
WINAPI
SampleCaptureCallback(
    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 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 capture the file.
            //

            // Prints out the file name 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 an error 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 dwFlags = 0,
          dwDisposition = 0,
          dwDesiredAccess = 0,
          dwCreateFlags = 0,
          dwCaptureFlags = 0,
          dwCompressionType = 0,
          dwCreationResult = 0,
          dwError = 0;

    PWSTR pszWimFile    = L"C:\\sample_image.wim";  // Destination .wim file that you want to capture the image to
    PWSTR pszTmpDir     = L"C:\\tmp";               // Temporary directory: OPTIONAL
    PWSTR pszCaptureDir = L"C:\\src";               // Capture directory or drive

    // Inspect the caller's parameters.
    //
    if (argc < 1 || argc > 2)
    {
        dwError = ERROR_INVALID_PARAMETER;
        bRet = FALSE;
    }

    if (bRet)
    {
        if (argc == 1)
        {
            // Use "capture" mode. Overwrite a pre-existing .wim file.
            //
            dwDisposition = WIM_CREATE_ALWAYS;
            dwDesiredAccess = WIM_GENERIC_WRITE;
        }
        else if (*argv[1] == L'a')
        {
            // Use "append" mode. Add a new image index to a pre-existing
            // .wim file if one is found.
            //
            dwDisposition = WIM_OPEN_EXISTING;
            dwDesiredAccess = WIM_GENERIC_WRITE | WIM_GENERIC_READ;
        }
        else
        {
            wprintf(L"need 'a' to append\n");
            dwError = ERROR_INVALID_PARAMETER;
            bRet = FALSE;
        }
    }

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

    // Open the .wim file
    //
    if (bRet)
    {
        // Use LZX compression ("/compress max"). Other possibilities include:
        // WIM_COMPRESS_NONE - No compression
        // WIM_COMPRESS_XPRESS - "Fast" compression
        //
        dwCompressionType = WIM_COMPRESS_LZX;

        // Optionally, if the image was captured with WIM_FLAG_VERIFY, 
        // you can use whole-file verification. Whole-file
        // verification performs extra hashing checks and generates extra hashes.
        // It detects file corruption due to a bad disk or a
        // faulty network connection, but it adds time to the operation due to
        // extra I/O operations and extra hash checks. 
// To enable whole-file verification, use:
        //
        // dwCreateFlags |= WIM_FLAG_VERIFY;

        hWim = WIMCreateFile(pszWimFile,
                             dwDesiredAccess,
                             dwDisposition,
                             dwCreateFlags,
                             dwCompressionType,
                             &dwCreationResult);

        if (!hWim)
        {
            bRet = FALSE;
            dwError = GetLastError();
            wprintf(L"Cannot open WIM file\n");
        }
    }

    // WIMGAPI uses temporary files. You must specify where to store the files.
    //
    if (bRet)
    {
        bRet = WIMSetTemporyPath(hWim, pszTmpDir);

        if (!bRet)
        {
            dwError = GetLastError();
            wprintf(L"Cannot set temporary directory\n");
        }
    }
    // 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 capture operation.
    // To enable per-file verification, use:
    //
    // dwCaptureFlags |= WIM_FLAG_VERIFY;

    // Finally, perform the capture operation.
    //
    if (bRet)
    {
        hImage = WIMCaptureImage(hWim, pszCaptureDir, dwCaptureFlags);

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

            wprintf(L"Cannot capture/append image\n");
        }
    }

    // When you are finished, close the handles that you created in the previous steps.
    // Note: you must close image handles before you close WIM handles.
    //
    if (hImage) WIMCloseHandle(hImage);
    if (hWim)   WIMCloseHandle(hWim);

    WIMUnregisterMessageCallback(NULL, (FARPROC)SampleCaptureCallback);

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

    return dwError;
}

See Also

Concepts

Imaging Reference