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;
}