Share via


EWF API Code Sample

5/10/2007

Sample.cpp provides an example of using the Enhanced Write Filter (EWF) API to perform the following actions:

  • To obtain and display the EWF overlay configuration
  • To obtain and display the EWF-protected volume configurations
  • To issue EWF commands to protected volumes

The following table shows the routines that are used in Sample.cpp.

Routine Description

DoReboot

Reboots the system for EWF functions that require a system reboot.

DisplayEWFVolumeConfig

Displays the EWF volume configuration that is defined by the EWF_VOLUME_CONFIG structure.

DumpEwfProtectedVolumes

Lists the EWF_VOLUME_CONFIG descriptions for each protected volume on the current system.

DisplayEwfOverlayConfig

Displays EWF overlay configuration that is defined by the EWF_OVERLAY_STORE_CONFIG structure.

DumpEwfOverlayConfig

Uses EwfMgrOpenOverlayStore to open a handle to the overlay partition.

DoEwfClearCommand

Demonstrates the use of the EwfMgrClearCommand function.

DoEwfPersistCommands

Demonstrates the use of the EwfMgrSetPersistentData and EwfMgrGetPersistentData functions.

DoEwfCheckPoint

Demonstrates the use of the EwfMgrCheckpoint function.

DoEwfRestore

Demonstrates the use of EwfMgrRestore function.

DoEwfEnable

Demonstrates the use of the EwfMgrEnable function.

DoEwfDisable

Demonstrates the use of the EwfMgrDisable function.

DoEwfCommit

Demonstrates the use of the DoEwfCommit function.

DoEwfSetLevel

Demonstrates the use of the EwfMgrSetLevel function.

DoEwfRegisterLowSpaceSync

Demonstrates the synchronous use of the EwfMgrRegisterLowSpaceNotification function.

DoEwfRegisterLowSpaceAsync

Demonstrates the asynchronous use of the EwfMgrRegisterLowSpaceNotification function.

DoEwfCommands

Demonstrates how to build a list of EWF-protected volume names and send commands to each of the protected volumes.

Sample.cpp

// Sample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"

#define EWFIMP
#include "ewfapi.h"

/*
EWF API Code Sample
Sample.cpp provides an example of using the Enhanced Write Filter (EWF) API to perform the following actions:
·   To obtain and display the EWF overlay configuration
·   To obtain and display the EWF-protected volume configurations
·   To issue EWF commands to protected volumes
The following table shows the routines that are used in Sample.cpp.

Routine   Description
DoReboot   Reboots the system for EWF functions that require a system reboot.
DisplayEWFVolumeConfig   Displays the EWF volume configuration that is defined by the EWF_VOLUME_CONFIG structure.
DumpEwfProtectedVolumes   Lists the EWF_VOLUME_CONFIG descriptions for each protected volume on the current system.
DisplayEwfOverlayConfig   Displays EWF overlay configuration that is defined by the EWF_OVERLAY_STORE_CONFIG structure.
DumpEwfOverlayConfig   Uses EwfMgrOpenOverlayStore to open a handle to the overlay partition. 
DoEwfClearCommand   Demonstrates the use of the EwfMgrClearCommand function.
DoEwfPersistCommands   Demonstrates the use of the EwfMgrSetPersistentData and EwfMgrGetPersistentData functions.
DoEwfCheckPoint   Demonstrates the use of the EwfMgrCheckpoint function.
DoEwfRestore   Demonstrates the use of EwfMgrRestore function.
DoEwfEnable   Demonstrates the use of the EwfMgrEnable function.
DoEwfDisable   Demonstrates the use of the EwfMgrDisable function.
DoEwfCommit   Demonstrates the use of the DoEwfCommit function.
DoEwfSetLevel   Demonstrates the use of the EwfMgrSetLevel function.
DoEwfRegisterLowSpaceSync   Demonstrates the synchronous use of the EwfMgrRegisterLowSpaceNotification function.
DoEwfRegisterLowSpaceAsync   Demonstrates the asynchronous use of the EwfMgrRegisterLowSpaceNotification function.
DoEwfCommands   Demonstrates how to build a list of EWF-protected volume names and send commands to each of the protected volumes.

Sample.cpp
// Sample.cpp: Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include "ewfapi.h"

/*++

DoReboot

Routine description:
  This routine reboots the system after an EWF boot 
  command is issued by one of the following EWF functions:
    EwfMgrCheckpoint
    EwfMgrRestore
    EwfMgrDisable
    EwfMgrEnable
    EwfMgrCommit
    EwfMgrSetLevel

  A reboot is not required for the following EWF 
  functions:
    EwfMgrClearCommand
    EwfMgrSetPersistentData
    EwfMgrGetPersistentData
Arguments:
  None
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD  DoReboot() 
{
  BOOL bResult = TRUE;
  HANDLE hToken = INVALID_HANDLE_VALUE;
  TOKEN_PRIVILEGES tkp;
  DWORD dwStatus = ERROR_SUCCESS;

  //Get a token for this process.
  bResult = OpenProcessToken(
    GetCurrentProcess(),
    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
    &hToken);

  if (!bResult) goto exit;
  bResult = LookupPrivilegeValue(
    NULL,
    SE_SHUTDOWN_NAME,
    &tkp.Privileges[0].Luid);

  if (!bResult) goto exit;
  tkp.PrivilegeCount = 1;
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  
  bResult = AdjustTokenPrivileges(
    hToken,
    FALSE,
    &tkp,
    0,NULL,
    0);

  if (!bResult) goto exit;
  bResult = ExitWindowsEx(EWX_REBOOT | EWX_FORCE,0);

exit:
  if (!bResult)
  {
    dwStatus = GetLastError();
  }
  if (hToken != INVALID_HANDLE_VALUE)
  {
     CloseHandle(hToken);
  }
  return dwStatus;
}

/*++

DisplayEWFVolumeConfig

Routine description:

  This routine displays an EWF volume configuration, which is 
  defined by the EWF_VOLUME_CONFIG structure (ewfapi.h) 
  and includes the following members:

    Type:              Specifies the type of overlay for this volume:
                       RAM, registry-described RAM, or disk.
    State:             Specifies the state of the overlay for this volume,
                       either ENABLED or DISALBED.
    BootCommand:       Specifies a command that will be executed on 
                       restart.
    Persistent Data:   Data that survives disable, enable, and restore 
                       operations. Persistent data size is 
                       EWF_MAX_PERSISTENT_DATA (32 bytes by default).
    MaxLevels:         Maximum number of checkpoint levels in the overlay.
    ClumpSize:         Size of the clumps, in bytes. Size must be 
                       512 bytes.
    CurrentLevel:      Current checkpoint level
    DiskMapSize:       Size of the mapping data on disk for the protected 
                       volume, in bytes (only for disk overlays).
    DiskDataSize:      Size of the data stored on disk for the protected 
                       volume, in bytes (only for disk overlays).
    RamDataSize:       Size of the data stored in RAM for the protected 
                       volume, in bytes (only for RAM overlays).
    MemMapSize:        Size of the mapping data in memory for the 
                       protected volume, in bytes.
    VolumeDesc:        Volume device name and volume ID.
    LevelDescArray:    Level description and end time, and level data 
                       size. Number of entries is specified by MaxLevels.
Arguments:
  pVolConfig:
    Pointer to an EWF_VOLUME_CONFIG structure.
Return value:
  None
--*/

VOID  DisplayEwfVolumeConfig ( PEWF_VOLUME_CONFIG pVolConfig )
{
  WORD wIndex = 0;
  WCHAR szVolumeName[EWF_MAX_DEVICE_NAME_LENGTH + 15] = {0};
  WCHAR chDrive = NULL;
  DWORD dwStatus = ERROR_SUCCESS;
  WORD wIdx = 0;
  FILETIME localFileTime;
  SYSTEMTIME systemTime;

  // Display this protected volume's configuration data type.
  wprintf(L"\n\n");
  wprintf(L"--------------------------------------------------------\n");
  wprintf(L"-- Ewf protected volume configuration                   \n");
  wprintf(L"--------------------------------------------------------\n\n");

  switch (pVolConfig->Type)
  {
    case EWF_DISK:      wprintf(L"TYPE      : EWF_DISK\n");    break;
    case EWF_RAM:       wprintf(L"TYPE      : EWF_RAM\n");     break;
    case EWF_RAM_REG:   wprintf(L"TYPE      : EWF_RAM_REG\n"); break;
    default:
      wprintf(L"ERROR: Unknown Ewf type\n"); 
    break;
  }

  // Display this protected volume's state.
  switch (pVolConfig->State)
  {
    case EWF_ENABLED:   wprintf(L"STATE     : EWF_ENABLED\n");  break;
    case EWF_DISABLED:  wprintf(L"STATE     : EWF_DISABLED\n"); break;
    default:
      wprintf(L"ERROR: Unknown Ewf state\n");
    break;
  }

  //Display this protected volume's boot command.
  switch (pVolConfig->BootCommand.Command)
  {
    case EWF_NO_CMD:    wprintf(L"BOOT CMD  : EWF_NO_CMD    ");  break;
    case EWF_ENABLE:    wprintf(L"BOOT CMD  : EWF_ENABLE    ");  break;
    case EWF_DISABLE:   wprintf(L"BOOT CMD  : EWF_DISABLE   ");  break;
    case EWF_COMMIT:    wprintf(L"BOOT CMD  : EWF_COMMIT    ");  break;
    case EWF_SET_LEVEL: wprintf(L"BOOT CMD  : EWF_SET_LEVEL ");  break;
    default:
      wprintf(L"ERROR: Unknown Ewf command ");   
    break;
  }
  
  //Display the EWF command parameters.
  wprintf(
    L" Param1 = %u  Param2 = %u\n\n",
    pVolConfig->BootCommand.Param1,
    pVolConfig->BootCommand.Param2);

  // Display this protected volume's persistent data.
  for (wIndex = 0; wIndex < EWF_MAX_PERSISTENT_DATA; wIndex++)
  {
    wprintf(L"%02X",pVolConfig->PersistentData[wIndex]);
  } 
  wprintf(L"\n\n");

  // Display this protected volume's other attributes.
  wprintf(L"Maximum Levels   : %u\n",       pVolConfig->MaxLevels);
  wprintf(L"Clump Size       : %u Bytes\n", pVolConfig->ClumpSize);
  wprintf(L"Current Level    : %u\n",       pVolConfig->CurrentLevel);

  // Display use statistics based on disk or RAM.
  if (pVolConfig->Type == EWF_DISK)
  { 
    wprintf(L"Disk Map Size    : %u Bytes\n",pVolConfig->DiskOverlay.DiskMapSize);
    wprintf(L"Disk Data Size   : %u Bytes\n",pVolConfig->DiskOverlay.DiskDataSize);
  } 
  else 
  { 
    wprintf(L"Ram Data Size    : %u Bytes\n",pVolConfig->RamOverlay.RamDataSize);
  }

  // Size of mapping data in memory.
  wprintf(L"Memory Map Size  : %u Bytes\n\n",pVolConfig->MemMapSize);

  // Display the volume device name and volume ID
  wprintf(
    L"Device Name      : %.*s\n",
    EWF_MAX_DEVICE_NAME_LENGTH,
    pVolConfig->VolumeDesc.DeviceName);

  wprintf(L"Volume ID        : ");

  for (wIdx = 0; wIdx < EWF_VOLUME_ID_SIZE; wIdx++)
  {
      wprintf(L"%02X", pVolConfig->VolumeDesc.VolumeID[wIdx]);
  }
  wprintf(L"\n");

  // The device name can be used to obtain a volume name
  // to get the associated drive letter.

  // Get the drive letter that represents this protected volume.
  // NOTE: The EwfMgrGetDriveLetterFromVolumeName API must be supplied
  // with a fully qualified Volume Name string.
  // e.g. \\?\storage#volume#1&37a96558&0&signature20c19bc2offset27119f401ngth18e955c00#{68bef3a0-82af-4f8a-b3d3-bd5dde13b413}
  // One way to obtain this Volume Name is to use the 
  //  EwfMgrGetProtectedVolumeList API.

  PEWF_VOLUME_NAME_ENTRY pEwfVolName = NULL;
  pEwfVolName = EwfMgrGetProtectedVolumeList();
  chDrive = EwfMgrGetDriveLetterFromVolumeName( pEwfVolName->Name );

  if (chDrive == -1) 
  {
     dwStatus = GetLastError();
     wprintf(L"EwfMgrGetDriveLetterFromVolumeName failed LE = %u\n",dwStatus);
  }
  else 
  {
     wprintf(L"DEVC Drive:  %c\n\n",chDrive);
  }

  // Display level description information for levels that have ended.
  for (wIdx = 0; wIdx < pVolConfig->CurrentLevel - 1; wIdx++)
  {
    wprintf(
      L"Level Index      : %u\n",
      wIdx + 1);
    
    wprintf(
      L"Level Name       : %.*s\n",
      EWF_MAX_LEVEL_NAME_LENGTH,
      pVolConfig->LevelDescArray[wIdx].LevelName);

    if (FileTimeToLocalFileTime(&pVolConfig->LevelDescArray[wIdx].LevelEndTime, &localFileTime))
    {
      if (FileTimeToSystemTime(&localFileTime, &systemTime))
      {
        wprintf(
          L"Level ended at   : %d:%d:%d on %d/%d/%d\n",
          (int)systemTime.wHour, (int)systemTime.wMinute, (int)systemTime.wSecond,
          (int)systemTime.wMonth, (int)systemTime.wDay, (int)systemTime.wYear);
      }
      else
      {
        wprintf(L"Failed converting FILETIME to SYSTEMTIME\n");
      }
    }
    else 
    {
      wprintf(L"Failed converting FILETIME to local FILETIME\n");
    }
      
    wprintf(
      L"Level Data Size  : %I64d Bytes\n\n",
      pVolConfig->LevelDescArray[wIdx].LevelDataSize);

  } // End of level descriptions.

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

/*++

DumpEwfProtectedVolumes

Routine description:
  This routine uses EwfMgrGetProtectedVolumeList to obtain 
  a list of protected volumes that exist on the system. It then 
  traverses each entry in the EWF_VOLUME_NAME_ENTRY list by using the 
  EwfMgrVolumeNameEntryPop and EwfMgrVolumeNameListIsEmpty functions. 
  For each volume name in the list, a handle is opened to the 
  protected volume by using EwfMgrOpenProtected. This handle 
  is then used to obtain the EWF_VOLUME_CONFIG data by using 
  EwfMgrGetProtectedVolumeConfig. Once the protected volume 
  configuration is obtained, the data is displayed to the console.

Arguments:
  None

Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD  DumpEwfProtectedVolumes()
{
  DWORD dwStatus = ERROR_SUCCESS;
  PEWF_VOLUME_NAME_ENTRY pProVolList = NULL;
  WCHAR chDrive = NULL;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  PEWF_VOLUME_CONFIG pVolConfig = NULL;
  WORD wIndex = 0;

  // Get a list of protected volume names.
  pProVolList = EwfMgrGetProtectedVolumeList();

  if (!pProVolList) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrGetProtectedVolumeList failed LE = %u\n",dwStatus);
    goto exit;
  }

  // Process and free each volume name in the list.
  while (!EwfMgrVolumeNameListIsEmpty(pProVolList))
  {
    // Get the drive letter assigned to this protected volume name.
    chDrive = EwfMgrGetDriveLetterFromVolumeName(pProVolList->Name);

    if (chDrive == -1) 
    {
      dwStatus = GetLastError();
      wprintf(L"EwfMgrGetDriveLetterFromVolumeName failed LE = %u\n",dwStatus);
      goto exit;
    }

    // Display the drive letter and name of this protected volume.
    wprintf(L"%c: = %s\n",chDrive,pProVolList->Name);

    // Use the volume name to open a handle to this protected volume.
    hProVol = EwfMgrOpenProtected(pProVolList->Name);

    if (hProVol == INVALID_HANDLE_VALUE) 
    { 
      dwStatus = GetLastError();
      wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
      goto exit;
    }

    // Get the protected volume configuration using the handle.
    pVolConfig = EwfMgrGetProtectedVolumeConfig(hProVol);

    if (!pVolConfig)
    {
      dwStatus = GetLastError();
      wprintf(L"EwfMgrGetProtectedVolumeConfig failed LE = %u\n",dwStatus);
      goto exit;
    }

    // Output the EWF_VOLUME_CONFIG structure.
    DisplayEwfVolumeConfig(pVolConfig);

    // Free the volume configuration data.
    LocalFree(pVolConfig);
    pVolConfig = NULL;

    // Close the handle to this protected volume.
    if (!EwfMgrClose(hProVol))
    {
      dwStatus = GetLastError();
      wprintf(L"EwfMgrClose failed LE = %u\n",dwStatus);
      goto exit;
    }
    
    // Reset the handle.
    hProVol = INVALID_HANDLE_VALUE;

    // Pop and free the head node of the protected volume list.
    EwfMgrVolumeNameEntryPop(&pProVolList);
  }

exit:
  if (pProVolList) 
  {
    EwfMgrVolumeNameListDelete(pProVolList);
    pProVolList = NULL;
  }

  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }

  if (pVolConfig)
  {
    LocalFree(pVolConfig);
  }

  return dwStatus;
}

/*++

DisplayEwfOverlayConfig

Routine description:
  This routine displays an EWF overlay configuration, which is defined by 
  the EWF_OVERLAY_STORE_CONFIG structure (ewfapi.h)and includes the 
  following members:
    FormatVersion:     Version of the overlay store volume format.
    VolumeSize:        Size of the overlay store volume , in bytes.
    NumSegments:       Number of segments that the overlay store volume is 
                       divided into.
    FreeSegments:      Number of free segments.
    SegmentSize:       Size of each segment, in bytes.
    MaxVolumes:        Maximum number of protected volumes.
    NumVolumes         Number of currently protected volumes.
    MaxLevels:         Maximum number of overlay levels.
    VolumeDescArray    Array of volume descriptions. Number of entries is 
                       specified by NumVolumes.
Arguments:
  pOvlConfig:
    Pointer to an PEWF_OVERLAY_STORE_CONFIG structure.
Return value:
  None
--*/

VOID  DisplayEwfOverlayConfig ( PEWF_OVERLAY_STORE_CONFIG pOvlConfig )
{
  PEWF_VOLUME_DESC pVolDesc = NULL;
  WORD ii = 0, jj = 0;
  WCHAR chDrive = NULL;
  DWORD dwStatus = 0;
  WCHAR szVolumeName[EWF_MAX_DEVICE_NAME_LENGTH + 15] = {0};

  wprintf(L"\n\n");
  wprintf(L"--------------------------------------------------------\n");
  wprintf(L"-- Ewf overlay store configuration :                    \n");
  wprintf(L"--------------------------------------------------------\n\n");
 
  // Display the EWF overlay store configuration.
  wprintf(L"Format Version       : %u\n",       pOvlConfig->FormatVersion);
  wprintf(L"Volume Size          : %I64d Mb\n", pOvlConfig->VolumeSize / 1000000L);
  wprintf(L"Number of Segments   : %u\n",       pOvlConfig->NumSegments);
  wprintf(L"Free Segments        : %u\n",       pOvlConfig->FreeSegments);
  wprintf(L"Segment Size         : %u Bytes\n", pOvlConfig->SegmentSize);
  wprintf(L"Max Volumes          : %u\n",       pOvlConfig->MaxVolumes);
  wprintf(L"Number of Volumes    : %u\n",       pOvlConfig->NumVolumes);
  wprintf(L"Max Levels           : %u\n\n",     pOvlConfig->MaxLevels);
 
  // Display information about each protected volume.
  for (ii = 0; ii < pOvlConfig->NumVolumes; ii++)
  {
    pVolDesc = &pOvlConfig->VolumeDescArray[ii];

    // Convert the protected volume's device name into a volume name.
   PEWF_VOLUME_NAME_ENTRY pEwfVolName = NULL;
   pEwfVolName = EwfMgrGetProtectedVolumeList();

   // Get the drive letter that represents this protected volume.
   chDrive = EwfMgrGetDriveLetterFromVolumeName(pEwfVolName->Name);

    if (chDrive == -1) 
    {
      dwStatus = GetLastError();
      wprintf(L"EwfMgrGetDriveLetterFromVolumeName failed LE = %u\n",dwStatus);
    }

    if ( pEwfVolName )
    {
       EwfMgrVolumeNameListDelete( pEwfVolName );
       pEwfVolName = NULL;
    }

    wprintf(L"Protected Volume [%u] : ID = ",ii);

    for (jj = 0; jj < EWF_VOLUME_ID_SIZE; jj++)
    {
      wprintf(L"%02X", pVolDesc->VolumeID[jj]);
    }

    wprintf(L"Name = %.*s  Drive = %c\n",
      EWF_MAX_DEVICE_NAME_LENGTH, pVolDesc->DeviceName, chDrive);

  } // End for each protected volume.

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

/*++

DumpEwfOverlayConfig

Routine description:
  This routine uses EwfMgrOpenOverlayStore to open a 
  handle to the overlay partition. It then uses this handle 
  to obtain a pointer to the EWF_OVERLAY_STORE_CONFIG structure
  using EwfMgrGetOverlayStoreConfig. After the overlay 
  configuration data is obtained, it is displayed to the console.

Arguments:
  None.

Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DumpEwfOverlayConfig() 
{
  BOOL bResult = FALSE;
  DWORD dwStatus = ERROR_SUCCESS;
  WORD wIndex = 0;
  HANDLE hOverlay = INVALID_HANDLE_VALUE;
  PEWF_OVERLAY_STORE_CONFIG pOvlConfig = NULL;

  // Create a handle to the EWF overlay store.
  hOverlay = EwfMgrOpenOverlayStore ( FALSE ); 

  if (hOverlay == INVALID_HANDLE_VALUE) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenOverlayStore failed LE = %u\n",dwStatus);
    goto exit;
  }

  // Get a pointer to the EWF overlay configuration.
  pOvlConfig = EwfMgrGetOverlayStoreConfig(hOverlay);

  if (!pOvlConfig) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrGetOverlayStoreConfig failed LE = %u\n",dwStatus);
    goto exit;
  }

  // Output the EWF_OVERLAY_STORE_CONFIG structure to the console.
  DisplayEwfOverlayConfig(pOvlConfig);

exit:
  if (pOvlConfig)
  {
    LocalFree(pOvlConfig);
  }
 
  if (hOverlay != INVALID_HANDLE_VALUE) 
  {
    EwfMgrClose(hOverlay);
  }

  return dwStatus;
}


/*++

DoEwfClearCommand

Routine description:
  This routine demonstrates the use of EwfMgrClearCommand. 
  First, a handle is opened to a protected volume, then the 
  EwfMgrClearCommand function is called.

  EwfMgrClearCommand:
    Command: Clears any pending commands 
             from the desired protected volume.
    Reboot:  Not required.
    Supported on EWF configurations of type EWF_DISK and 
    EWF_RAM.

Arguments:
  szProVolName

    Volume name obtained from EwfMgrGetProtectedVolumeList or 
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    the form \\.\C: where C represents the drive letter of the 
   protected volume.

Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfClearCommand ( LPWSTR szProVolName ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;

  // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }
 
  // Clear any EWF boot commands.
  if (!EwfMgrClearCommand(hProVol))
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrClearCommand failed LE = %u\n",dwStatus);
    goto exit;
  }
  wprintf(L"EwfMgrClearCommand succeeded\n");

exit:
  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }

  return dwStatus;
}


/*++

DoEwfPersistCommands

Routine description:
  This routine demonstrates the use of EwfMgrSetPersistentData 
  and EwfMgrGetPersistentData. First, a handle is opened to a 
  protected volume, and then commands are issued to the protected volume.

  EwfMgrSetPersistentData, EwfMgrGetPersistentData :
    Commands: Set and get persistent data to and
             from the desired EWF-protected volume.
    Reboot:  Not required.
    Supported on EWF configurations of type EWF_DISK and 
    EWF_RAM.

Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or 
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.

Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfPersistCommands ( LPWSTR szProVolName ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;
  WORD wIdx = 0;

  // Used to demonstrate EWF set and get persistent data commands.
  BYTE buffer[EWF_MAX_PERSISTENT_DATA] = {
    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
    0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
    0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
    0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20};

  DWORD cbCount = EWF_MAX_PERSISTENT_DATA;  // 32 bytes

 // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }
 
  bResult = EwfMgrSetPersistentData(
    hProVol,
    (LPBYTE)buffer,
    cbCount);

  if (!bResult)
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrSetPersistentData failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrSetPersistentData succeeded\n");

  ZeroMemory(buffer,cbCount);

  bResult = EwfMgrGetPersistentData(
    hProVol, 
    buffer,
    cbCount);

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrGetPersistentData failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrGetPersistentData succeeded\n");

  // Display the persistent data of the protected volume.
  for (wIdx = 0; wIdx < EWF_MAX_PERSISTENT_DATA; wIdx++)
  {
     wprintf(L"%02X",buffer[wIdx]);
  } 

  wprintf(L"\n");

exit:
  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }
  return dwStatus;
}

/*++

DoEwfCheckPoint

Routine description:
  This routine demonstrates the use of EwfMgrCheckpoint. 
  First, a handle is opened to a protected volume, and then the 
  command is issued to the protected volume.

  EwfMgrCheckpoint:
    Command: Adds a checkpoint overlay level on the specified 
             EWF-protected volume.
    Reboot:  Required.

    Supported on Ewf Configurations of type EWF_DISK.

Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or  
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.
  bReboot
    If TRUE, a reboot is issued after the command is sent to the EWF 
driver.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfCheckPoint ( LPWSTR szProVolName, BOOL bReboot ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;

  // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrCheckpoint(hProVol,L"Optional description");

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrCheckpoint failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrCheckpoint succeeded\n\n");

  // This command requires a reboot to take effect.
  if (bReboot) DoReboot();
  
exit:

  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }
  return dwStatus;
}


/*++

DoEwfRestore

Routine description:
  This routine demonstrates the use of the EwfMgrRestore API. First, a 
  handle is opened to a protected, and then the command is issued.
  DoEwfRestore:
    Command: Decreases the overlay level by one.
    Reboot:  Required.
    Supported on Ewf Configurations of type EWF_DISK.
  
Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or  
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.

  bReboot
    If TRUE, a reboot is issued after the command is sent to the EWF 
    driver.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfRestore ( LPWSTR szProVolName, BOOL bReboot ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;

 // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrRestore(hProVol);

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrRestore failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrRestore succeeded\n");

  // This command requires a reboot to take effect.
  if (bReboot) DoReboot();

exit:

  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }
  return dwStatus;
}

/*++

DoEwfEnable

Routine description:
  This routine demonstrates the use of EwfMgrEnable. 
  First, a handle is opened to a protected volume, and then the 
  command is issued.

  EwfMgrEnable:
    Command: Enables a currently disabled overlay on the specified volume
             by creating a new overlay at level 1 and setting the current 
             level to 1.

    Reboot:  Required.
    Supported on the EWF configuration types EWF_DISK, EWF_RAM, and 
    EWF_RAM_REG.
  
Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or 
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.

  bReboot
    If TRUE, a reboot is issued after the command is sent to the EWF 
    driver.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfEnable ( LPWSTR szProVolName, BOOL bReboot ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;

  // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrEnable(hProVol);

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrEnable failed LE = %u\n",dwStatus);
    goto exit;
  }
  wprintf(L"EwfMgrEnable succeeded\n");

  // This command requires a reboot to take effect.
  if (bReboot) DoReboot();

exit:
  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }
  return dwStatus;
}




/*++

DoEwfDisable

Routine description:
  This routine demonstrates the use of EwfMgrDisable. First, a handle 
  is opened to a protected volume, and then the command is issued. 
  EwfMgrDisable:
    Command: Disables a currently enabled overlay on the 
             specified volume.
    Reboot:  Required.

    Supported on the EWF configuration types EWF_DISK, EWF_RAM, and 
    EWF_RAM_REG (special).
  
Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.

  bReboot
    If TRUE, a reboot is issued after the command is sent to the EWF 
    driver.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfDisable ( LPWSTR szProVolName, BOOL bReboot ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;

  // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }

  // For EWF_RAM_REG configurations, the second parameter (commit)
  // must be TRUE. This will commit the EWF_RAM_REG disable state,
  // which is required to disable the EWF_RAM_REG configuration.

  bResult = EwfMgrDisable(hProVol,FALSE);

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrDisable failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrDisable succeeded\n");

  // This command requires a reboot to take effect.
  if (bReboot) DoReboot();

exit:
  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }

  return dwStatus;
}



/*++

DoEwfCommit

Routine description:
  This routine demonstrates the use of EwfMgrCommit. First, a handle 
  is opened to a protected volume, and then the command is issued. 

  EwfMgrCommit:
    Command: Commits all current level data in the overlay 
             to the protected volume, creating a new overlay at level 1 
             and setting the current level to 1.
    Reboot:  Required.

    Supported on the EWF configuration types EWF_DISK, EWF_RAM, and 
    EWF_RAM_REG.
  
Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or 
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.

  bReboot
    If TRUE, a reboot is issued after the command is sent to the EWF 
    driver.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfCommit ( LPWSTR szProVolName, BOOL bReboot ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;

  // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrCommit(hProVol);

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrCommit failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrCommit succeeded\n");

  // This command requires a reboot to take effect.
  if (bReboot) DoReboot();

exit:
  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }

  return dwStatus;
}



/*++

DoEwfSetLevel

Routine description:
  This routine demonstrates the use of EwfMgrSetLevel. First, a handle 
  is opened to a protected volume, and then the command is issued. 

  EwfMgrSetLevel:
    Command: Sets the overlay level on an EWF-protected 
             volume for disk overlays, decreasing the overlay level by a
             specified amount.

    Reboot:  Required.
    Supported on the EWF configuration type EWF_DISK.
  
Arguments:
  szProVolName
    Volume name obtained from EwfMgrGetProtectedVolumeList or 
    device name obtained from EwfMgrGetOverlayStoreConfig prepended with 
    \\.\C: where C represents the drive letter of the protected volume.

  bReboot
    If TRUE, a reboot is issued after the command is sent to the EWF 
    driver.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfSetLevel ( LPWSTR szProVolName, BOOL bReboot ) 
{
  DWORD dwStatus = ERROR_SUCCESS;
  HANDLE hProVol = INVALID_HANDLE_VALUE;
  BOOL bResult = FALSE;

  // Use the volume name to open a handle to this protected volume.
  hProVol = EwfMgrOpenProtected(szProVolName);

  if (hProVol == INVALID_HANDLE_VALUE) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrSetLevel(
    hProVol,
    L"Optional Description",
    0,        // Level zero to be restored back to the protected volume.
    FALSE);   // Cannot delete the protected volumes data.

  if (!bResult) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrSetLevel failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(L"EwfMgrSetLevel succeeded\n");

  // This command requires a reboot to take effect.
  if (bReboot) DoReboot();

exit:
  if (hProVol != INVALID_HANDLE_VALUE)
  {
    EwfMgrClose(hProVol);
  }

  return dwStatus;
}


/*++

DoEwfRegisterLowSpaceSync

Routine description:
  This routine demonstrates the synchronous use of 
  EwfMgrRegisterLowSpaceNotification. First, a handle is opened to 
  the overlay volume. When the overlay volume has only FreeBytes 
  remaining, the function returns.

  EwfMgrRegisterLowSpaceNotification:
    Command: Registers for a low space notification when the available 
             bytes in the overlay reach a specified threshold.

    Supported on EWF configuration type EWF_DISK.
  
Arguments:
  FreeBytes
    When this many free bytes remain on the overlay partition,
    the function returns.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfRegisterLowSpaceSync ( LONGLONG FreeBytes ) 
{
  HANDLE hOverlay = INVALID_HANDLE_VALUE;
  DWORD dwStatus = ERROR_SUCCESS;
  BOOL bResult = FALSE;

  // Create an synchronous handle to the EWF overlay store.
  hOverlay = EwfMgrOpenOverlayStore ( FALSE ); 

  if (hOverlay == INVALID_HANDLE_VALUE) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenOverlayStore failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrRegisterLowSpaceNotification(
    hOverlay,
    FreeBytes,
    NULL);

  if (!bResult) 
  { 
    dwStatus = GetLastError();
    wprintf(L"EwfMgrRegisterLowSpaceNotification failed LE = %u\n",dwStatus);
    goto exit;
  }

  wprintf(
    L"Warning: Low Ewf overlay notification: %I64d bytes remaining\n",
    FreeBytes);

exit:
  if (hOverlay != INVALID_HANDLE_VALUE) 
  {
    EwfMgrClose(hOverlay);
  }
  return dwStatus;
}

/*++

DoEwfRegisterLowSpaceAsync

Routine description:
  This routine demonstrates the asynchronous usage of 
  EwfMgrRegisterLowSpaceNotification. First, a handle is opened 
  to the overlay volume. When the overlay volume has only 
  FreeBytes remaining, an event is signaled.

  EwfMgrRegisterLowSpaceNotification:
    Command: Registers for a low space notification when the available 
             bytes in the overlay reach a specified threshold.
    Supported on EWF configuration type EWF_DISK.
  
Arguments:
  FreeBytes
    When this many free bytes remain on the overlay partition, an 
    event is signaled.
    
Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfRegisterLowSpaceAsync ( LONGLONG FreeBytes ) 
{
  HANDLE hOverlay = INVALID_HANDLE_VALUE;
  DWORD dwStatus = ERROR_SUCCESS;
  OVERLAPPED Overlapped;
  BOOL bResult = FALSE;

  // Create an overlapped handle to the EWF overlay store.
  hOverlay = EwfMgrOpenOverlayStore ( TRUE ); 

  if (hOverlay == INVALID_HANDLE_VALUE) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrOpenOverlayStore failed LE = %u\n",dwStatus);
    goto exit;
  }

  ZeroMemory(&Overlapped,sizeof(Overlapped));

  Overlapped.hEvent = CreateEvent(
    NULL,     // Default security.
    FALSE,    // Auto-reset.
    FALSE,    // Non-signaled state.
    NULL);

  if (Overlapped.hEvent == NULL) 
  {
    dwStatus = GetLastError();
    wprintf(L"CreateEvent failed LE = %u\n",dwStatus);
    goto exit;
  }

  bResult = EwfMgrRegisterLowSpaceNotification(
    hOverlay,
    FreeBytes,
    &Overlapped);

  if (!bResult) 
  { 
    dwStatus = GetLastError();

    // If the I/O is pending, then wait for the event.
    if (dwStatus == ERROR_IO_PENDING) { 
      dwStatus = ERROR_SUCCESS;
      goto wait;
    }

    // An error occurred.
    wprintf(L"EwfMgrRegisterLowSpaceNotification failed LE = %u\n",dwStatus);
    goto exit;
  }

  // Synchronous, free byte requirement was met.
  goto done;

  // Wait for event to be signaled when free byte requirement is met.

wait:
  dwStatus = WaitForSingleObject(Overlapped.hEvent,INFINITE);

  if (dwStatus == WAIT_FAILED)
  { 
    dwStatus = GetLastError();
    wprintf(L"WaitForSingleObject failed LE = %u\n",dwStatus);
  } 

  dwStatus = ERROR_SUCCESS;

  // Done event was signaled, output low overlay notification.
done:
  wprintf(
    L"Warning: Low Ewf overlay notification: %I64d bytes remaining\n",
    FreeBytes);

exit:
  if (hOverlay != INVALID_HANDLE_VALUE) 
  {
    EwfMgrClose(hOverlay);
  }

  if (Overlapped.hEvent)
  {
    CloseHandle(Overlapped.hEvent);
  }

  return dwStatus;
}




/*++

DoEwfCommands

Routine description:
  This routine demonstrates the use of building a list of EWF 
  protected volume names that exist on the system. After the 
  list is obtained, the routine demonstrates how to send 
  commands to each of the protected volumes by using the command 
  samples.

Arguments:
  None.

Return value:
  ERROR_SUCCESS if success; otherwise, a Win32 error code.
--*/

DWORD DoEwfCommands () 
{
  DWORD dwStatus = ERROR_SUCCESS;
  PEWF_VOLUME_NAME_ENTRY pProVolList = NULL;
  
  // Get a list of protected volume names.
  pProVolList = EwfMgrGetProtectedVolumeList();

  if (!pProVolList) 
  {
    dwStatus = GetLastError();
    wprintf(L"EwfMgrGetProtectedVolumeList failed LE = %u\n",dwStatus);
    goto exit;
  }

  // Process and free each volume name in the list and 
  // use the volume name to demonstrate command use.

  while (!EwfMgrVolumeNameListIsEmpty(pProVolList))
  {
    DoEwfPersistCommands (pProVolList->Name);
    DoEwfCheckPoint      (pProVolList->Name, FALSE); //Do not reboot.
    DoEwfRestore         (pProVolList->Name, FALSE); //Do not reboot.
    DoEwfEnable          (pProVolList->Name, FALSE); //Do not reboot.
    DoEwfDisable         (pProVolList->Name, FALSE); //Do not reboot.
    DoEwfCommit          (pProVolList->Name, FALSE); //Do not reboot.
    DoEwfSetLevel        (pProVolList->Name, FALSE); //Do not reboot.
    DoEwfClearCommand    (pProVolList->Name);

    EwfMgrVolumeNameEntryPop(&pProVolList);
  }

  // Demonstrate the usage of the EWF register low space
  // notification functions.
  DoEwfRegisterLowSpaceAsync ( 9000000L ); // 9Mb free

  DoEwfRegisterLowSpaceSync  ( 6000000L ); // 6Mb free

  if ( pProVolList )
  {
    EwfMgrVolumeNameListDelete( pProVolList );
    pProVolList = NULL;
  }

exit:
  return dwStatus;
}


/*++
Description:
  This program demonstrates the following use of the EWF API:
    1) Obtaining and displaying the EWF overlay configuration.
    2) Obtaining and displaying the EWF-protected volume configurations.
    3) Issuing EWF commands to protected volumes.

Arguments:
  None.

Return value:
  None.
--*/


int _tmain(int argc, _TCHAR* argv[])
{
  wprintf(L"Ewf API Sample\n\n");

  // Obtain and display the EWF overlay configuration.
  DumpEwfOverlayConfig();

  // Obtain and display the EWF-protected volume configurations.
  DumpEwfProtectedVolumes();

  // Issue EWF commands to the protected volumes.
  DoEwfCommands();

  return 0;
}

See Also

Concepts

Enhanced Write Filter API
EWF API Functions