驅動中通過設備鏈接名取得磁盤符號的方法

主要思路:
從驅動層設備鏈接名獲取DosName很難做到通用,但DosName->DeviceSymblinkName可以做到通用,這樣的話就有一種思路:
查詢一個設備鏈接名對應的磁盤盤符的方法:
獲取從A到Z的盤的設備鏈接名,如果有一個和傳入的參數(設備鏈接名)完全匹配,那麼其對應的盤符就是該設備鏈接名對應的盤符。

GetSymbolicLink(
IN PUNICODE_STRING SymbolicLinkName,
OUT PUNICODE_STRING LinkTarget
)

/*++
Routine Description:
This routine returns the target of the symbolic link name.
Arguments:
SymbolicLinkName - Supplies the symbolic link name.
LinkTarget - Returns the link target.
Return Value:
NTSTATUS
--*/

{
OBJECT_ATTRIBUTES oa;
NTSTATUS status;
HANDLE h;

InitializeObjectAttributes(&oa, SymbolicLinkName, OBJ_CASE_INSENSITIVE,0, 0);

status = ZwOpenSymbolicLinkObject(&h, GENERIC_READ, &oa);

if (!NT_SUCCESS(status))
{
return status;
}

LinkTarget->MaximumLength = 200*sizeof(WCHAR);
LinkTarget->Length = 0;
LinkTarget->Buffer = ExAllocatePool(PagedPool, LinkTarget->MaximumLength);

if (!LinkTarget->Buffer)
{
ZwClose(h);
return STATUS_INSUFFICIENT_RESOURCES;
}

RtlZeroMemory(LinkTarget->Buffer, LinkTarget->MaximumLength);

status = ZwQuerySymbolicLinkObject(h, LinkTarget, NULL);
ZwClose(h);

if (!NT_SUCCESS(status))
{
ExFreePool(LinkTarget->Buffer);
}

return status;
}

NTSTATUS QuerySymbolicLink(
IN PUNICODE_STRING SymbolicLinkName,
OUT PUNICODE_STRING LinkTarget
)                                  
{
OBJECT_ATTRIBUTES oa;
NTSTATUS status;
HANDLE handle;

InitializeObjectAttributes(&oa, SymbolicLinkName,
OBJ_CASE_INSENSITIVE,
0, 0);

status = ZwOpenSymbolicLinkObject(&handle, GENERIC_READ, &oa);
if (!NT_SUCCESS(status))
{
return status;
}

LinkTarget->MaximumLength = 200*sizeof(WCHAR);
LinkTarget->Length = 0;
LinkTarget->Buffer = ExAllocatePool(PagedPool, LinkTarget->MaximumLength);
if (!LinkTarget->Buffer)
{
ZwClose(handle);
return STATUS_INSUFFICIENT_RESOURCES;
}

RtlZeroMemory(LinkTarget->Buffer, LinkTarget->MaximumLength);

status = ZwQuerySymbolicLinkObject(handle, LinkTarget, NULL);
ZwClose(handle);

if (!NT_SUCCESS(status))
{
ExFreePool(LinkTarget->Buffer);
}

return status;
}

NTSTATUS
RtlVolumeDeviceToDosName(
IN PUNICODE_STRING DeviceName,
OUT PUNICODE_STRING DosName
)

/*++

Routine Description:

This routine returns a valid DOS path for the given device object.
This caller of this routine must call ExFreePool on DosName->Buffer
when it is no longer needed.

Arguments:

VolumeDeviceObject - Supplies the volume device object.
DosName - Returns the DOS name for the volume
Return Value:

NTSTATUS

--*/

{
NTSTATUS status;
UNICODE_STRING driveLetterName;
WCHAR          driveLetterNameBuf[128];
WCHAR c;
WCHAR DriLetter[3];
UNICODE_STRING linkTarget;

for (c = L'A'; c <= L'Z'; c++)
{
RtlInitEmptyUnicodeString(&driveLetterName,driveLetterNameBuf,sizeof(driveLetterNameBuf));
RtlAppendUnicodeToString(&driveLetterName, L"\\??\\ ");
DriLetter[0] = c;
DriLetter[1] = L':';
DriLetter[2] = 0;
RtlAppendUnicodeToString(&driveLetterName,DriLetter);

status = QuerySymbolicLink(&driveLetterName, &linkTarget);
if (!NT_SUCCESS(status))
{
continue;
}

if (RtlEqualUnicodeString(&linkTarget, DeviceName, TRUE))
{
ExFreePool(linkTarget.Buffer);
break;
}

ExFreePool(linkTarget.Buffer);
}

if (c <= L'Z')
{
DosName->Buffer = ExAllocatePool(PagedPool, 3*sizeof(WCHAR));
if (!DosName->Buffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}

DosName->MaximumLength = 6;
DosName->Length   = 4;
*DosName->Buffer  = c;
*(DosName->Buffer+ 1) = ':';
*(DosName->Buffer+ 2) = 0;

return STATUS_SUCCESS;
}

return status;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章