This is a code sample to help incorporate a Hide/Unhide function into your solution. This option helps you hide a partition from OS, applications, and users, thus preventing access to its contents and vice versa.
Due to internal restrictions, hdmengine cannot work on multiple processes at the same time, so it locks the volume during the process to restrict access from another process. For example, if an additional process is initialized (for example, resize a partition) when the hdmengine is busy with a different process (for example, creating a partition), the engine will not be able to lock the additional process (resize a partition) and will execute it in the Bluescreen mode.
Before you read the code sample:
- Include the header files.
- Add hdmclient_hdmclientlib.dll library to your project.
- Set up callbacks from hdmclientlib.
For more details on the initial setup, please see the Setting Up the C++ Development Environment section.
Add the header files to copy blocks of memory and pull in the rest of the headers from the clientapp engine, including the callback prototypes.
#include <string.h> // memcpy
#include "../hdmclientapp_progress.h"
Set callbacks. You need to implement the abstract interface struct Hdmclient_IProgress.
_Hdmclient_Init proc_Hdmclient_Init = NULL;
_Hdmclient_Close proc_Hdmclient_Close = NULL;
_Hdmclient_GetInterface proc_Hdmclient_GetInterface = NULL;
_Hdmclient_GetLog proc_Hdmclient_GetLog = NULL;
_Hdmclient_InstallBluescreen proc_Hdmclient_InstallBluescreen = NULL;
_Hdmclient_GetErrorDescription proc_Hdmclient_GetErrorDescription = NULL;
Add a helper function to log output messages. How to set LogPrint please see hdmclientapp_main.cpp or look at a code sample here.
static void LogPrint(Hdmclient_ILog * /* pLog */, bool /* rewrite */, const char * /* format */, IN ...)
{
// How to set LogPrint please see hdmclientapp_main.cpp
}
Select the disk number (absolute), partition number (absolute), you need to change.
HDMCLIENT_ERR Hdmclient_Example_PartitionHideUnhide(unsigned diskNumber,
unsigned partNumber)
Set the variables for the error code, whether a reboot is necessary, and an interface to log the actions as well as the interface to implement callbacks.
{
HDMCLIENT_ERR err = SERR_SUCCESS;
BOOL bReboot = FALSE;
Hdmclient_ILog *pLog = NULL;
Hdmclient_Progress hdmclientProgress;
Set the hdmengine initialization flags and enable run multiple instances of Hdmengine application.
if(!err)
{
unsigned int initFlags = Hdmclient_InitFlags::Hdmclient_InitFlag_EnableRunMultiple;
Initialize Hdmengine API: pass engine flags, pass the progress interface to Hdmengine API, pass the application log path.
err = proc_Hdmclient_Init((Hdmclient_InitFlags)initFlags,
&hdmclientProgress,
"hdmclient_hdmclientapp.log",
NULL, NULL, NULL);
Get the logging interface.
if(!err)
proc_Hdmclient_GetLog(&pLog);
}
Get the partitioning interface.
if(!err)
{
Hdmclient_IInterface* pInterface = NULL;
if(!err)
err = proc_Hdmclient_GetInterface(&pInterface);
Search for the selected partition by disk and partition number (all numbers zero based, extended and free partitions are also counted). Hdmclient_IInterface::DiskInfo diskInfo = {}; – Displays selected disk info and Hdmclient_IInterface::PartitionInfo partInfo displayed selected partition info.
Hdmclient_IInterface::DiskInfo diskInfo = {};
Hdmclient_IInterface::PartitionInfo partInfo = {};
if(!err)
{
Hdmclient_IInterface::EnumDisksInfo* enumDisksInfo = NULL;
Get the disks enumerator and release the disks enumerator.
err = pInterface->GetDisksInfo(&enumDisksInfo);
if(!err)
{
if(enumDisksInfo && (enumDisksInfo->disksCount > 0))
{
if(!err)
{
if(diskNumber == (unsigned)-1)
{
err = SERR_DISK_NOT_FOUND;
LogPrint(pLog, false, "Disk is not selected .. Failed\n");
}else
if((diskNumber + 1) > enumDisksInfo->disksCount)
{
err = SERR_DISK_NOT_FOUND;
LogPrint(pLog, false, "Disk number is out of range (maximum number is %lu) .. Failed\n", enumDisksInfo->disksCount - 1);
}else
{
auto pDiskInfo = enumDisksInfo->ppDisksInfo[diskNumber];
memcpy(&diskInfo, pDiskInfo, sizeof(diskInfo));
if(partNumber != (unsigned)-1)
{
if((partNumber + 1) <= pDiskInfo->enumPartitionsInfo.partitionsCount)
{
auto pPartitionInfo = pDiskInfo->enumPartitionsInfo.ppPartitionsInfo[partNumber];
memcpy(&partInfo, pPartitionInfo, sizeof(partInfo));
}else
{
err = SERR_PART_NOT_FOUND;
LogPrint(pLog, false, "Partition number is out of range (maximum number is %lu) .. Failed\n", pDiskInfo->enumPartitionsInfo.partitionsCount - 1);
}
}
}
}
}
pInterface->ReleaseDisksInfo(enumDisksInfo);
}
}
Perform the virtual step.
if(!err)
{
bool bHide = !(partInfo.Flags & Hdmclient_IInterface::PartitionFlags::PartitionFlag_Hidden) ? true : false;
Check that the required action is available for selected object.
if(!(partInfo.ActFlags & Hdmclient_IInterface::PartitionActFlags::PartitionActFlag_Can_Hide))
{
err = SERR_INCOMPATIBLEOP;
LogPrint(pLog, false, "%s is not enabled for selected partition ... Failed\n", bHide ? "Hide" : "Unhide");
}else
Perform the Hide/Unhide (virtual step).
{
err = pInterface->Partition_SetFlags(partInfo.DiskNumber,
partInfo.PartitionNumber,
Hdmclient_IInterface::SetFlag_Type::SetFlag_Unchanged,
bHide ? Hdmclient_IInterface::SetFlag_Type::SetFlag_Set : Hdmclient_IInterface::SetFlag_Type::SetFlag_UnSet);
LogPrint(pLog, false, "%s selected partition ... %s\n", bHide ? "Hiding" : "Unhiding",
err ? "Failed" : "Success");
}
}
Perform the Hide/Unhide (physical step): Apply the queue or above operations.
if(!err)
{
if(!err)
{
LogPrint(pLog, false, "Applying operations ...\n");
err = pInterface->Apply();
if(!err)
{
LogPrint(pLog, false, "Applying queue of operations ... Success\n");
}else
{
LogPrint(pLog, false, "Applying queue of operations ... Failed (Result: 0x%x, \"%s\")\n", err, proc_Hdmclient_GetErrorDescription(err));
To add the reload feature in the Bluescreen mode if a reload is needed, use the special error code that signals that the reboot is necessary to continue operation.
if(err == SERR_NEEDRESTART)
{
if(SERR_SUCCESS == proc_Hdmclient_InstallBluescreen())
bReboot = TRUE;
}
}
}
}
}
Close the HDM client API.
proc_Hdmclient_Close(bReboot, FALSE);
return err;
}