当前位置: 首页 > 工具软件 > TrueCrypt > 使用案例 >

TrueCrypt 6.2a原理及代码分析

梁巴英
2023-12-01

TrueCrypt 6.2a原理及代码分析

  3 comments

  25th Apr 10

  rafa

 

1 项目物理布局

Project 
   |____ Boot /* MBR部分的代码 */ 
   |____ Common /* 公共数据 */ 
   |____ Crypto /* 加密库 */ 
   |____ Driver /* 驱动代码 */ 
   |____ Format /* 应用程序:Format 格式化*/ 
   |____ Mount /* 应用程序:Mount 装载/卸载磁盘*/ 
   |____ Platform /* 平台相关代码 */ 
   |____ Setup /* 应用程序: 安装代码 */ 
   其他略

2 编译需要的工具

2.1 Linux平台

    – GNU Make 
    – GNU C++ Compiler 4.0 or compatible    
    – pkg-config 
    – wxWidgets 2.8 shared library and header files installed orwxWidgets 2.8 library source code 
    – FUSE library and header files 
    – RSA Security Inc. PKCS #11 Cryptographic Token Interface(Cryptoki) 2.20 header files

2.2 Window平台

    – Microsoft Visual C++ 2008 SP1 (Professional Editionor compatible) 
    – Microsoft Visual C++ 1.52 (available from MSDN SubscriberDownloads) 
    – Microsoft Windows Driver Kit for Windows Server 2008(build 6001.18002) 
    – RSA Security Inc. PKCS #11 Cryptographic Token Interface(Cryptoki) 2.20 header files 
    – NASM 0.99 assembler 
    – Yasm assembler 
    – gzip compressor

3 驱动部分代码分析

3.1 初始化过程

3.1.1 初始化加密/解密处理线程.

   系统使用了PIPE技术, 提高了处理能力:通过使用多线程实现PIPE数据流处理。

   系统根据当前CPU个数,创建业务工作线程,每个CPU对应2个业务处理线程:读数据线程和写数据线程,这样做可以减少核间锁的开销和提高读写队列处理能力。

   系统最多支持32个CPU。此处为整个系统搭建了一个运行处理框架。

   相应的接口为: EncryptionThreadPoolStart

3.1.2 检查加密算法有效性和获悉系统版本信息

3.1.3 驱动为SERVICE_BOOT_START启动方式

    如驱动为SERVICE_BOOT_START启动方式,则需要加载由TrueCrypt的MBR代码加载的启动参数。

typedef struct 

char Signature[8]; /* magic : "TRUE #Ef" 空格代表了DC1:左向游标 */ 
uint16 BootLoaderVersion; /* 版本:6.2a 数值为0x062a*/ 
uint16 CryptoInfoOffset; /* 加密数据区偏移位置 */ 
uint16 CryptoInfoLength; /* 加密数据长度 */ 
uint32 HeaderSaltCrc32; /* 加密算法Salt */ 
Password BootPassword; /* 加密密码 */ 
uint64 HiddenSystemPartitionStart; /* 隐藏系统分区启动位置 */ 
uint64 DecoySystemPartitionStart; /* Decoy系统分区启动位置 */ 
uint32 BootArgumentsCrc32; /* Crc32教研值 */

} BootArguments;

NTSTATUS LoadBootArguments () 

NTSTATUS status = STATUS_UNSUCCESSFUL;

/* 从物理地址加载启动参数 
* 每次向下偏移2K地址,最大到4K的地址处。 
         * 即:(0×9000 < 4 + 0×10 + sizeof(BootArguments))~(0×8000 < 4 + 0×10 + sizeof(BootArguments)) 地址空间范围 
* 这里以0×9000为起始基数开始偏移计算地址 
   */ 
for (bootLoaderSegment = TC_BOOT_LOADER_SEGMENT; 
   bootLoaderSegment >= TC_BOOT_LOADER_SEGMENT – 64 * 1024 / 16&& status != STATUS_SUCCESS; 
   bootLoaderSegment -= 32 * 1024 / 16) 

   bootArgsAddr.QuadPart = (bootLoaderSegment << 4) +TC_BOOT_LOADER_ARGS_OFFSET; 
   mappedBootArgs = MmMapIoSpace (bootArgsAddr, sizeof(BootArguments), MmCached); 
   if (!mappedBootArgs) 
    return STATUS_INSUFFICIENT_RESOURCES;

   /* 检查是否是TrueCrypt 的magic来判断是否是TrueCrypt的参数 
                * #define TC_IS_BOOT_ARGUMENTS_SIGNATURE(SG)     (SG[0] == ‘T’ && SG[1] == ‘R’ && SG[2] == ‘U’ && SG[3]== ‘E’ && SG[4] == 0×11 && SG[5] == 0×23 && SG[6] ==0×45 && SG[7] == 0×66) 
   * 翻译出该magic: "TRUE #Ef" 空格代表了DC1:左向游标 
   */ 
   if (TC_IS_BOOT_ARGUMENTS_SIGNATURE (mappedBootArgs)) 
   { 
    BootArguments *bootArguments = (BootArguments *)mappedBootArgs; 
    if (bootArguments->BootLoaderVersion == VERSION_NUM 
     && bootArguments->BootArgumentsCrc32 !=GetCrc32 ((byte *) bootArguments, (int) ((byte*)&bootArguments->BootArgumentsCrc32 – (byte *) bootArguments))) 
    { 
         TC_BUG_CHECK(STATUS_CRC_ERROR); 
    }

    /* 保存启动参数到全局变量 */ 
    BootLoaderSegment = bootLoaderSegment;

    BootArgs = *bootArguments; 
    BootArgsValid = TRUE; 
    memset (bootArguments, 0, sizeof (*bootArguments));

    if (BootArgs.BootLoaderVersion < 0×600) 
    { 
     /* 6.0 版本以下不支持 以下两种系统 
     * 这两种系统分区加密是在6.2中引入的 
     */ 
     BootArgs.HiddenSystemPartitionStart = 0; 
     BootArgs.DecoySystemPartitionStart = 0; 
    }

    …

    if (CacheBootPassword &&BootArgs.BootPassword.Length > 0) 
     AddPasswordToCache (&BootArgs.BootPassword);

    status = STATUS_SUCCESS; 
   }

   MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments)); 
}

return status; 

3.1.4 驱动入口

NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRINGRegistryPath) 

PKEY_VALUE_PARTIAL_INFORMATION startKeyValue; 
int i; 
TCDriverObject = DriverObject; 
KeInitializeMutex (&driverMutex, 0);

EncryptionThreadPoolStart(); 
SelfTestsPassed = AutoTestAlgorithms (); 
PsGetVersion (&OsMajorVersion, &OsMinorVersion, NULL, NULL);

ReadRegistryConfigFlags(); 
if (NT_SUCCESS (TCReadRegistryKey (RegistryPath, L"Start",&startKeyValue))) 

   /* 如果驱动启动方式为 SERVICE_BOOT_START, 即属于加密了系统磁盘方式 
* 这种方式需要加载启动参数 
   * 启动参数已经由TrueCrypt的MBR代码写到固定的物理地址处,一般从0×9000物理地址处开始检查参数 
   */ 
   if (startKeyValue->Type == REG_DWORD && *((uint32 *)startKeyValue->Data) == SERVICE_BOOT_START) 
   {    
    LoadBootArguments();

    /* 根据注册表项,判断是否是卷设备的upfilter 
     * 此设备{71A27CDD-812A-11D0-BEC7-08002BE2092F}是卷设备,其一般上层过滤为VolSnap 
    */ 
    VolumeClassFilterRegistered =IsVolumeClassFilterRegistered();

    DriverObject->DriverExtension->AddDevice =DriverAddDevice; 
   }

   TCfree (startKeyValue); 
}

for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i) 

   DriverObject->MajorFunction[i] = TCDispatchQueueIRP; 
}

DriverObject->DriverUnload = TCUnloadDriver; 
/* 创建设备 
* 设备名称为:\\Device\\TrueCryptVolume"\\DosDevices\\TrueCrypt
*/ 
return TCCreateRootDeviceObject (DriverObject); 
}

 

1 业务架构分析

  TrueCrypt模块通过Windows操作系统加载,模块驱动在入口接口中作了初始化:初始化了密码算法、加载了启动参数并创建了业务框架。

  模块驱动初始化完成后,整个TrueCrypt模块分为了两部分:与Windows操作系统交互部分和业务流程部分。与Windows操作系统交互部分通过创建设备对象来与Windows 操作系统的I/O管理器进行数据交互;业务流程部分通过业务架构进行工作;他们之间的交互通过队列来传递数据流。

  这样基本形成了从上到下和从下到上两种数据流,共cpu个数 * 2 条数据流,每条数据流通过队列和线程池实现了半异步和半同步的设计模式。

1.1 主要数据结构

三种工作队列状态 
typedef enum 

WorkItemFree, 
WorkItemReady, 
WorkItemBusy 
} WorkItemState;

三种工作队列类型

typedefenum 

EncryptDataUnitsWork, 
DecryptDataUnitsWork, 
DeriveKeyWork 
} EncryptionThreadPoolWorkType;

/* 加密相关的参数 :加密算法类型,密钥,加密磁盘元数据等 */ 
typedef struct CRYPTO_INFO_t 

int ea;      /* Encryption algorithm ID */ 
int mode;     /* Mode of operation (e.g., XTS) */ 
unsigned __int8 ks[MAX_EXPANDED_KEY]; /* Primary key schedule (if it is acascade, it conatins multiple concatenated keys) */ 
unsigned __int8 ks2[MAX_EXPANDED_KEY]; /* Secondary key schedule (if cascade,multiple concatenated) for XTS mode. */

BOOLhiddenVolume;    // Indicates whether the volume ismounted/mountable as hidden volume

#ifndefTC_WINDOWS_BOOT 

#endif //TC_WINDOWS_BOOT

UINT64_STRUCTVolumeSize;

UINT64_STRUCTEncryptedAreaStart; 
UINT64_STRUCT EncryptedAreaLength;

uint32HeaderFlags;

}CRYPTO_INFO, *PCRYPTO_INFO;

/* 加密队列结构 */ 
typedef struct EncryptionThreadPoolWorkItemStruct 

WorkItemState State; /* 状态 */ 
EncryptionThreadPoolWorkType Type; /* 类型*/

TC_EVENTItemCompletedEvent; /* 异步完成事件 */

structEncryptionThreadPoolWorkItemStruct *FirstFragment; 
LONG OutstandingFragmentCount;

/* 工作参数 */ 
union 

   /* EncryptDataUnitsWork/DecryptDataUnitsWork 类型队列工作参数 */ 
   struct 
   { 
    PCRYPTO_INFO CryptoInfo; 
    byte *Data; 
    UINT64_STRUCT StartUnitNo; 
    TC_LARGEST_COMPILER_UINT UnitCount;

  } Encryption;

  /* DeriveKeyWork 类型队列工作参数 */ 
   struct 
   { 
    TC_EVENT *CompletionEvent; 
    LONG *CompletionFlag; 
    char *DerivedKey; 
    int IterationCount; 
    TC_EVENT *NoOutstandingWorkItemEvent; 
    LONG *OutstandingWorkItemCount; 
    char *Password; 
    int PasswordLength; 
    int Pkcs5Prf; 
    char *Salt;

  } KeyDerivation; 
};

}EncryptionThreadPoolWorkItem;

2 数据处理流程

  TrueCrypt模块启动后,创建了业务框架,其中最重要的数据处理流程(数据的加密/解密/密钥生成)。TrueCrypt模块这部分设计很巧妙,使用了半同步/半异步的设计模式,并结合了多核条件下数据同步技术。

  TrueCrypt根据CPU个数,创建了相应的线程(我们这里给叫做数据处理线程)。这些线程开始时分别选择一个工作队列,等待数据的到来。一旦有数据进入队列,根据数据的类型,进行相应的处理;处理完毕后,通知队列的状态维护线程数据处理完毕,请维护队列状态;然后自己根据游标选择下一个要处理的队列进行处理;为什么不直接选择刚处理完的队列呢?因为此时刚处理完的队列状态还没有恢复到准备阶段,为了提高处理速度,选择下一个准备好的队列,进行处理。具体请看草图:

主要的代码分析如下:

staticTC_THREAD_PROC EncryptionThreadProc (void *threadArg) 

EncryptionThreadPoolWorkItem *workItem;

while(!StopPending) 

   /* 队列是多核的共享资源,需要保护 */ 
   TC_ACQUIRE_MUTEX (&DequeueMutex);

  workItem = &WorkItemQueue[DequeuePosition++];

  /* 选择了队列,现更新游标 */ 
   if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) 
    DequeuePosition = 0;

  while (!StopPending && GetWorkItemState (workItem) != WorkItemReady) 
   { 
    /* 等待数据到来 */ 
    TC_WAIT_EVENT (WorkItemReadyEvent); 
   }

  /* 设置队列状态忙 */ 
   SetWorkItemState (workItem, WorkItemBusy);

  TC_RELEASE_MUTEX (&DequeueMutex);

  if (StopPending) 
    break;

  /* 三种队列类型 */ 
   switch (workItem->Type) 
   { 
   case DecryptDataUnitsWork: 
    DecryptDataUnitsCurrentThread (workItem->Encryption.Data,&workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount,workItem->Encryption.CryptoInfo); 
    break;

  case EncryptDataUnitsWork: 
    EncryptDataUnitsCurrentThread (workItem->Encryption.Data,&workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount,workItem->Encryption.CryptoInfo); 
    break;

  case DeriveKeyWork: 
    switch (workItem->KeyDerivation.Pkcs5Prf) 
    { 
    ….

   default:   
     TC_THROW_FATAL_EXCEPTION; 
    }

   … 
    continue;

  default: 
    TC_THROW_FATAL_EXCEPTION; 
   }

  if (workItem != workItem->FirstFragment) 
   { 
    SetWorkItemState (workItem, WorkItemFree); 
    /* 数据处理完成,通知传输线程, 取走数据*/ 
    TC_SET_EVENT (WorkItemCompletedEvent); 
   }

  if (InterlockedDecrement(&workItem->FirstFragment->OutstandingFragmentCount) == 0) 
    TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent); 
}

PsTerminateSystemThread(STATUS_SUCCESS); 
}

voidEncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data,const UINT64_STRUCT *startUnitNo, TC_LARGEST_COMPILER_UINT unitCount,PCRYPTO_INFO cryptoInfo) 

… 
/* 如果没有启动线程队列,则直接调用加密/解密算法 */ 
if (!ThreadPoolRunning || unitCount == 1) 

   switch (type) 
   { 
   case DecryptDataUnitsWork: 
    DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount,cryptoInfo); 
    break;

  case EncryptDataUnitsWork: 
    EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount,cryptoInfo); 
    break;

  default: 
    TC_THROW_FATAL_EXCEPTION; 
   }

  return; 
}

/* 把数据放入加密队列,等待加密操作完成 */ 
TC_ACQUIRE_MUTEX (&EnqueueMutex); 
firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition];

while(GetWorkItemState (firstFragmentWorkItem) != WorkItemFree) 

   TC_WAIT_EVENT (WorkItemCompletedEvent); 
}

firstFragmentWorkItem->OutstandingFragmentCount= fragmentCount;

while(fragmentCount– > 0) 

   workItem = &WorkItemQueue[EnqueuePosition++]; 
   if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) 
    EnqueuePosition = 0;

  while (GetWorkItemState (workItem) != WorkItemFree) 
   { 
    TC_WAIT_EVENT (WorkItemCompletedEvent); 
   }

  …

  SetWorkItemState (workItem, WorkItemReady); 
   TC_SET_EVENT (WorkItemReadyEvent); 
}

TC_RELEASE_MUTEX(&EnqueueMutex);

TC_WAIT_EVENT(firstFragmentWorkItem->ItemCompletedEvent);

/* 等待加密完成 */ 
SetWorkItemState (firstFragmentWorkItem, WorkItemFree); 
TC_SET_EVENT (WorkItemCompletedEvent);

/* data已经是加密后的数据 */ 
}

3 驱动设备

TrueCrypt内核会创建4种类型的设备:CDO,磁盘过滤设备,卷过滤设备和磁盘设备。其设备类型的标示在设备的扩展结构中。

在内核驱动初始化时,根据具注册表中的参数决定本驱动是否创建卷过滤或者磁盘过滤设备:DriverObject->DriverExtension->AddDevice= DriverAddDevice

创建过滤设备的接口即是DriverAddDevice:

NTSTATUSDriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) 

/* 卷过滤设备 */ 
if (VolumeClassFilterRegistered && BootArgsValid &&BootArgs.HiddenSystemPartitionStart != 0) 

   PWSTR interfaceLinks; 
   if (NT_SUCCESS (IoGetDeviceInterfaces(&GUID_DEVINTERFACE_VOLUME, pdo, DEVICE_INTERFACE_INCLUDE_NONACTIVE,&interfaceLinks))) 
   { 
    /* 找到设备的Interface*/ 
    if (interfaceLinks[0] != UNICODE_NULL) 
    {     
     ExFreePool (interfaceLinks);

    return VolumeFilterAddDevice (driverObject, pdo); 
    }

   ExFreePool (interfaceLinks); 
   } 
}

/* 磁盘过滤设备 */ 
return DriveFilterAddDevice (driverObject, pdo); 
}

NTSTATUSVolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) 

… 
/* 获取设备栈顶层设备 */ 
attachedDeviceObject = IoGetAttachedDeviceReference (pdo);

DriverMutexWait(); 
status = IoCreateDevice (driverObject, sizeof (VolumeFilterExtension), NULL,attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject); 
DriverMutexRelease();

ObDereferenceObject(attachedDeviceObject);

/* 加入设备栈 */ 
Extension->LowerDeviceObject = IoAttachDeviceToDeviceStack(filterDeviceObject, pdo); 
…;

returnstatus; 
err: 

returnstatus; 
}

DriveFilterAddDevice与VolumeFilterAddDevice 过程类同。

附录:

typedefstruct EXTENSION 

/* 设备类型 */ 
BOOL bRootDevice; /* Is this the root device ? which the user-mode apps talk to*/ 
BOOL IsVolumeDevice;    
BOOL IsDriveFilterDevice; 
BOOL IsVolumeFilterDevice;

ULONGlMagicNumber; /* To ensure the completion routine is not sending us bad IRP’s*/

intUniqueVolumeId; 
int nDosDriveNo; /* Drive number this extension is mounted against */

/* 操作参数 */ 
BOOL bShuttingDown;    /* Is the driver shutting down ? */ 
BOOL bThreadShouldQuit;   /* Instruct per device worker thread toquit */ 
PETHREAD peThread;    /* Thread handle */ 
KEVENT keCreateEvent;   /* Device creation event */ 
KSPIN_LOCK ListSpinLock; /* IRP spinlock */ 
LIST_ENTRY ListEntry;   /* IRP listentry */ 
KSEMAPHORE RequestSemaphore; /* IRP list request Semaphore */

HANDLEhDeviceFile;    /* Device handle for this device */ 
PFILE_OBJECT pfoDeviceFile; /* Device fileobject for this device */ 
PDEVICE_OBJECT pFsdDevice; /* lower level device handle */

CRYPTO_INFO*cryptoInfo; /* Cryptographic and other information for this device */

/* 磁盘属性 */ 
__int64 HostLength; 
__int64 DiskLength;    /* The length of the disk referred to bythis device */ 
__int64 NumberOfCylinders;   /* Partition info */ 
ULONG TracksPerCylinder; /* Partition info */ 
ULONG SectorsPerTrack;   /* Partition info */ 
ULONG BytesPerSector;   /* Partition info */ 
UCHAR PartitionType;   /* Partition info */ 
int HostBytesPerSector;

KEVENTkeVolumeEvent;   /* Event structure used when setting up a device */

EncryptedIoQueueQueue;

/* 设备属性 */ 
BOOL bReadOnly;     /* Is this device read-only ? */ 
BOOL bRemovable;    /* Is this device removable media ? */ 
BOOL bRawDevice;    /* Is this a raw-partition or raw-floppydevice ? */ 
BOOL bMountManager;    /* Mount manager knows about volume */

WCHARwszVolume[TC_MAX_PATH]; /* DONT change this size without also changingMOUNT_LIST_STRUCT! */

//Container file date/time (used to reset date and time of file-hosted volumesafter dismount or unsuccessful mount attempt, to preserve plausible deniabilityof hidden volumes). 
LARGE_INTEGER fileCreationTime; 
LARGE_INTEGER fileLastAccessTime; 
LARGE_INTEGER fileLastWriteTime; 
LARGE_INTEGER fileLastChangeTime; 
BOOL bTimeStampValid;

PSIDUserSid; 
BOOL SecurityClientContextValid; 
SECURITY_CLIENT_CONTEXT SecurityClientContext;

}EXTENSION, *PEXTENSION;

typedefstruct 

BOOL bRootDevice; 
BOOL IsVolumeDevice; 
BOOL IsDriveFilterDevice; 
BOOL IsVolumeFilterDevice;

PDEVICE_OBJECTDeviceObject; 
PDEVICE_OBJECT LowerDeviceObject; 
PDEVICE_OBJECT Pdo; 
int64 ConfiguredEncryptedAreaStart; 
int64 ConfiguredEncryptedAreaEnd;

uint32VolumeHeaderSaltCrc32; 
EncryptedIoQueue Queue;

BOOLBootDrive; 
BOOL VolumeHeaderPresent; 
BOOL DriveMounted;

KEVENTMountWorkItemCompletedEvent;

CRYPTO_INFO*HeaderCryptoInfo; 
BOOL HiddenSystem;

}DriveFilterExtension;

4 初始化过程总结

内核初始化阶段主要完成几个任务:

4.1 加载加密算法 
4.2 加载64个32对数据加密/解密/子密钥创建对列(半同步/半异步模式) 
4.3 根据配置创建磁盘过滤或者卷过滤设备 
4.4 创建CDO

下部分(TrueCrypt 6.2a原理及代码分析(3~5))开始分析数据处理流程。(仅好友可见或者私有保留)

这里看下EncryptedIoQueueStart的处理
//创建3个线程来处理读写。
NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue)
{
NTSTATUS status;
EncryptedIoQueueBuffer *buffer;
int i;

queue->StartPending= TRUE;
queue->ThreadExitRequested = FALSE;

queue->OutstandingIoCount= 0;
queue->IoThreadPendingRequestCount = 0;

queue->FirstPoolBuffer= NULL;
KeInitializeMutex (&queue->BufferPoolMutex, 0);

KeInitializeEvent(&queue->NoOutstandingIoEvent, SynchronizationEvent, FALSE);
KeInitializeEvent (&queue->PoolBufferFreeEvent, SynchronizationEvent,FALSE);
KeInitializeEvent (&queue->QueueResumedEvent, SynchronizationEvent,FALSE);

queue->FragmentBufferA= TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
if (!queue->FragmentBufferA)
   goto noMemory;

queue->FragmentBufferB= TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
if (!queue->FragmentBufferB)
   goto noMemory;

KeInitializeEvent(&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE);
KeInitializeEvent (&queue->FragmentBufferBFreeEvent,SynchronizationEvent, TRUE);

queue->ReadAheadBufferValid= FALSE;
queue->ReadAheadBuffer = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
if (!queue->ReadAheadBuffer)
   goto noMemory;

// Preallocatebuffers
for (i = 0; i < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; ++i)
{
   if (i < TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT &&!GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem)))
    goto noMemory;

   if(!GetPoolBuffer (queue, sizeof (EncryptedIoRequest)))
    goto noMemory;
}

for (buffer =queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer)
{
   buffer->InUse = FALSE;
}

// Main thread
InitializeListHead (&queue->MainThreadQueue);
KeInitializeSpinLock (&queue->MainThreadQueueLock);
KeInitializeEvent (&queue->MainThreadQueueNotEmptyEvent,SynchronizationEvent, FALSE);

status = TCStartThread(MainThreadProc, queue, &queue->MainThread);
if (!NT_SUCCESS (status))
   goto err;

// IO thread
InitializeListHead (&queue->IoThreadQueue);
KeInitializeSpinLock (&queue->IoThreadQueueLock);
KeInitializeEvent (&queue->IoThreadQueueNotEmptyEvent, SynchronizationEvent,FALSE);

status =TCStartThread (IoThreadProc, queue, &queue->IoThread);
if (!NT_SUCCESS (status))
{
   queue->ThreadExitRequested = TRUE;
   TCStopThread (queue->MainThread,&queue->MainThreadQueueNotEmptyEvent);
   goto err;
}

// Completion thread
InitializeListHead (&queue->CompletionThreadQueue);
KeInitializeSpinLock (&queue->CompletionThreadQueueLock);
KeInitializeEvent (&queue->CompletionThreadQueueNotEmptyEvent,SynchronizationEvent, FALSE);

status =TCStartThread (CompletionThreadProc, queue, &queue->CompletionThread);
if (!NT_SUCCESS (status))
{
   queue->ThreadExitRequested = TRUE;
   TCStopThread (queue->MainThread,&queue->MainThreadQueueNotEmptyEvent);
   TCStopThread (queue->IoThread,&queue->IoThreadQueueNotEmptyEvent);
   goto err;
}

#ifdefTC_TRACE_IO_QUEUE
GetElapsedTimeInit (&queue->LastPerformanceCounter);
#endif

queue->StopPending= FALSE;
queue->StartPending = FALSE;

Dump ("Queuestarted\n");
return STATUS_SUCCESS;

noMemory:
status = STATUS_INSUFFICIENT_RESOURCES;

err:
if (queue->FragmentBufferA)
   TCfree (queue->FragmentBufferA);
if (queue->FragmentBufferB)
   TCfree (queue->FragmentBufferB);

FreePoolBuffers(queue);

queue->StartPending= FALSE;
return status;
}

到这里顺一下流程。
收到挂载通知后,驱动生成一个设备对象
然后创建一个线程处理卷的挂载,
线程中创建了3个线程
这里以MainThreadProc为例,来看看这个线程都做了什么

static VOIDMainThreadProc (PVOID threadArg)
{
EncryptedIoQueue *queue = (EncryptedIoQueue *) threadArg;
PLIST_ENTRY listEntry;
EncryptedIoQueueItem *item;

LARGE_INTEGERfragmentOffset;
ULONG dataRemaining;
PUCHAR activeFragmentBuffer = queue->FragmentBufferA;
PUCHAR dataBuffer;
EncryptedIoRequest *request;
uint64 intersectStart;
uint32 intersectLength;

if(IsEncryptionThreadPoolRunning())
   KeSetPriorityThread (KeGetCurrentThread(), LOW_REALTIME_PRIORITY);//设置优先级为低

while(!queue->ThreadExitRequested) //没有收到退出请求
{
   if (!NT_SUCCESS (KeWaitForSingleObject(&queue->MainThreadQueueNotEmptyEvent, Executive, KernelMode, FALSE,NULL))) // EncryptedIoQueueAddIrp中设置这个事件收到读写的时候
    continue;

   while((listEntry = ExInterlockedRemoveHeadList (&queue->MainThreadQueue,&queue->MainThreadQueueLock))) // 从队列头取出一个数据
   {
    PIRP irp = CONTAINING_RECORD (listEntry, IRP,Tail.Overlay.ListEntry);
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
   
    if (queue->Suspended) //如果队列是暂停状态等待
     KeWaitForSingleObject(&queue->QueueResumedEvent, Executive, KernelMode, FALSE, NULL);

   item = GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem));
    item->Queue = queue;
    item->OriginalIrp = irp;
    item->Status = STATUS_SUCCESS;

   IoSetCancelRoutine (irp, NULL); //设置了取消例程
    if (irp->Cancel)
    {
     CompleteOriginalIrp (item, STATUS_CANCELLED, 0);
     continue;
    }

   switch (irpSp->MajorFunction)
    {
    case IRP_MJ_READ:
     item->Write = FALSE;
     item->OriginalOffset =irpSp->Parameters.Read.ByteOffset;
     item->OriginalLength =irpSp->Parameters.Read.Length;
     break;

   case IRP_MJ_WRITE:
     item->Write = TRUE;
     item->OriginalOffset =irpSp->Parameters.Write.ByteOffset;
     item->OriginalLength =irpSp->Parameters.Write.Length;
     break;

   default:
     CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER,0);
     continue;
    }

#ifdefTC_TRACE_IO_QUEUE
    item->OriginalIrpOffset = item->OriginalOffset;
#endif

    //Handle misaligned read operations to work around a bug in Windows SystemAssessment Tool which does not follow FILE_FLAG_NO_BUFFERING requirements whenbenchmarking disk devices
    if (queue->IsFilterDevice
     && !item->Write
     && item->OriginalLength > 0
     && (item->OriginalLength &(ENCRYPTION_DATA_UNIT_SIZE - 1)) == 0
     && (item->OriginalOffset.QuadPart &(ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
    {
     byte *buffer;
     ULONG alignedLength = item->OriginalLength +ENCRYPTION_DATA_UNIT_SIZE;
     LARGE_INTEGER alignedOffset;
     alignedOffset.QuadPart =item->OriginalOffset.QuadPart & ~((LONGLONG) ENCRYPTION_DATA_UNIT_SIZE -1);

    buffer = TCalloc (alignedLength);
     if (!buffer)
     {
      CompleteOriginalIrp (item,STATUS_INSUFFICIENT_RESOURCES, 0);
      continue;
     }

    item->Status = TCReadDevice (queue->LowerDeviceObject, buffer,alignedOffset, alignedLength);

    if (NT_SUCCESS (item->Status))
     {
      UINT64_STRUCT dataUnit;

     dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe (irp->MdlAddress,HighPagePriority);
      if (!dataBuffer)
      {
       TCfree (buffer);
       CompleteOriginalIrp (item,STATUS_INSUFFICIENT_RESOURCES, 0);
       continue;
      }

     if (queue->EncryptedAreaStart != -1 && queue->EncryptedAreaEnd !=-1)
      {
       GetIntersection (alignedOffset.QuadPart,alignedLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd,&intersectStart, &intersectLength);
       if (intersectLength > 0)
       {
        dataUnit.Value = intersectStart /ENCRYPTION_DATA_UNIT_SIZE;
        DecryptDataUnits (buffer +(intersectStart - alignedOffset.QuadPart), &dataUnit, intersectLength /ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo);
       }
      }

     memcpy (dataBuffer, buffer + (item->OriginalOffset.LowPart &(ENCRYPTION_DATA_UNIT_SIZE - 1)), item->OriginalLength);
     }

    TCfree (buffer);
     CompleteOriginalIrp (item, item->Status, NT_SUCCESS(item->Status) ? item->OriginalLength : 0);
     continue;
    }

    //Validate offset and length
    if (item->OriginalLength == 0
     || (item->OriginalLength &(ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0
     || (item->OriginalOffset.QuadPart &(ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0
     || (!queue->IsFilterDevice &&item->OriginalOffset.QuadPart + item->OriginalLength >queue->VirtualDeviceLength))
    {
     CompleteOriginalIrp (item, STATUS_INVALID_PARAMETER,0);
     continue;
    }

#ifdefTC_TRACE_IO_QUEUE
    Dump ("Q %I64d [%I64d] %c len=%d\n",item->OriginalOffset.QuadPart, GetElapsedTime (&queue->LastPerformanceCounter),item->Write ? 'W' : 'R', item->OriginalLength);
#endif

    if(!queue->IsFilterDevice)
    {
     // 校准偏移
     if (queue->CryptoInfo->hiddenVolume)
      item->OriginalOffset.QuadPart +=queue->CryptoInfo->hiddenVolumeOffset;
     else
      item->OriginalOffset.QuadPart +=queue->CryptoInfo->volDataAreaOffset;

    // Hidden volume protection
     if (item->Write &&queue->CryptoInfo->bProtectHiddenVolume)
     {
      // If there has already been a write operationdenied in order to protect the
      // hidden volume (since the volume mount time)
      if(queue->CryptoInfo->bHiddenVolProtectionAction) 
      {
       // Do not allow writing to this volumeanymore. This is to fake a complete volume
       // or system failure (otherwise certainkinds of inconsistency within the file
       // system could indicate that this volumehas used hidden volume protection).
       CompleteOriginalIrp (item,STATUS_INVALID_PARAMETER, 0);
       continue;
      }

     // Verify that no byte is going to be written to the hidden volume area
      if (RegionsOverlap ((unsigned __int64)item->OriginalOffset.QuadPart,
       (unsigned __int64)item->OriginalOffset.QuadPart + item->OriginalLength - 1,
      queue->CryptoInfo->hiddenVolumeOffset,
       (unsigned __int64)queue->CryptoInfo->hiddenVolumeOffset +queue->CryptoInfo->hiddenVolumeProtectedSize - 1))
      {
       Dump ("Hidden volume protectiontriggered: write %I64d-%I64d (protected %I64d-%I64d)\n",item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart +item->OriginalLength - 1, queue->CryptoInfo->hiddenVolumeOffset,queue->CryptoInfo->hiddenVolumeOffset +queue->CryptoInfo->hiddenVolumeProtectedSize - 1);
      queue->CryptoInfo->bHiddenVolProtectionAction = TRUE;

      // Deny this write operation to prevent the hidden volume from beingoverwritten
       CompleteOriginalIrp (item,STATUS_INVALID_PARAMETER, 0);
       continue;
      }
     }
    }
    else if (item->Write
     && RegionsOverlap(item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart +item->OriginalLength - 1, TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET,TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET + TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE -1))
    {
     // Prevent inappropriately designed software fromdamaging important data that may be out of sync with the backup on the RescueDisk (such as the end of the encrypted area).
     Dump ("Preventing write to the system encryptionkey data area\n");
     CompleteOriginalIrp (item,STATUS_MEDIA_WRITE_PROTECTED, 0);
     continue;
    }
    else if (item->Write && IsHiddenSystemRunning()
     && (RegionsOverlap(item->OriginalOffset.QuadPart, item->OriginalOffset.QuadPart +item->OriginalLength - 1, SECTOR_SIZE, TC_BOOT_LOADER_AREA_SECTOR_COUNT *SECTOR_SIZE - 1)
     || RegionsOverlap (item->OriginalOffset.QuadPart,item->OriginalOffset.QuadPart + item->OriginalLength - 1,GetBootDriveLength(), _I64_MAX)))
    {
     Dump ("Preventing write to boot loader or hostprotected area\n");
     CompleteOriginalIrp (item, STATUS_MEDIA_WRITE_PROTECTED,0);
     continue;
    }
//前几个条件都进不去,直接到这里
    dataBuffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, HighPagePriority);

    if(dataBuffer == NULL)
    {
     CompleteOriginalIrp (item,STATUS_INSUFFICIENT_RESOURCES, 0);
     continue;
    }

    //Divide data block to fragments to enable efficient overlapping of encryptionand IO operations
    //分割数据块成几个部分,以便更快的加密和io
    dataRemaining = item->OriginalLength;
    fragmentOffset = item->OriginalOffset;

   while (dataRemaining > 0)
    {
     BOOL isLastFragment = dataRemaining <=TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; //256*1024
    
     ULONG dataFragmentLength = isLastFragment ?dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; //如果大于256*1024 就用256*1024
分成几块操作
     activeFragmentBuffer = (activeFragmentBuffer ==queue->FragmentBufferA ? queue->FragmentBufferB :queue->FragmentBufferA);

    InterlockedIncrement (&queue->IoThreadPendingRequestCount);

    // Create IO request
     request = GetPoolBuffer (queue, sizeof(EncryptedIoRequest));
     request->Item = item;
     request->CompleteOriginalIrp = isLastFragment;
     request->Offset = fragmentOffset;
     request->Data = activeFragmentBuffer;
     request->OrigDataBufferFragment = dataBuffer;
     request->Length = dataFragmentLength;

    if (queue->IsFilterDevice)
     {
      if (queue->EncryptedAreaStart == -1 ||queue->EncryptedAreaEnd == -1)
      {
       request->EncryptedLength = 0;
      }
      else
      {
       // Get intersection of data fragment withencrypted area
       GetIntersection (fragmentOffset.QuadPart,dataFragmentLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd,&intersectStart, &intersectLength);

      request->EncryptedOffset = intersectStart - fragmentOffset.QuadPart;
       request->EncryptedLength =intersectLength;
      }
     }
     else
     {
      request->EncryptedOffset = 0;
      request->EncryptedLength =dataFragmentLength;
     }
     //等待queue->FragmentBufferAFreeEvent被设置 在IoThreadProc中被设置
     AcquireFragmentBuffer (queue, activeFragmentBuffer);

    if (item->Write)
     {
      // Encrypt data 加密数据部分
      memcpy (activeFragmentBuffer, dataBuffer,dataFragmentLength);

     if (request->EncryptedLength > 0)
      {
       UINT64_STRUCT dataUnit;
       ASSERT (request->EncryptedOffset +request->EncryptedLength <= request->Offset.QuadPart +request->Length);

      dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) /ENCRYPTION_DATA_UNIT_SIZE;

      if (queue->CryptoInfo->bPartitionInInactiveSysEncScope)
        dataUnit.Value +=queue->CryptoInfo->FirstDataUnitNo.Value;
       else if (queue->RemapEncryptedArea)
        dataUnit.Value +=queue->RemappedAreaDataUnitOffset;
        
       EncryptDataUnits (activeFragmentBuffer +request->EncryptedOffset, &dataUnit, request->EncryptedLength /ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo);
/*
void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo,uint32 nbrUnits, PCRYPTO_INFO ci)
#ifndef TC_WINDOWS_BOOT
{
EncryptionThreadPoolDoWork (EncryptDataUnitsWork, buf, structUnitNo, nbrUnits,ci);
}
*/
      }
     }

    // Queue IO request
     ExInterlockedInsertTailList(&queue->IoThreadQueue, &request->ListEntry,&queue->IoThreadQueueLock);
     KeSetEvent (&queue->IoThreadQueueNotEmptyEvent,IO_DISK_INCREMENT, FALSE);

    if (isLastFragment)
      break;

    dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
     dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
     fragmentOffset.QuadPart +=TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
    }
   }
}

PsTerminateSystemThread(STATUS_SUCCESS);
}

//如果是加密的话就用到了EncryptionThreadPoolDoWork(EncryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci);
看下这个函数实现,这里写的很精髓
void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data,const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo)
{
uint32 fragmentCount;
uint32 unitsPerFragment;
uint32 remainder;

byte *fragmentData;
uint64 fragmentStartUnitNo;

EncryptionThreadPoolWorkItem*workItem;
EncryptionThreadPoolWorkItem *firstFragmentWorkItem;
//加密的长度除512
if (unitCount == 0)
   return;

if (!ThreadPoolRunning || unitCount == 1) //没有启用加密解密线程就直接做加密解密了
{
   switch (type)
   {
   case DecryptDataUnitsWork:
    DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount,cryptoInfo);
    break;

   caseEncryptDataUnitsWork:
    EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount,cryptoInfo);
    break;

   default:
    TC_THROW_FATAL_EXCEPTION;
   }

   return;
}

if (unitCount <=ThreadCount)
{
   fragmentCount = unitCount;
   unitsPerFragment = 1;
   remainder = 0;
}
else
{
   /* Note that it is not efficient to divide the data into fragmentssmaller than a few hundred bytes.
   The reason is that the overhead associated with thread handlingwould in most cases make a multi-threaded 
   process actually slower than a single-threaded process. */

  fragmentCount = ThreadCount;
   unitsPerFragment = unitCount / ThreadCount;
   remainder = unitCount % ThreadCount;

   if (remainder> 0)
    ++unitsPerFragment;
}

fragmentData = data;
fragmentStartUnitNo = startUnitNo->Value;

TC_ACQUIRE_MUTEX(&EnqueueMutex); //多线程同步
firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition];

while(GetWorkItemState (firstFragmentWorkItem) != WorkItemFree)
{
   TC_WAIT_EVENT (WorkItemCompletedEvent);
}

firstFragmentWorkItem->OutstandingFragmentCount= fragmentCount;
//这里假设fragmentCount ==1 unitCount== 3ThreadCount==2 unitsPerFragment==1
while (fragmentCount-- > 0) 
{
   workItem = &WorkItemQueue[EnqueuePosition++];
   if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) //大于等于最大线程数的2倍
    EnqueuePosition = 0;

   while(GetWorkItemState (workItem) != WorkItemFree)
   {
    TC_WAIT_EVENT (WorkItemCompletedEvent);
   }

  workItem->Type = type;
   workItem->FirstFragment = firstFragmentWorkItem;

  workItem->Encryption.CryptoInfo = cryptoInfo;
   workItem->Encryption.Data = fragmentData;
   workItem->Encryption.UnitCount = unitsPerFragment;
   workItem->Encryption.StartUnitNo.Value = fragmentStartUnitNo;

   fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE;
   fragmentStartUnitNo += unitsPerFragment;

   if(remainder > 0 && --remainder == 0)
    --unitsPerFragment;

  SetWorkItemState (workItem, WorkItemReady);
   TC_SET_EVENT (WorkItemReadyEvent);
}

TC_RELEASE_MUTEX(&EnqueueMutex);

TC_WAIT_EVENT(firstFragmentWorkItem->ItemCompletedEvent);
SetWorkItemState (firstFragmentWorkItem, WorkItemFree);
TC_SET_EVENT (WorkItemCompletedEvent);
}
这里把加密解密放入队列后之前驱动入口函数根据cpu个数开的EncryptionThreadProc线程就派上用场了
简单看看函数实现
//不断去工作项中取出信息
static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
{
EncryptionThreadPoolWorkItem *workItem;

while (!StopPending)
{
   TC_ACQUIRE_MUTEX (&DequeueMutex); //分配一个快速互斥体。多线程同步

   workItem= &WorkItemQueue[DequeuePosition++];

   if(DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE)
    DequeuePosition = 0;

   while(!StopPending && GetWorkItemState (workItem) != WorkItemReady)
   {
    TC_WAIT_EVENT (WorkItemReadyEvent);
   }

  SetWorkItemState (workItem, WorkItemBusy);

  TC_RELEASE_MUTEX (&DequeueMutex); //释放这个快速互斥体

   if(StopPending)
    break;

   switch(workItem->Type)
   {
   case DecryptDataUnitsWork:
    DecryptDataUnitsCurrentThread (workItem->Encryption.Data,&workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount,workItem->Encryption.CryptoInfo);
    break;

   caseEncryptDataUnitsWork:
    EncryptDataUnitsCurrentThread (workItem->Encryption.Data,&workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount,workItem->Encryption.CryptoInfo);
    break;

   caseDeriveKeyWork:
    switch (workItem->KeyDerivation.Pkcs5Prf)
    {
    case RIPEMD160:
     derive_key_ripemd160(workItem->KeyDerivation.Password,workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt,PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount,workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

   case SHA512:
     derive_key_sha512(workItem->KeyDerivation.Password,workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt,PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount,workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

   case WHIRLPOOL:
     derive_key_whirlpool(workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength,workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount,workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

   case SHA1:
     derive_key_sha1 (workItem->KeyDerivation.Password,workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt,PKCS5_SALT_SIZE,
      workItem->KeyDerivation.IterationCount,workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
     break;

   default:  
     TC_THROW_FATAL_EXCEPTION;
    }

   InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE);
    TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent);
   
    if (InterlockedDecrement(workItem->KeyDerivation.OutstandingWorkItemCount) == 0)
     TC_SET_EVENT (*workItem->KeyDerivation.NoOutstandingWorkItemEvent);

   SetWorkItemState (workItem, WorkItemFree);
    TC_SET_EVENT (WorkItemCompletedEvent);
    continue;

   default:
    TC_THROW_FATAL_EXCEPTION;
   }

   if(workItem != workItem->FirstFragment)
   {
    SetWorkItemState (workItem, WorkItemFree);
    TC_SET_EVENT (WorkItemCompletedEvent);
   }

   if(InterlockedDecrement(&workItem->FirstFragment->OutstandingFragmentCount) == 0)
    TC_SET_EVENT(workItem->FirstFragment->ItemCompletedEvent);
}

#ifdef DEVICE_DRIVER
PsTerminateSystemThread (STATUS_SUCCESS);
#else
_endthreadex (0);
    return 0;
#endif
}

整个流程大体就这样了,多线程的处理十分值得学习啊

 

1 对于卷过滤设备,基本没有过多的操作,这里仅是关注设备读写属性的要求。

英文注释很明了,这里就不再过多解释。

static NTSTATUS DispatchControl (PDEVICE_OBJECT DeviceObject, PIRPIrp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
{
NTSTATUS status;

if (IsHiddenSystemRunning())
{
   switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
   {
   case IOCTL_DISK_IS_WRITABLE:

    if (SystemVolumePdo == NULL)
    {
     // The first volume checked for being writable is thesystem volume
     SystemVolumePdo = Extension->Pdo;
     Dump ("System volume pdo=%p\n",SystemVolumePdo);
    }
    else if (Extension->Pdo != SystemVolumePdo)
    {
     // Volumes other than the system volume must bepresented as read-only
     ++HiddenSysLeakProtectionCount;
     return TCCompleteDiskIrp (Irp,STATUS_MEDIA_WRITE_PROTECTED, 0);
    }

    return TCCompleteDiskIrp (Irp, STATUS_SUCCESS,0);

   case TC_IOCTL_DISK_IS_WRITABLE:
    Dump ("TC_IOCTL_DISK_IS_WRITABLE pdo=%p\n",Extension->Pdo);

    if (!ProbingHostDeviceForWrite)
     break;

    // Probe the real state of the device as theuser is mounting a TrueCrypt volume.

    // Volumefilter may be attached to a merged drive+volume PDO. First test ifTC_IOCTL_DISK_IS_WRITABLE works for the underlying device.
    status = SendDeviceIoControlRequest(Extension->LowerDeviceObject, TC_IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0);
    if (NT_SUCCESS (status) || status ==STATUS_MEDIA_WRITE_PROTECTED)
     return TCCompleteDiskIrp (Irp, status, 0);

    status = SendDeviceIoControlRequest(Extension->LowerDeviceObject, IOCTL_DISK_IS_WRITABLE,NULL, 0, NULL, 0);
    return TCCompleteDiskIrp (Irp, status, 0);
   }
}

return PassIrp (Extension->LowerDeviceObject, Irp);
}

2 加密系统盘分析(SetupThreadProc)

 类似资料: