获取卷信息
使用内核链表和快速互斥体。
快速互斥体不支持递归获取,也就是不允许自己线程重复获取。
一般互斥体只其他线程,自己线程可以多次取得。
1 2 3 4 5 6 7 8 9 10 11
| FAST_MUTEX __VolumeInfoLock; LIST_ENTRY __VolumeInfoList;
void InitializeVolumeInfo() { ExInitializeFastMutex(&__VolumeInfoLock); InitializeListHead(&__VolumeInfoList);
EnumVolumeInfo(); }
|
枚举卷信息
从A盘开始,将路径转为UnicodeString,再转到OA,调用ZwCreateFile获取卷句柄,调用ZwQueryObject获取对象信息,插入数据结构中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| void EnumVolumeInfo() { WCHAR DosDevice[] = L"\\DosDevices\\X:"; UNICODE_STRING v1; WCHAR i; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE VolumeHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock;
OBJECT_NAME_INFORMATION* ObjectNameInfo = NULL; ULONG ObjectNameInfoLength = BUFFER_SIZE_MAX;
FreeVolumeInfo();
ObjectNameInfo = (OBJECT_NAME_INFORMATION*)AllocateBufferFromLookAsideList(); if (ObjectNameInfo == NULL) return;
for (i = 0; i < 26; i++) { DosDevice[12] = L'A' + i;
RtlInitUnicodeString(&v1, DosDevice);
InitializeObjectAttributes(&ObjectAttributes, &v1, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwCreateFile( &VolumeHandle, SYNCHRONIZE | FILE_ANY_ACCESS, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, NULL, 0);
if (NT_SUCCESS(Status) == FALSE) continue;
ObjectNameInfoLength = BUFFER_SIZE_MAX; Status = ZwQueryObject(VolumeHandle, 1, ObjectNameInfo, ObjectNameInfoLength, &ObjectNameInfoLength); if (NT_SUCCESS(Status) == TRUE) AddVolumeInfo(VolumeHandle, L'A' + i, &ObjectNameInfo->Name);
ZwClose(VolumeHandle); }
if (ObjectNameInfo != NULL) FreeBufferToLookAsideList(ObjectNameInfo); }
|
解析卷信息
ObReferenceObjectByHandle从句柄到对象,FileObject->DeviceObject->Vpb由文件对象获取Vpb,Vpb->DeviceObject获取Vpb对象,判断是否存在。
动态申请VOLUME_INFO结构,将各种信息放入,插入链表中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| void AddVolumeInfo( HANDLE VolumeHandle, WCHAR VolumeName, UNICODE_STRING* DeviceName) { VOLUME_INFO* v5 = NULL; FILE_OBJECT* FileObject = NULL; PVPB Vpb = NULL; DEVICE_OBJECT* VpbDeviceObject = NULL;
ULONG v7 = sizeof(VOLUME_INFO) + (DeviceName->Length + 1) * sizeof(WCHAR);
NTSTATUS Status = ObReferenceObjectByHandle(VolumeHandle, 0, 0, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { return; }
if (!FileObject || !FileObject->DeviceObject || !FileObject->DeviceObject->Vpb) { goto Exit; }
Vpb = FileObject->DeviceObject->Vpb; VpbDeviceObject = Vpb->DeviceObject; if (!VpbDeviceObject) { goto Exit; }
v5 = (VOLUME_INFO*)AllocateBuffer(v7); if (v5 == NULL) { goto Exit; } v5->DeviceObject = FileObject->DeviceObject; v5->VpbDeviceObject = VpbDeviceObject; v5->VolumeName = VolumeName; memcpy(&v5->DeviceName[0], DeviceName->Buffer, DeviceName->Length); v5->Length = DeviceName->Length / sizeof(WCHAR);
ExAcquireFastMutex(&__VolumeInfoLock); InsertTailList(&__VolumeInfoList, &v5->ListEntry);
ExReleaseFastMutex(&__VolumeInfoLock); Exit: ObDereferenceObject(FileObject); return; }
|
释放卷信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| VOID FreeVolumeInfo() { VOLUME_INFO* v5 = NULL; LIST_ENTRY* v1 = NULL;
ExAcquireFastMutex(&__VolumeInfoLock);
if (IsListEmpty(&__VolumeInfoList) == TRUE) goto Exit;
while (IsListEmpty(&__VolumeInfoList) == FALSE) { v1 = RemoveHeadList(&__VolumeInfoList); if (v1 == NULL) continue;
v5 = CONTAINING_RECORD(v1, VOLUME_INFO, ListEntry); if (v5 == NULL) continue;
FreeBuffer(v5); }
Exit: InitializeListHead(&__VolumeInfoList); ExReleaseFastMutex(&__VolumeInfoLock); }
|