Skip to content

Instantly share code, notes, and snippets.

@vmwarecode
Created July 13, 2016 14:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vmwarecode/1979011bdb3081dc425d2814b2a1527f to your computer and use it in GitHub Desktop.
Save vmwarecode/1979011bdb3081dc425d2814b2a1527f to your computer and use it in GitHub Desktop.
Sample to demonstrate Mounting of target VMs vmdk on physical or virtual proxy using VDDK SDK.
/*
* vixMntApiSample.cpp --
*
* Sample program to demonstrate mounting of vmdk on proxy using
* vixDiskLib and vixMntApi DLL.
*/
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#include <process.h>
#else
#include <dlfcn.h>
#include <sys/time.h>
#endif
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string.h>
#include <vector>
#include <stdexcept>
#include <memory>
#include <assert.h>
#include "vixDiskLib.h"
#include "vixMntApi.h"
using std::cout;
using std::cin;
using std::string;
using std::endl;
using std::vector;
#define COMMAND_INFO (1 << 0)
#define COMMAND_DUMP_META (1 << 1)
#define COMMAND_READ_META (1 << 2)
#define COMMAND_WRITE_META (1 << 3)
#define COMMAND_MOUNT (1 << 4)
#define VIXDISKLIB_VERSION_MAJOR 5
#define VIXDISKLIB_VERSION_MINOR 5
#define ERROR_MNTAPI_VOLUME_ALREADY_MOUNTED 24305
static struct {
int command;
char *transportModes;
char *diskPath;
char *mntDiskPaths[20];
char *metaKey;
char *metaVal;
uint32 openFlags;
Bool isRemote;
char *host;
char *userName;
char *password;
char *thumbPrint;
int port;
int nfcHostPort;
char *srcPath;
VixDiskLibConnection connection;
char *vmxSpec;
bool useInitEx;
char *cfgFile;
char *libdir;
char *ssMoRef;
} appGlobals;
static int ParseArguments(int argc, char* argv[]);
static void DoReadMetadata(void);
static void DoWriteMetadata(void);
static void DoDumpMetadata(void);
static void DoInfo(void);
static void DoMount(const vector<string> &disks);
static int BitCount(int number);
#define THROW_ERROR(vixError) \
throw VixDiskLibErrWrapper((vixError), __FILE__, __LINE__)
#define CHECK_AND_THROW(vixError) \
do { \
if (VIX_FAILED((vixError))) { \
throw VixDiskLibErrWrapper((vixError), __FILE__, __LINE__); \
} \
} while (0)
/*
*--------------------------------------------------------------------------
*
* LogFunc --
*
* Callback for VixDiskLib Log messages.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
LogFunc(const char *fmt, va_list args)
{
printf("Log: ");
vprintf(fmt, args);
}
/*
*--------------------------------------------------------------------------
*
* WarnFunc --
*
* Callback for VixDiskLib Warning messages.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
WarnFunc(const char *fmt, va_list args)
{
printf("Warning: ");
vprintf(fmt, args);
}
/*
*--------------------------------------------------------------------------
*
* PanicFunc --
*
* Callback for VixDiskLib Panic messages.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
PanicFunc(const char *fmt, va_list args)
{
printf("Panic: ");
vprintf(fmt, args);
exit(10);
}
#define CHECK(vixError__, label__) \
do {\
char *errorText = NULL; \
if (VIX_FAILED(vixError__)) { \
printf("Failed at %s:%d, errorcode : %s (%"FMT64"d)\n", \
__FILE__, __LINE__, VixDiskLib_GetErrorText(vixError__, NULL), vixError__);\
VixDiskLib_FreeErrorText(errorText); \
goto label__; \
} \
} while (0)
typedef struct {
VixVolumeHandle volumeHandle;
VixVolumeInfo* volInfo;
} MountedVolume;
vector<MountedVolume> mountedVolumes;
vector<VixDiskSetHandle> mountedDisks;
typedef void (VixDiskLibGenericLogFunc)(const char *fmt, va_list args);
// Wrapper class for VixDiskLib disk objects.
class VixDiskLibErrWrapper
{
public:
explicit VixDiskLibErrWrapper(VixError errCode, const char* file, int line)
:
_errCode(errCode),
_file(file),
_line(line)
{
char* msg = VixDiskLib_GetErrorText(errCode, NULL);
_desc = msg;
VixDiskLib_FreeErrorText(msg);
}
VixDiskLibErrWrapper(const char* description, const char* file, int line)
:
_errCode(VIX_E_FAIL),
_desc(description),
_file(file),
_line(line)
{
}
string Description() const { return _desc; }
VixError ErrorCode() const { return _errCode; }
string File() const { return _file; }
int Line() const { return _line; }
private:
VixError _errCode;
string _desc;
string _file;
int _line;
};
class VixDisk
{
public:
VixDiskLibHandle Handle() { return _handle; }
VixDisk(VixDiskLibConnection connection, char *path, uint32 flags)
{
_handle = NULL;
VixError vixError = VixDiskLib_Open(connection, path, flags, &_handle);
CHECK_AND_THROW(vixError);
printf("Disk \"%s\" is open using transport mode \"%s\".\n",
path, VixDiskLib_GetTransportMode(_handle));
}
~VixDisk()
{
if (_handle) {
VixDiskLib_Close(_handle);
}
_handle = NULL;
}
private:
VixDiskLibHandle _handle;
};
/*
*--------------------------------------------------------------------------
*
* PrintUsage --
*
* Displays the usage message.
*
* Results:
* 1.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static int
PrintUsage(void)
{
printf("Usage: vixMntApiSample.exe command [options] diskPath\n\n");
printf("List of commands (all commands are mutually exclusive):\n");
printf(" -info : displays information for specified virtual disk\n");
printf(" -wmeta key value : writes (key,value) entry into disk's metadata table\n");
printf(" -rmeta key : displays the value of the specified metada entry\n");
printf(" -meta : dumps all entries of the disk's metadata\n");
printf(" -mount : Mounts target VM disk on to the proxy.\n\n");
printf("options:\n");
printf(" -host hostname : hostname/IP address of VC/vSphere host (Mandatory)\n");
printf(" -user userid : user name on host (Mandatory) \n");
printf(" -password password : password on host. (Mandatory)\n");
printf(" -port port : port to use to connect to VC/ESXi host (default = 443) \n");
printf(" -nfchostport port : port to use to establish NFC connection to ESXi host (default = 902) \n");
printf(" -vm moref=id : id is the managed object reference of the VM \n");
printf(" -libdir dir : Folder location of the VDDK installation. "
"On Windows, the bin folder holds the plugin. On Linux, it is "
"the lib64 directory\n");
printf(" -initex configfile : Specify path and filename of config file \n");
printf(" -ssmoref moref : Managed object reference of VM snapshot \n");
printf(" -mode mode : Mode string to pass into VixDiskLib_ConnectEx. "
"Valid modes are: nbd, nbdssl, san, hotadd \n");
printf(" -thumb string : Provides a SSL thumbprint string for validation. "
"Format: xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx\n");
return 1;
}
/*
*--------------------------------------------------------------------------
*
* main --
*
* Main routine of the program.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
int
main(int argc, char* argv[])
{
int retval;
bool bVixInit(false);
vector<string> disks;
memset(&appGlobals, 0, sizeof appGlobals);
appGlobals.command = 0;
appGlobals.openFlags = 0;
appGlobals.isRemote = FALSE;
retval = ParseArguments(argc, argv);
if (retval) {
return retval;
}
VixDiskLibConnectParams cnxParams = {0};
if (appGlobals.isRemote) {
cnxParams.vmxSpec = appGlobals.vmxSpec;
cnxParams.serverName = appGlobals.host;
cnxParams.credType = VIXDISKLIB_CRED_UID;
cnxParams.creds.uid.userName = appGlobals.userName;
cnxParams.creds.uid.password = appGlobals.password;
cnxParams.thumbPrint = appGlobals.thumbPrint;
cnxParams.port = appGlobals.port;
}
VixError vixError;
try {
if (appGlobals.useInitEx) {
vixError = VixDiskLib_InitEx(VIXDISKLIB_VERSION_MAJOR,
VIXDISKLIB_VERSION_MINOR,
&LogFunc, &WarnFunc, &PanicFunc,
appGlobals.libdir,
appGlobals.cfgFile);
} else {
vixError = VixDiskLib_Init(VIXDISKLIB_VERSION_MAJOR,
VIXDISKLIB_VERSION_MINOR,
NULL, NULL, NULL, // Log, warn, panic
appGlobals.libdir);
}
CHECK_AND_THROW(vixError);
bVixInit = true;
if (appGlobals.vmxSpec != NULL) {
vixError = VixDiskLib_PrepareForAccess(&cnxParams, "Sample");
}
if (appGlobals.ssMoRef == NULL && appGlobals.transportModes == NULL) {
vixError = VixDiskLib_Connect(&cnxParams,
&appGlobals.connection);
} else {
Bool ro = (appGlobals.openFlags & VIXDISKLIB_FLAG_OPEN_READ_ONLY);
vixError = VixDiskLib_ConnectEx(&cnxParams, ro, appGlobals.ssMoRef,
appGlobals.transportModes,
&appGlobals.connection);
}
CHECK_AND_THROW(vixError);
if (appGlobals.command & COMMAND_INFO) {
DoInfo();
} else if (appGlobals.command & COMMAND_READ_META) {
DoReadMetadata();
} else if (appGlobals.command & COMMAND_WRITE_META) {
DoWriteMetadata();
} else if (appGlobals.command & COMMAND_DUMP_META) {
DoDumpMetadata();
} else if (appGlobals.command & COMMAND_MOUNT) {
char again;
string disk;
disks.push_back(appGlobals.diskPath);
cout << "\n Disk - " << appGlobals.diskPath << " is entered for mounting, Would you like to enter multiple other disk paths (y/n)? ";
cin >> again;
cin.ignore(1, '\n');
while (toupper(again) == 'Y') {
cout << "\n Enter disk path: " << endl;
getline(cin, disk);
disks.push_back(disk);
cout << "\n Would you like to enter another disk path (y/n)? ";
cin >> again;
cin.ignore(1, '\n');
}
DoMount(disks);
}
retval = 0;
} catch (const VixDiskLibErrWrapper& e) {
cout << "Error: [" << e.File() << ":" << e.Line() << "] " <<
std::hex << e.ErrorCode() << " " << e.Description() << "\n";
retval = 1;
}
if (appGlobals.vmxSpec != NULL) {
vixError = VixDiskLib_EndAccess(&cnxParams, "Sample");
}
if (appGlobals.connection != NULL) {
VixDiskLib_Disconnect(appGlobals.connection);
}
if (bVixInit) {
VixDiskLib_Exit();
}
return retval;
}
/*
*--------------------------------------------------------------------------
*
* BitCount --
*
* Counts all the bits set in an int.
*
* Results:
* Number of bits set to 1.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static int
BitCount(int number) // IN
{
int bits = 0;
while (number) {
number = number & (number - 1);
bits++;
}
return bits;
}
/*
*--------------------------------------------------------------------------
*
* ParseArguments --
*
* Parses the arguments passed on the command line.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static int
ParseArguments(int argc, char* argv[])
{
int i;
if (argc < 3) {
printf("Error: Too few arguments. See usage below.\n\n");
return PrintUsage();
}
for (i = 1; i < argc - 1; i++) {
if (!strcmp(argv[i], "-info")) {
appGlobals.command |= COMMAND_INFO;
appGlobals.openFlags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
} else if (!strcmp(argv[i], "-mount")) {
appGlobals.command |= COMMAND_MOUNT;
appGlobals.openFlags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
} else if (!strcmp(argv[i], "-meta")) {
appGlobals.command |= COMMAND_DUMP_META;
appGlobals.openFlags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
} else if (!strcmp(argv[i], "-rmeta")) {
appGlobals.command |= COMMAND_READ_META;
if (i >= argc - 2) {
printf("Error: The -rmeta command requires a key value to "
"be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.metaKey = argv[++i];
appGlobals.openFlags |= VIXDISKLIB_FLAG_OPEN_READ_ONLY;
} else if (!strcmp(argv[i], "-wmeta")) {
appGlobals.command |= COMMAND_WRITE_META;
if (i >= argc - 3) {
printf("Error: The -wmeta command requires key and value to "
"be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.metaKey = argv[++i];
appGlobals.metaVal = argv[++i];
} else if (!strcmp(argv[i], "-host")) {
if (i >= argc - 2) {
printf("Error: The -host option requires the IP address "
"or name of the host to be specified. "
"See usage below.\n\n");
return PrintUsage();
}
appGlobals.host = argv[++i];
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-user")) {
if (i >= argc - 2) {
printf("Error: The -user option requires a username "
"to be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.userName = argv[++i];
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-password")) {
if (i >= argc - 2) {
printf("Error: The -password option requires a password "
"to be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.password = argv[++i];
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-thumb")) {
if (i >= argc - 2) {
printf("Error: The -thumb option requires an SSL thumbprint "
"to be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.thumbPrint = argv[++i];
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-port")) {
if (i >= argc - 2) {
printf("Error: The -port option requires the host's port "
"number to be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.port = strtol(argv[++i], NULL, 0);
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-nfchostport")) {
if (i >= argc - 2) {
return PrintUsage();
}
appGlobals.nfcHostPort = strtol(argv[++i], NULL, 0);
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-vm")) {
if (i >= argc - 2) {
printf("Error: The -vm option requires the moref id of "
"the vm to be specified. See usage below.\n\n");
return PrintUsage();
}
appGlobals.vmxSpec = argv[++i];
appGlobals.isRemote = TRUE;
} else if (!strcmp(argv[i], "-libdir")) {
if (i >= argc - 2) {
printf("Error: The -libdir option requires the folder location "
"of the VDDK installation to be specified. "
"See usage below.\n\n");
return PrintUsage();
}
appGlobals.libdir = argv[++i];
} else if (!strcmp(argv[i], "-initex")) {
if (i >= argc - 2) {
printf("Error: The -initex option requires the path and filename "
"of the VDDK config file to be specified. "
"See usage below.\n\n");
return PrintUsage();
}
appGlobals.useInitEx = true;
appGlobals.cfgFile = argv[++i];
if (appGlobals.cfgFile[0] == '\0') {
appGlobals.cfgFile = NULL;
}
} else if (!strcmp(argv[i], "-ssmoref")) {
if (i >= argc - 2) {
printf("Error: The -ssmoref option requires the moref id "
"of a VM snapshot to be specified. "
"See usage below.\n\n");
return PrintUsage();
}
appGlobals.ssMoRef = argv[++i];
} else if (!strcmp(argv[i], "-mode")) {
if (i >= argc - 2) {
printf("Error: The -mode option requires a mode string to "
"connect to VixDiskLib_ConnectEx. Valid modes are "
"'nbd', 'nbdssl', 'san' and 'hotadd'. "
"See usage below.\n\n");
return PrintUsage();
}
appGlobals.transportModes = argv[++i];
} else {
printf("Error: Unknown command or option: %s\n", argv[i]);
return PrintUsage();
}
}
appGlobals.diskPath = argv[i];
if (BitCount(appGlobals.command) != 1) {
printf("Error: Missing command. See usage below.\n");
return PrintUsage();
}
if (appGlobals.isRemote) {
if (appGlobals.host == NULL ||
appGlobals.userName == NULL ||
appGlobals.password == NULL) {
printf("Error: Missing a mandatory option. ");
printf("-host, -user and -password must be specified. ");
printf("See usage below.\n");
return PrintUsage();
}
}
return 0;
}
/*
*--------------------------------------------------------------------------
*
* DoInfo --
*
* Queries the information of a virtual disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
DoInfo(void)
{
VixDisk disk(appGlobals.connection, appGlobals.diskPath, appGlobals.openFlags);
VixDiskLibInfo *info = NULL;
VixError vixError;
vixError = VixDiskLib_GetInfo(disk.Handle(), &info);
CHECK_AND_THROW(vixError);
cout << "capacity = " << info->capacity << " sectors" << endl;
cout << "number of links = " << info->numLinks << endl;
cout << "adapter type = ";
switch (info->adapterType) {
case VIXDISKLIB_ADAPTER_IDE:
cout << "IDE" << endl;
break;
case VIXDISKLIB_ADAPTER_SCSI_BUSLOGIC:
cout << "BusLogic SCSI" << endl;
break;
case VIXDISKLIB_ADAPTER_SCSI_LSILOGIC:
cout << "LsiLogic SCSI" << endl;
break;
default:
cout << "unknown" << endl;
break;
}
cout << "BIOS geometry = " << info->biosGeo.cylinders <<
"/" << info->biosGeo.heads << "/" << info->biosGeo.sectors << endl;
cout << "physical geometry = " << info->physGeo.cylinders <<
"/" << info->physGeo.heads << "/" << info->physGeo.sectors << endl;
VixDiskLib_FreeInfo(info);
cout << "Transport modes supported by vixDiskLib: " <<
VixDiskLib_ListTransportModes() << endl;
}
/*
*--------------------------------------------------------------------------
*
* DoReadMetadata --
*
* Reads metadata from a virtual disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
DoReadMetadata(void)
{
size_t requiredLen;
VixDisk disk(appGlobals.connection, appGlobals.diskPath, appGlobals.openFlags);
VixError vixError = VixDiskLib_ReadMetadata(disk.Handle(),
appGlobals.metaKey,
NULL, 0, &requiredLen);
if (vixError != VIX_OK && vixError != VIX_E_BUFFER_TOOSMALL) {
THROW_ERROR(vixError);
}
std::vector <char> val(requiredLen);
vixError = VixDiskLib_ReadMetadata(disk.Handle(),
appGlobals.metaKey,
&val[0],
requiredLen,
NULL);
CHECK_AND_THROW(vixError);
cout << appGlobals.metaKey << " = " << &val[0] << endl;
}
/*
*--------------------------------------------------------------------------
*
* DoWriteMetadata --
*
* Writes metadata in a virtual disk.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
DoWriteMetadata(void)
{
VixDisk disk(appGlobals.connection, appGlobals.diskPath, appGlobals.openFlags);
VixError vixError = VixDiskLib_WriteMetadata(disk.Handle(),
appGlobals.metaKey,
appGlobals.metaVal);
CHECK_AND_THROW(vixError);
}
/*
*--------------------------------------------------------------------------
*
* DoDumpMetadata --
*
* Dumps all the metadata.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
static void
DoDumpMetadata(void)
{
VixDisk disk(appGlobals.connection, appGlobals.diskPath, appGlobals.openFlags);
char *key;
size_t requiredLen;
VixError vixError = VixDiskLib_GetMetadataKeys(disk.Handle(),
NULL, 0, &requiredLen);
if (vixError != VIX_OK && vixError != VIX_E_BUFFER_TOOSMALL) {
THROW_ERROR(vixError);
}
std::vector<char> buf(requiredLen);
vixError = VixDiskLib_GetMetadataKeys(disk.Handle(), &buf[0], requiredLen, NULL);
CHECK_AND_THROW(vixError);
key = &buf[0];
while (*key) {
vixError = VixDiskLib_ReadMetadata(disk.Handle(), key, NULL, 0,
&requiredLen);
if (vixError != VIX_OK && vixError != VIX_E_BUFFER_TOOSMALL) {
THROW_ERROR(vixError);
}
std::vector <char> val(requiredLen);
vixError = VixDiskLib_ReadMetadata(disk.Handle(), key, &val[0],
requiredLen, NULL);
CHECK_AND_THROW(vixError);
cout << key << " = " << &val[0] << endl;
key += (1 + strlen(key));
}
}
static void
UnmountDisks()
{
vector<VixDiskSetHandle>::const_iterator iter = mountedDisks.begin();
for (; iter != mountedDisks.end(); ++iter) {
VixMntapi_CloseDiskSet(*iter);
}
}
static void
UnmountVolumes()
{
vector<MountedVolume>::const_iterator iter = mountedVolumes.begin();
for (; iter != mountedVolumes.end(); ++iter) {
VixMntapi_FreeVolumeInfo((*iter).volInfo);
VixMntapi_DismountVolume((*iter).volumeHandle, TRUE);
}
}
static void
DoMount(const vector<string> &disks)
{
VixError vixError;
VixDiskLibHandle *diskHandles;
VixDiskLibHandle diskHandle, childHandle;
VixDiskSetHandle diskSetHandle = NULL;
VixVolumeHandle *volumeHandles = NULL;
VixVolumeInfo *volInfo = NULL;
VixDiskSetInfo *diskSetInfo = NULL;
size_t numVolumes = 0;
uint32 openFlags = VIXDISKLIB_FLAG_OPEN_READ_ONLY;
int j;
vector<string> childDisks;
int diskHandlesCount = disks.size();
diskHandles = new VixDiskLibHandle[diskHandlesCount];
for(int i=0; i < diskHandlesCount; i++) {
diskHandles[i] = NULL;
}
char *pch, *dup, buffer[50];
dup = strdup(appGlobals.vmxSpec);
pch = strtok(dup, "=");
while (pch != NULL)
{
sprintf(buffer, "%s", pch);
pch = strtok (NULL, "=");
}
for(int i=0; i<disks.size(); i++) {
std::stringstream childDiskName;
childDiskName << "C:\\" << (string)buffer << "-childDisk-" << (i+1) << ".vmdk";
childDisks.push_back(childDiskName.str());
}
free(dup);
printf("Calling VixMntapi_Init...\n");
vixError = VixMntapi_Init(VIXMNTAPI_MAJOR_VERSION, VIXMNTAPI_MINOR_VERSION,
&LogFunc, &WarnFunc, PanicFunc,
appGlobals.libdir, appGlobals.cfgFile);
CHECK(vixError, cleanup);
// create local connection
VixDiskLibConnection localConnection = NULL;
vixError = VixDiskLib_Connect(NULL, &localConnection);
CHECK(vixError, cleanup);
vector<string>::const_iterator iter = disks.begin();
for ( int i=0 ; iter != disks.end(); ++i, ++iter)
{
vixError = VixDiskLib_Open(appGlobals.connection,
(*iter).c_str(),
openFlags,
&diskHandle);
CHECK(vixError, cleanup);
printf("Selected transport method: %s\n", VixDiskLib_GetTransportMode(diskHandle));
vixError = VixDiskLib_CreateChild(diskHandle, childDisks[i].c_str(), VIXDISKLIB_DISK_MONOLITHIC_SPARSE, NULL, NULL);
CHECK(vixError, cleanup);
vixError = VixDiskLib_Open(localConnection, childDisks[i].c_str(), VIXDISKLIB_FLAG_OPEN_SINGLE_LINK, &childHandle);
CHECK(vixError, cleanup);
vixError = VixDiskLib_Attach(diskHandle, childHandle);
CHECK(vixError, cleanup);
diskHandles[i] = childHandle;
}
printf("\nCalling VixMntapi_OpenDiskSet...\n");
vixError = VixMntapi_OpenDiskSet(diskHandles,
disks.size(),
openFlags,
&diskSetHandle);
CHECK(vixError, cleanup);
mountedDisks.push_back(diskSetHandle);
printf("\n\nCalling VixMntapi_GetDiskSetInfo...\n");
vixError = VixMntapi_GetDiskSetInfo(diskSetHandle, &diskSetInfo);
CHECK(vixError, cleanup);
printf("DiskSet Info - flags %u (passed - %u), mountPoint %s.\n",
diskSetInfo->openFlags, openFlags,
diskSetInfo->mountPath);
printf("\n\nCalling VixMntapi_GetVolumeHandles...\n");
vixError = VixMntapi_GetVolumeHandles(diskSetHandle,
&numVolumes,
&volumeHandles);
CHECK(vixError, cleanup);
printf("\n\nNum Volumes %d\n", numVolumes);
printf("Enter the volume number from which to start mounting...\n");
scanf("%d", &j);
volInfo = NULL;
for (int i = j-1; i < numVolumes; ++i) {
printf("\n\nMounting volume using VixMntapi_MountVolume...\n");
vixError = VixMntapi_MountVolume(volumeHandles[i], TRUE);
if (vixError == ERROR_MNTAPI_VOLUME_ALREADY_MOUNTED)
;
else
CHECK(vixError, cleanup);
}
MountedVolume newVolume = {0, 0};
for (int i = j-1; i < numVolumes; ++i) {
printf("\n\nGetting volume info using VixMntapi_GetVolumeInfo...\n");
vixError = VixMntapi_GetVolumeInfo(volumeHandles[i], &newVolume.volInfo);
CHECK(vixError, cleanup);
printf("\nMounted Volume %d, Type %d, isMounted %d, symLink %s, numGuestMountPoints %d (%s)\n\n",
i, newVolume.volInfo->type, newVolume.volInfo->isMounted,
newVolume.volInfo->symbolicLink == NULL ? "<null>" : newVolume.volInfo->symbolicLink,
newVolume.volInfo->numGuestMountPoints,
(newVolume.volInfo->numGuestMountPoints == 1) ? (newVolume.volInfo->inGuestMountPoints[0]) : "<null>" );
mountedVolumes.push_back(newVolume);
assert(volumeHandles[i]);
assert(newVolume.volInfo);
newVolume.volumeHandle = volumeHandles[i];
std::wstringstream ansiSS;
ansiSS << newVolume.volInfo->symbolicLink;
std::wstring sVolumeName = ansiSS.str();
sVolumeName = sVolumeName.substr(3);
sVolumeName.erase(sVolumeName.length()-1);
sVolumeName = L"\\Device" + sVolumeName;
cout << endl << endl << "Defining MS-DOS device name \"T:\" for volume " << newVolume.volInfo->symbolicLink << endl;
if ( DefineDosDeviceW( DDD_RAW_TARGET_PATH, L"T:", sVolumeName.c_str()) ) {
HANDLE hDevice;
std::wstring wsVolume = L"\\\\.\\T:";
hDevice = CreateFileW( wsVolume.c_str(),
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if ( hDevice == INVALID_HANDLE_VALUE ) {
printf("Error opening volume, err = %d\n", GetLastError());
} else {
WIN32_FIND_DATAW fdFile;
std::wstring wsPath = L"T:\\*.*";
HANDLE hFind = FindFirstFileW(wsPath.c_str(), &fdFile);
std::string MountPoint = (newVolume.volInfo->numGuestMountPoints == 1) ? (newVolume.volInfo->inGuestMountPoints[0]) : "<null>";
cout << "=====================================================================================" << endl;
cout << "=== Dumping contents of target VM's (" << MountPoint << ") drive (Mounted at T: drive on proxy) ===" << endl;
cout << "=====================================================================================" << endl;
while ( hFind != INVALID_HANDLE_VALUE ) {
if ( hFind != INVALID_HANDLE_VALUE ) {
printf("Successfully read Object = '%S'\n", fdFile.cFileName);
} else {
printf("Failed to read Object. Volume/NTFS filesystem is corrupt (%d)\n", GetLastError());
}
if ( !FindNextFileW(hFind, &fdFile )) {
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
}
::MessageBoxW(NULL, L"Volume mounted under T: drive, press OK to unmount", L"Info", NULL);
DefineDosDeviceW( DDD_RAW_TARGET_PATH |
DDD_REMOVE_DEFINITION |
DDD_EXACT_MATCH_ON_REMOVE, L"T:", sVolumeName.c_str());
}
}
}
if (VIX_FAILED(vixError)) {
printf("Failed at %s:%d with %lld, but ignoring\n",
__FILE__, __LINE__, vixError);
vixError = VIX_OK;
}
cleanup:
printf("Cleanup Stuff:\n");
VixMntapi_FreeDiskSetInfo(diskSetInfo);
if (volumeHandles) {
VixMntapi_FreeVolumeHandles(volumeHandles);
}
printf(" Unmounting Volumes...\n");
UnmountVolumes();
printf(" Unmounting Disks...\n");
UnmountDisks();
printf(" Closing Disk handles, unlinking and deleting the child disk file...\n");
for(j = 0; j < diskHandlesCount; j++) {
VixDiskLib_Close(diskHandles[j]);
VixDiskLib_Unlink(localConnection, childDisks[j].c_str());
DeleteFileA(childDisks[j].c_str());
}
VixDiskLib_Disconnect(localConnection);
printf("Calling VixMntapi_Exit...\n");
VixMntapi_Exit();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment