Mount and Unmount an Image

The following code example demonstrates how to mount and to unmount an image, by using the WIMMountImage and WIMUnmountImage functions.

Example

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

#define MOUNT_DIRECTORY L"c:\\mount"
#define WIM_FILE        L"c:\\sample_image.wim"
#define IMAGE_INDEX     1

DWORD MountImage(BOOL bOpenForWriting)
{
    BOOL  bRet    = FALSE;
    DWORD dwError = ERROR_SUCCESS;
    WCHAR szTempPath[MAX_PATH] = {0};
    HANDLE hWim   = NULL;
    HANDLE hImage = NULL;

    // Get a temporary working directory to use with WIMGAPI.
    //
    bRet = GetTempPathW(ARRAYSIZE(szTempPath), szTempPath);
    if (!bRet)
    {
        dwError = GetLastError();
        wprintf(L"Error 0x%08x while attempting to determine temporary path.\n", dwError);
    }

    // Open the Windows image.
    //
    if (bRet)
    {
        DWORD dwDesiredAccess = WIM_GENERIC_READ | WIM_GENERIC_MOUNT;
        DWORD dwCreateFlags = 0;
        DWORD dwCreationResult = 0;

        if (bOpenForWriting)
        {
            dwDesiredAccess |= WIM_GENERIC_WRITE;
        }

        // 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(WIM_FILE,
                             dwDesiredAccess,
                             WIM_OPEN_EXISTING,
                             dwCreateFlags,
                             0,
                             &dwCreationResult);
        if (!hWim)
        {
            dwError = GetLastError();
            bRet = FALSE;

            wprintf(L"Error 0x%08x while opening the WIM.\n", dwError);
        }
    }

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

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

            wprintf(L"Error 0x%08x while setting temporary path.\n", dwError);
        }
    }

    // Acquire an image handle.
    //
    if (bRet)
    {
        hImage = WIMLoadImage(hWim, IMAGE_INDEX);

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

            wprintf(L"Error 0x%08x while acquiring image handle.\n", dwError);
        }
    }

    // Finally, mount the image.
    //
    if (bRet)
    {
        DWORD dwMountFlags = 0;

        if (!bOpenForWriting)
        {
            dwMountFlags |= WIM_FLAG_MOUNT_READONLY;
        }

        // 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 mount operation.
        // To enable per-file verification, use:
        //
        // dwMountFlags |= WIM_FLAG_VERIFY;

        //
        // Note: For progress reporting, use WIMRegisterMessageCallback. 
        // For more information, see the Apply an Image from a .wim File code sample.
        //

        bRet = WIMMountImageHandle(hImage, MOUNT_DIRECTORY, dwMountFlags);

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

            wprintf(L"Error 0x%08x while mounting image.\n", dwError);
        }
    }

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

    return dwError;
}

DWORD UnmountImage(BOOL bCommitChanges)
{
    BOOL  bRet    = TRUE;
    DWORD dwError = ERROR_SUCCESS;
    HANDLE hWim   = NULL;
    HANDLE hImage = NULL;
    DWORD dwHandleFlags = 0;

    // 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:
    //
    // dwHandleFlags |= WIM_FLAG_VERIFY;

    bRet = WIMGetMountedImageHandle(MOUNT_DIRECTORY, dwHandleFlags, &hWim, &hImage);
    if (!bRet)
    {
        dwError = GetLastError();

        wprintf(L"Error 0x%x attempting to obtain an image handle.\n", dwError);
    }

    if (bRet && bCommitChanges)
    {
        DWORD dwCommitFlags = 0;
        
        // 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 commit operation.
        // To enable per-file verification, use:
        //
        //dwCommitFlags |= WIM_FLAG_VERIFY;

        bRet = WIMCommitImageHandle(hImage, dwCommitFlags, NULL);
        if (!bRet)
        {
            dwError = GetLastError();
            wprintf(L"Error 0x%x attempting to commit the image\n", dwError);
        }
    }

    if (bRet)
    {
        //
        // Note: For progress reporting, use WIMRegisterMessageCallback.  
        // For more information, see the Apply an Image from a .wim File code sample.
        //

        bRet = WIMUnmountImageHandle(hImage, 0);

        if (!bRet)
        {
            dwError = GetLastError();
            wprintf(L"Error 0x%x attempting to unmount the image\n", dwError);
        }
    }

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

    return dwError;
}

// Main function
//
int __cdecl wmain(int argc, PWSTR argv[])
{
    DWORD dwError = ERROR_SUCCESS;

    // Mount the image.
    //
    dwError = MountImage(TRUE);

    // Unmount the image and commit changes.
    //
    if (ERROR_SUCCESS == dwError)
    {
        dwError = UnmountImage(TRUE);
    }    

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

    return dwError;
}

Remarks

  • When mounting an image, you must ensure that the temporary path does not lie within the mount path.

  • If you intend to mount an image for read-only access, do not specify a temporary path.

See Also

Show: