EWF API Code Sample (Standard 7 SP1)
7/8/2014
Sample.cpp provides an example that uses the Enhanced Write Filter (EWF) API to perform the following actions:
- Obtain and display the EWF overlay configuration
- Obtain and display the EWF-protected volume configurations
- Issue EWF commands to protected volumes
The following table shows the functions that are used in Sample.cpp.
Function |
Description |
---|---|
DoReboot |
Restarts the system for EWF functions that require a system restart. |
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 the 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 using the EwfMgrClearCommand function. |
DoEwfPersistCommands |
Demonstrates using the EwfMgrSetPersistentData and EwfMgrGetPersistentData functions. |
DoEwfCheckPoint |
Demonstrates using the EwfMgrCheckpoint function. |
DoEwfRestore |
Demonstrates using the EwfMgrRestore function. |
DoEwfEnable |
Demonstrates using the EwfMgrEnable function. |
DoEwfDisable |
Demonstrates using the EwfMgrDisable function. |
DoEwfCommit |
Demonstrates using the EwfMgrCommit function. |
DoEwfCommitFile |
Demonstrates using the EwfMgrCommitFile function. |
DoEwfSetLevel |
Demonstrates using the EwfMgrSetLevel function. |
DoEwfRegisterLowSpaceSync |
Demonstrates the synchronous use of the EwfMgrRegisterLowSpaceNotification function. |
DoEwfRegisterLowSpaceAsync |
Demonstrates the asynchronous use of the EwfMgrRegisterLowSpaceNotification function. |
DoEwfCommands |
Demonstrates building a list of EWF-protected volume names and sending commands to each 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"
/*++
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 restarts 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;
}
/*++
DoEwfCommitFile
Routine description:
This routine demonstrates the use of EwfMgrCommitFile. First, a handle
is opened to a protected volume, and then the command is issued.
EwfMgrCommitFile:
Command: Commits all current level data in the overlay for a specific file to the protected volume.
Reboot: Required.
Is supported on EWF configuration types "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 DoEwfCommitFile ( LPCWSTR szVolumeName, BOOL bReboot )
{
DWORD dwStatus = ERROR_SUCCESS;
HANDLE hProVol = INVALID_HANDLE_VALUE;
BOOL bResult = FALSE;
DWORD dwAttributes = 0;
// Say if you want to commit changes to the file "C:\\persist.dat"
// Get the file attributes
dwAttributes = GetFileAttributesW(L"C:\\persist.dat");
if (INVALID_FILE_ATTRIBUTES == dwAttributes)
{
dwStatus = GetLastError();
goto exit;
}
// Check if the file is a compressed/sparse file
if ((FILE_ATTRIBUTE_COMPRESSED & dwAttributes) ||
(FILE_ATTRIBUTE_SPARSE_FILE & dwAttributes))
{
dwStatus = ERROR_NOT_SUPPORTED;
goto exit;
}
// Use the volume name to open a handle to this protected volume.
hProVol = EwfMgrOpenProtected(szVolumeName);
if (hProVol == INVALID_HANDLE_VALUE)
{
dwStatus = GetLastError();
wprintf(L"EwfMgrOpenProtected failed LE = %u\n",dwStatus);
goto exit;
}
bResult = EwfMgrCommitFile(hProVol, L"\\persist.dat");
if (!bResult)
{
dwStatus = GetLastError();
wprintf(L"EwfMgrCommitFile failed LE = %u\n",dwStatus);
goto exit;
}
wprintf(L"EwfMgrCommitFile 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.
DoEwfCommitFile (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 ); // 9 Mb free
DoEwfRegisterLowSpaceSync ( 6000000L ); // 6 Mb 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;
}