65.9K
CodeProject 正在变化。 阅读更多。
Home

虚拟卷软件开发工具包 (VV SDK) 在线用户指南

2014年7月9日

CPOL

12分钟阅读

viewsIcon

25031

虚拟卷软件开发工具包 (VV SDK) 是一个用于创建虚拟磁盘的开发人员工具包。

引言

虚拟卷软件开发工具包 (VV SDK) 是一个用于创建虚拟磁盘的开发人员工具包。

如果您想创建一个自定义的 RAM 磁盘应用程序,或者处理与驱动器号关联的磁盘映像,您无需花费大量时间编写驱动程序。只需下载并试用 VV SDK

VV SDK 允许应用程序创建自己的 RAM 驱动器,其内容完全存储在内存中;基于映像文件的虚拟驱动器;以及也可以装载为虚拟驱动器的加密容器。虚拟卷可以模拟独立卷和整个硬盘,并具有分区能力。

内置格式化程序能够创建具有现成文件系统的分区。每个虚拟卷或分区都可以分配一个驱动器号,其可见性可以限制为当前会话。

附加功能包括自动将 RAM 磁盘数据从 RAM 刷新到关联的映像文件以避免数据丢失,以及在虚拟磁盘卸载时安全擦除内存中的机密数据。

VV SDK 内容

VV SDK 安装包中的文件列表

  • spvve.sys 是负责创建、删除和管理虚拟磁盘的主要内核模式驱动程序。
  • spvdbus.sys 是一个虚拟总线驱动程序,它提供了包含一个或多个分区的完整硬盘模拟。
  • vvlib.dll 是一个用于连接到应用程序的库,其中包含本文所述的 API 函数。它可以链接到任何项目,无论其实现语言是什么。
  • vv.exe 是一个控制台应用程序,用于演示该工具包的功能。
  • install.exe 是一个演示如何安装该产品的应用程序。该应用程序的更详细模拟是控制台演示中的“install”命令。
  • vvlib.lib 和 .h 文件是用于将 VV SDK 链接到任何用 C/C++ 语言编写的项目中的链接库和头文件。

特点

本节提供了有关虚拟卷工具包功能的更多信息。它描述了一套可供开发人员在应用程序中使用的工具。

虚拟卷的主要功能是创建 RAM 磁盘,用于将数据存储在高速度内存中,从而提供对信息的快速访问。具体的读/写速度取决于处理器和内存模块的性能。例如,这对于磁盘子系统性能可能成为瓶颈的数据库服务器可能很有用。您可以创建一个基于存储在普通硬盘上的映像文件的虚拟磁盘。可以创建混合虚拟磁盘。创建此类磁盘时,其内容会用映像文件数据填充,但之后它们在内存中运行。虚拟磁盘可以作为独立卷或具有分区表的完整硬盘创建。用户可以将硬盘分区为所需数量的驱动器(逻辑驱动器)。

每个虚拟卷或分区都可以分配一个驱动器号(例如,R:)在全局或会话命名空间中。在全局命名空间中,该驱动器号对系统中的所有用户都可用;在会话命名空间中,它仅对用于调用例程的用户上下文可用。

虚拟卷可以创建预格式化的虚拟磁盘,并支持 FAT16、FAT32 和 NTFS 等文件系统。也可以使用虚拟卷函数格式化现有卷。VV SDK 提供了一系列用于处理内存和逻辑驱动器号以及获取有关已挂载虚拟磁盘信息的辅助函数。

另一个重要功能是能够注册虚拟磁盘以进行自动挂载,这使得在系统启动早期(在服务运行和用户登录之前)创建并挂载虚拟磁盘成为可能。挂载卷有几种方式,例如,只读方式,即无法更改其内容(但请记住,并非所有文件系统都可以与只读卷一起工作),和/或作为可移动磁盘。您可以使用“原始”映像(用于基于映像文件的磁盘);通常,任何文件都可以用作映像。如果使用 NTFS 文件系统,您可以在挂载时启用卷压缩。

引擎允许加密虚拟磁盘上的数据。在这种情况下,映像文件应称为加密容器。支持的分组密码是:AES、DES、3DES、RC6、Serpent、Blowfish、Twofish、CAST 和 GOST 28147-89。

产品中的内核模式驱动程序由供应商进行数字签名,这消除了购买自己代码签名证书的必要性。如果客户需要一个没有我们签名的版本进行自定义签名,可以根据要求提供。还可以提供命名版本(通过协商),例如当客户希望他们的公司名称在其产品中被提及时。

API

下一节将介绍提供此产品功能的 API 函数的描述。每个子节都通过调用示例描述了相应 API 函数的用法。产品的整个 API 在提供的头文件中进行了描述。要链接到您用 C/C++ 编写的项目,您可以使用 vvlib.lib 链接库。库代码包含在 vvlib.dll 可执行模块中。库中使用的所有字符串都以 Unicode 存储和管理,除了包含卷标的字符串,其编码是 ANSI。有关每个函数和结构的更详细描述,请参阅 SDK 安装后 \texts\vv.chm 文件中的文档。

重要的是,您首先需要通过 VvlibInitialize API 函数初始化引擎。此函数应在所有其他库函数之前调用。只有在初始化成功后,您才能调用库的其他函数。

创建虚拟磁盘

要创建虚拟 RAM 磁盘,请使用标准或扩展的 VvlibCreateMemoryVolume API 函数。在输入参数中指定加密算法(如果不需要加密,则为 VV_ALG_NULL 值)、新磁盘的大小、所需的密码(如果需要)、正在创建混合虚拟磁盘的映像文件路径,以及控制虚拟磁盘创建和操作的各种方面的标志。如果磁盘创建成功,则函数返回非零值,否则返回“false”。您可以使用内置的 VvlibGetErrorCode API 函数找出错误原因。

在输出时,该函数会用执行结果的详细信息填充 VV_MOUNT_INFORMATION 结构。VolumeHandle 字段中的值是虚拟磁盘的句柄,可用于后续控制。

此函数可能需要一些时间来创建映像;特别是读取大型映像文件(如果指定了)需要时间。因此,您应该使用单独的线程来执行此操作,以避免应用程序用户界面冻结。

ULONG uError = 0;
ULONG uMountFlags = 0;
VV_MOUNT_INFORMATION MountInfo = {0};

// Create mount flags bitmask.
uMountFlags = VV_MODE_EMULATE_DISK |    // Emulate partitionable hard disk.
    VV_MODE_REMOVABLE;        // Create removable disk instead of fixed.

// Create RAM-drive with no associated image file.
if (! VvlibCreateMemoryVolume (
    VV_ALG_NULL,    // Don't use encryption.
    104857600,    // 100 MB, size of the disk.
    NULL,        // Pure RAM-disk, not associated with an image.
    NULL,        // Password not required for pure in-memory disks.
    &MountInfo))    // Results of the operation will be placed here.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

创建映像文件

VvlibCreateImage 函数在指定文件夹中创建硬盘映像文件。与大多数库函数一样,如果操作成功,它将返回“true”,否则返回“false”。结果是您硬盘上的一个映像文件。映像文件的大小将比输入参数中指定的大小大几 KB,因为结果文件包含映像头。

函数输入包括文件路径、指示是否覆盖现有文件的标志、映像大小(字节)、将作为新加密密钥基础的访问密码(如果需要)、加密算法或 VV_ALG_NULL(如果不需要加密)、文件系统类型或 VV_FS_NONE(如果不需要格式化或稍后进行格式化),以及文件系统使用的卷标或 NULL(如果不需要卷标)。

选择正确的映像类型很重要。要为独立卷创建映像,请将 uImageType 参数指定为 VV_IMAGE_VOLUME。要为硬盘模拟创建映像,请指定 VV_IMAGE_HARD_DISK; 在这种情况下,映像中还会额外形成一个分区表。

ULONG uError = 0;

// Create hard disk image with a partition table.
if (! VvlibCreateImage (
    L"C:\\Images\\hdtest.vvi",    // Path to the image file.
    true,                // Existing file should be overwritten.
    VV_IMAGE_HARD_DISK,        // Type of the image is Hard Disk.
    104857600,            // Size of the image is 100 MB.
    NULL,                // No password needed.
    VV_ALG_NULL,            // No encryption used.
    VV_FS_NTFS,            // The only partition will be formatted to NTFS.
    "Test volume"))            // Label for the only volume.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

// Create volume image as cryptocontainer with AES-256 encryption.
if (! VvlibCreateImage (
    L"C:\\Images\\cctest.vvi",    // Path to the image file.
    false,                // Existing file should not be overwritten.
    VV_IMAGE_VOLUME,        // Type of the image is standalone Volume.
    104857600,            // Size of the image is 100 MB.
    L"MySuperPassword",        // Password for using it as a cipher key.
    VV_ALG_AES,            // Encryption algorithm is AES with 256-bit key.
    VV_FS_NTFS,            // Volume will be formatted for use with NTFS.
    "Crypto volume"))        // Volume label.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

从文件挂载映像

VvlibMountImage API 函数创建一个基于硬盘上指定映像文件的虚拟磁盘。如果挂载成功,则返回非零值,否则返回零。使用 VvlibGetErrorCode 函数获取错误代码。

函数输入包括映像文件路径字符串、加密容器的访问密码(如果需要),以及指示挂载参数的标志。输出是 pMountInformation 参数中的结构,其中填充了结果的详细信息和虚拟磁盘句柄。

指定挂载映像的类型很重要。例如,如果映像是为硬盘模拟创建的,则应指定 VV_MODE_EMULATE_DISK 标志,否则将不识别分区表。

ULONG uError = 0;
VV_MOUNT_INFORMATION MountInfo = {0};

// Mount the specified image file.
// A correct password must be passed in.
if (! VvlibMountImage (
    L"C:\\Images\\cctest.vvi",    // Path to the existing image file.
    L"MySuperPassword",        // Password is needed because the image is encrypted.
    VV_MODE_REMOVABLE,        // Mount as removable disk that is ejectable from Explorer.
    &MountInfo))            // Get a handle for the mounted volume.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

要挂载随机文件(即原始映像)并基于它创建虚拟磁盘,请调用 VvlibMountRawImage 函数。在这种情况下,设置 VV_MODE_RAW 标志是可选的。

ULONG uError = 0;
VV_MOUNT_INFORMATION MountInfo = {0};

// Mount the specified file as image.
// This file should be large enough.
if (! VvlibMountRawImage (
    L"C:\\Images\\rawtest.bin",    // Path to an existing binary file.
    VV_MODE_REMOVABLE,        // Mount as removable disk that is ejectable from Explorer.
    &MountInfo))            // Get a handle for the mounted volume.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

创建自动挂载的虚拟磁盘

VvlibAddAutoVolume 函数管理虚拟磁盘在注册表中的注册。因此,每次系统启动时都会创建虚拟磁盘,并且可以在系统服务(包括)中使用。虚拟磁盘创建后,其分区会自动分配在函数参数中指定的驱动器号。输入还包括挂载标志,安装后应用于磁盘的属性,所需的磁盘大小(字节),文件系统使用的卷标,以及如果您想创建混合虚拟磁盘或基于映像文件的虚拟磁盘的挂载映像路径。

该函数没有加密参数,因为在这种情况下,密码必须以明文形式存储,这是不安全的,因此该函数仅允许挂载不带密码保护的映像。

该函数的扩展版本包括几个额外的输入参数,例如,用于在挂载后自动在虚拟磁盘上创建文件夹(不支持嵌套路径),或如果指定了映像文件,则用于自动将混合磁盘数据刷新到映像文件。

如果自动挂载的虚拟磁盘注册成功,则函数返回非零值;否则返回零,并通过 VvlibGetErrorCode 返回错误代码。

ULONG uError = 0;

// Create RAM drive that will automatically mount on system startup.
if (! VvlibAddAutoVolume (
    L'R',            // Drive letter will be assigned automatically.
    VV_MODE_IN_MEMORY,    // Create a standalone in-memory volume.
    0,            // No properties needed in this case.
    536870912,        // Size of the RAM drive will be 512 MB.
    VV_FS_FAT32,        // The volume will be formatted into FAT32...
    "RAM drive",        // ...and will be labeled "RAM drive".
    NULL))            // No associated image file, pure RAM disk.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

卸载虚拟磁盘

VvlibUnmount API 函数允许您卸载虚拟磁盘。此函数可应用于各种类型的磁盘,包括内存中的磁盘(RAM 磁盘)和从映像文件挂载的磁盘。该函数的标准版本包含两个参数:一个虚拟磁盘的句柄(您可以通过使用 VvlibGetVolumes 函数枚举磁盘来获取),以及一个强制卸载标志(以防虚拟磁盘被应用程序阻止并且包含打开的文件句柄)。

ULONG uIdx = 0;
ULONG uError = 0;
bool bEraseData = false;
ULONG uHandles = NULL;
PVHANDLE pHandles = NULL;
VV_VOLUME_INFORMATION VolInfo = {0};

// Get the list of mounted volumes.
if (! VvlibGetVolumes (
    &uVolumes,    // Receives the number of mounted volumes.
    &pVolumes))    // Receives the array of volume handles.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

// Enumerate the mounted volumes.
for (uIdx = 0; uIdx < uVolumes; uIdx += 1)
{
    // Get volume information.
    if (! VvlibQueryVolumeInformation (
        pHandles [uIdx],    // Volume handle.
        &VolInfo))        // Will be filled with the information about the volume.
    {
        // Error handling goes here.
        uError = VvlibGetErrorCode ();
        ...
    }
        
    // Check if we need to securely erase the virtual disk data in memory to keep it confidential.
    bEraseData = VolInfo.AlgId != VV_ALG_NULL;

    // Unmount the current virtual disk.
    if (! VvlibUnmount (
        pHandles [uIdx],    // Volume handle.
        true,            // Force unmount regardless of open files, etc.
        bEraseData))        // Whether or not to wipe image data in memory.
    {
        // Error handling goes here.
        uError = VvlibGetErrorCode ();
        ...
    }
}

// Release used resources.
VvlibFree (
    &pHandles);

卸载时安全删除数据

VvlibUnmountEx API 函数是前面描述的卸载函数的扩展版本。此函数允许在卸载时安全地销毁存储在内存中的虚拟磁盘数据。为此,应将第三个参数 bWipeImageData 设置为非零值。这仅适用于内容存储在 RAM 中的虚拟磁盘,否则不适用。请参阅上面的代码示例。

创建加密虚拟磁盘

创建虚拟磁盘的一些函数,例如 VvlibCreateMemoryVolumeVvlibCreateImage,包括加密映像数据的能力。加密是使用内置的分组密码之一进行的,例如 AES、DES、3DES、RC6、Serpent、Blowfish、Twofish、CAST 或 GOST 28147-89。加密方法通常指定为输入参数 uAlgId。请参阅上面的代码示例。

管理驱动器号

VvlibCreateLink API 函数创建到虚拟磁盘设备对象的符号链接(即,驱动器号,如 R: 或 V:),而 VvlibDeleteLink 函数删除它。

bSessionOnly 参数接受一个值,该值决定链接的创建位置 — 在全局还是会话命名空间中。会话驱动器号仅对当前用户可用,全局驱动器号对所有人可用。VvlibCreateLink 函数的扩展版本在模拟具有分区的完整硬盘时设置其他驱动器号。在这种情况下,驱动器号可以分配给每个分区,而不仅仅是第一个。

ULONG uError = 0;
VHANDLE hVolume = NULL;
...
// Create drive letter for a virtual disk.
// If the specified virtual disk is a hard disk, then only the first partition will be affected.
if (! VvlibCreateLink (
    hVolume,    // Handle to the volume.
    VV_LINK_FORCE,    // Delete existing link first, if needed.
    L'S',        // New drive letter will be "S:".
    false))        // Create link in a global namespace, for all users.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

VvlibDeleteLink 函数会删除到虚拟卷的链接和系统中的驱动器号。该函数不卸载虚拟磁盘,它只删除链接和驱动器号。但是,虚拟磁盘卸载也会自动删除分配的驱动器号,因此您无需调用 VvlibDeleteLink 函数。在删除驱动器号后,可以为虚拟驱动器分配新的驱动器号。

ULONG uError = 0;
VHANDLE hVolume = NULL;
...
// Delete link for the specified virtual disk.
// If the specified virtual disk is a hard disk, then all link assigned to its partitions will be deleted.
if (! VvlibDeleteLink (
    hVolume,         // Virtual disk handle.
    VV_PARTITION_ALL))    // Process all partitions if applicable.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

格式化卷

VvlivFormatVolume API 函数使用指定的ファイルシステム格式化卷。支持的文件系统包括 FAT16、FAT32 和 NTFS。输入参数为:虚拟磁盘句柄和格式化分区编号(对于具有多个分区的硬盘),格式化操作标志,要格式化分区的ファイルシステム类型,新创建ファイルシステム的卷标或 NULL(如果不需要卷标)。

输出时,如果格式化成功,函数返回非零值,否则返回“false”。错误代码可通过 VvlibGetErrorCode 获取。

ULONG uError = 0;
ULONG uFormatFlags = 0;
VHANDLE hVolume = NULL;
...

// Create format flags bitmask.
uFormatFlags = VV_FMT_COMPRESS |    // Apply NTFS compression.
    VV_FMT_USE_INDEXES;        // Append the volume index to labels (for partitions).

// Format the specified volume for use with NTFS file system.
if (! VvlibFormatVolume (
    hVolume,        // Virtual disk handle.
    VV_PARTITION_ANY,    // Format all partitions, if applicable.
    uFormatFlags,        // Flags affecting formatting behaviour.
    VV_FS_NTFS,        // Format to NTFS file system.
    "Volume"))        // Base string for the volume labels.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

此函数可能需要一些时间,因此您应该使用单独的线程来调用它,以避免应用程序用户界面冻结。

其他管理函数

VvlibSetFlushState 是一个用于设置混合虚拟磁盘数据自动刷新功能的函数,包括两次刷新操作之间的间隔(秒)、是否转储所有数据或仅转储已更改块(更快)的操作标志,以及在保存磁盘数据之前是否需要文件系统缓存刷新。

ULONG uError = 0;
ULONG uFlushFlags = 0;
VHANDLE hVolume = NULL;
...

// Create flush flags bitmask.
uFlushFlags = VV_SAVE_FLUSH_FS |    // Flush file systems on the virtual disk before writing.
    VV_SAVE_DIFFERENTIAL;        // Flush only changed blocks to increase the speed.

// Set new autoflush mode.
if (! VvlibSetFlushState (
    hVolume,    // Virtual disk handle.
    3600,        // Flush interval is one hour (in seconds).
    uFlushFlags))    // Flush flags affecting flush behaviour.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

VvlibSetProperties 函数设置和删除虚拟磁盘的各种属性。这些属性存储在映像文件的头中。例如,您可以指定在系统关机和/或电源转换期间是否要保存混合虚拟磁盘数据。

ULONG uError = 0;
VHANDLE hVolume = NULL;
...
// Set new properties.
if (! VvlibSetProperties (
    hVolume,        // Virtual disk handle.
    VV_PROP_SAVE_VOLUME,    // Save hybrid disk data on shutdown.
    0))            // Don't remove existing properties, if there are any.
{
    // Error handling goes here.
    uError = VvlibGetErrorCode ();
    ...
}

版本历史

2014.02.04 v2.5.3

  • 修复了基于映像的 RAM 磁盘的 CPU 最大化问题。
  • 修复了 Windows 8.1 上的一些 NTFS 格式化问题。
  • 为 RAM 磁盘内存分配添加了 NUMA 节点首选项。

2013.11.15 v2.5.2

  • 修复了 Windows 8 和 Windows 8.1 上的任务管理器崩溃问题。
  • 修复了 Samsung Magician 中一个晦涩的启动崩溃问题。

2013.10.05 v2.5.1

  • 初始版本。此 SDK 源自 RAM Disk 软件,现在已作为独立产品提供给开发人员。
© . All rights reserved.