hellfirehj 发表于 2017-6-1 13:33:42

设备名与链接名的转换

MyQueryDosDeviceW从ReactOS的源码里拷贝的
兼容R0/R3
DWORD
WINAPI
MyQueryDosDeviceW(
                                  LPCWSTR lpDeviceName,
                                  LPWSTR lpTargetPath,
                                  DWORD ucchMax
                                  )
{
      POBJECT_DIRECTORY_INFORMATION DirInfo;
      OBJECT_ATTRIBUTES ObjectAttributes;
      UNICODE_STRING UnicodeString;
      HANDLE DirectoryHandle;
      HANDLE DeviceHandle;
      ULONG ReturnLength;
      ULONG NameLength;
      ULONG Length;
      ULONG Context;
      BOOLEAN RestartScan;
      NTSTATUS Status;
      UCHAR Buffer;
      PWSTR Ptr;

      /* Open the '\??' directory */
      RtlInitUnicodeString (&UnicodeString,
                L"\\??");
      InitializeObjectAttributes (&ObjectAttributes,
                &UnicodeString,
                OBJ_CASE_INSENSITIVE,
                NULL,
                NULL);
      Status = NtOpenDirectoryObject (&DirectoryHandle,
                DIRECTORY_QUERY,
                &ObjectAttributes);
      if (!NT_SUCCESS (Status))
      {
                return 0;
      }

      Length = 0;

      if (lpDeviceName != NULL)
      {
                /* Open the lpDeviceName link object */
                RtlInitUnicodeString (&UnicodeString,
                        (PWSTR)lpDeviceName);
                InitializeObjectAttributes (&ObjectAttributes,
                        &UnicodeString,
                        OBJ_CASE_INSENSITIVE,
                        DirectoryHandle,
                        NULL);
                Status = NtOpenSymbolicLinkObject (&DeviceHandle,
                        GENERIC_READ,
                        &ObjectAttributes);
                if (!NT_SUCCESS (Status))
                {
                        pfnNtClose (DirectoryHandle);
                        return 0;
                }

                /* Query link target */
                UnicodeString.Length = 0;
                UnicodeString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR);
                UnicodeString.Buffer = lpTargetPath;

                ReturnLength = 0;
                Status = NtQuerySymbolicLinkObject (DeviceHandle,
                        &UnicodeString,
                        &ReturnLength);
                pfnNtClose (DeviceHandle);
                pfnNtClose (DirectoryHandle);
                if (!NT_SUCCESS (Status))
                {
                        return 0;
                }

                Length = UnicodeString.Length / sizeof(WCHAR);
                if (Length < ucchMax)
                {
                        /* Append null-charcter */
                        lpTargetPath = UNICODE_NULL;
                        Length++;
                }
                else
                {
                        return 0;
                }
      }
      else
      {
                RestartScan = TRUE;
                Context = 0;
                Ptr = lpTargetPath;
                DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;

                while (TRUE)
                {
                        Status = NtQueryDirectoryObject (DirectoryHandle,
                              Buffer,
                              sizeof (Buffer),
                              TRUE,
                              RestartScan,
                              &Context,
                              &ReturnLength);
                        if (!NT_SUCCESS(Status))
                        {
                              if (Status == STATUS_NO_MORE_ENTRIES)
                              {
                                        /* Terminate the buffer */
                                        *Ptr = UNICODE_NULL;
                                        Length++;

                                        Status = STATUS_SUCCESS;
                              }
                              else
                              {
                                        Length = 0;
                              }
                              break;
                        }

                        if (!wcscmp (DirInfo->TypeName.Buffer, L"SymbolicLink"))
                        {
                              NameLength = DirInfo->Name.Length / sizeof(WCHAR);
                              if (Length + NameLength + 1 >= ucchMax)
                              {
                                        Length = 0;
                                        break;
                              }

                              memcpy (Ptr,
                                        DirInfo->Name.Buffer,
                                        DirInfo->Name.Length);
                              Ptr += NameLength;
                              Length += NameLength;
                              *Ptr = UNICODE_NULL;
                              Ptr++;
                              Length++;
                        }

                        RestartScan = FALSE;
                }

                pfnNtClose (DirectoryHandle);
      }

      return Length;
}
TA实现的:
BOOLEAN NtPathToDosPathW(WCHAR *FullNtPath, WCHAR *FullDosPath)
{
      WCHAR DosDevice= {0};       //dos设备名最大长度为4
      WCHAR NtPath= {0};       //nt设备名最大长度为64
      WCHAR *RetStr=NULL;
      size_t NtPathLen=0;
      if (!FullNtPath || !FullDosPath)
      {
                return FALSE;
      }
      for(short i=65; i<26+65; i++)
      {
                DosDevice=i;
                DosDevice=L':';
                if(QueryDosDeviceW(DosDevice,NtPath,64))
                {
                        if (NtPath)
                        {
                              NtPathLen=wcslen(NtPath);
                              if (!wcsnicmp(NtPath,FullNtPath,NtPathLen))
                              {
                                        wcscpy(FullDosPath,DosDevice);
                                        wcscat(FullDosPath,FullNtPath+NtPathLen);
                                        return TRUE;
                              }
                        }
                }
      }
      return FALSE;
}

BOOLEAN DosPathToNtPathW(WCHAR *FullDosPath, WCHAR *FullNtPath)
{
      WCHAR DosDevice= {0};       //dos设备名最大长度为4
      WCHAR NtPath= {0};       //nt设备名最大长度为64
      WCHAR *RetStr=NULL;
      size_t NtPathLen=0;
      if (!FullNtPath || !FullDosPath)
      {
                return FALSE;
      }
      DosDevice=FullDosPath;
      DosDevice=L':';
      if(QueryDosDeviceW(DosDevice,NtPath,64))
      {
                if (NtPath)
                {
                        wcscpy(FullNtPath,NtPath);
                        wcscat(FullNtPath,FullDosPath+2);
                        return TRUE;
                }
      }
      return FALSE;
}

BOOLEAN NtPathToDosPathA(CHAR *FullNtPath, CHAR *FullDosPath)
{
      CHAR DosDevice= {0};       //dos设备名最大长度为4
      CHAR NtPath= {0};       //nt设备名最大长度为64
      CHAR *RetStr=NULL;
      size_t NtPathLen=0;
      if (!FullNtPath || !FullDosPath)
      {
                return FALSE;
      }
      for(short i=65; i<26+65; i++)
      {
                DosDevice=i;
                DosDevice=L':';
                if(QueryDosDeviceA(DosDevice,NtPath,64))
                {
                        if (NtPath)
                        {
                              NtPathLen=strlen(NtPath);
                              if (!strnicmp(NtPath,FullNtPath,NtPathLen))
                              {
                                        strcpy(FullDosPath,DosDevice);
                                        strcat(FullDosPath,FullNtPath+NtPathLen);
                                        return TRUE;
                              }
                        }
                }
      }
      return FALSE;
}

BOOLEAN DosPathToNtPathA(CHAR *FullDosPath, CHAR *FullNtPath)
{
      CHAR DosDevice= {0};       //dos设备名最大长度为4
      CHAR NtPath= {0};       //nt设备名最大长度为64
      CHAR *RetStr=NULL;
      size_t NtPathLen=0;
      if (!FullNtPath || !FullDosPath)
      {
                return FALSE;
      }
      DosDevice=FullDosPath;
      DosDevice=L':';
      if(QueryDosDeviceA(DosDevice,NtPath,64))
      {
                if (NtPath)
                {
                        strcpy(FullNtPath,NtPath);
                        strcat(FullNtPath,FullDosPath+2);
                        return TRUE;
                }
      }
      return FALSE;
}

void test()
{
      WCHAR dspW1[]=L"c:\\windows\\system32\\config\\sam",dspW2={0};
      WCHAR ntpW= {0};
      DosPathToNtPathW(dspW1,ntpW);
      printf("%S\n",ntpW);
      NtPathToDosPathW(ntpW,dspW2);
      printf("%S\n",dspW2);
      //
      CHAR dspA1[]="c:\\windows\\system32\\config\\sam",dspA2={0};
      CHAR ntpA= {0};
      DosPathToNtPathA(dspA1,ntpA);
      printf("%s\n",ntpA);
      NtPathToDosPathA(ntpA,dspA2);
      printf("%s\n",dspA2);
}


只能用于R0MF实现的:
#include <ntddk.h>
#include <windef.h>
#include <ntstrsafe.h>

//输入\\??\\c:-->\\device\\\harddiskvolume1
//LinkTarget.Buffer注意要释放

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

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

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

        LinkTarget->MaximumLength = MAX_PATH*sizeof(WCHAR);
        LinkTarget->Length = 0;
        LinkTarget->Buffer = ExAllocatePoolWithTag(PagedPool, LinkTarget->MaximumLength,'SOD');
        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;
}

//输入\\Device\\harddiskvolume1
//输出C:
//DosName.Buffer的内存记得释放

NTSTATUS
MyRtlVolumeDeviceToDosName(
                                                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                                        = 0;
        UNICODE_STRING                        driveLetterName                        = {0};
        WCHAR                                        driveLetterNameBuf = {0};
        WCHAR                                        c                                                = L'\0';
        WCHAR                                        DriLetter                        = {0};
        UNICODE_STRING                        linkTarget                                = {0};

        for (c = L'A'; c <= L'Z'; c++)
        {
                RtlInitEmptyUnicodeString(&driveLetterName,driveLetterNameBuf,sizeof(driveLetterNameBuf));
                RtlAppendUnicodeToString(&driveLetterName, L"\\??\\");
                DriLetter = c;
                DriLetter = L':';
                DriLetter = 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 = ExAllocatePoolWithTag(PagedPool, 3*sizeof(WCHAR), 'SOD');
                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;
}

//c:\\windows\\hi.txt<--\\device\\harddiskvolume1\\windows\\hi.txt
BOOL NTAPI GetNTLinkName(WCHAR *wszNTName, WCHAR *wszFileName)
{
        UNICODE_STRING                ustrFileName = {0};
        UNICODE_STRING                ustrDosName = {0};
        UNICODE_STRING                ustrDeviceName = {0};

        WCHAR                                *pPath = NULL;
        ULONG                                i = 0;
        ULONG                                ulSepNum = 0;


        if (wszFileName == NULL ||
                wszNTName == NULL ||
                _wcsnicmp(wszNTName, L"\\device\\harddiskvolume", wcslen(L"\\device\\harddiskvolume"))!=0)
        {
                return FALSE;
        }

        ustrFileName.Buffer = wszFileName;
        ustrFileName.Length = 0;
        ustrFileName.MaximumLength = sizeof(WCHAR)*MAX_PATH;

        while(wszNTName!=L'\0')
        {

                if (wszNTName == L'\0')
                {
                        break;
                }
                if (wszNTName == L'\\')
                {
                        ulSepNum++;
                }
                if (ulSepNum == 3)
                {
                        wszNTName = UNICODE_NULL;
                        pPath = &wszNTName;
                        break;
                }
                i++;
        }

        if (pPath == NULL)
        {
                return FALSE;
        }

        RtlInitUnicodeString(&ustrDeviceName, wszNTName);

        if (!NT_SUCCESS(MyRtlVolumeDeviceToDosName(&ustrDeviceName, &ustrDosName)))
        {
                return FALSE;
        }

        RtlCopyUnicodeString(&ustrFileName, &ustrDosName);
        RtlAppendUnicodeToString(&ustrFileName, L"\\");
        RtlAppendUnicodeToString(&ustrFileName, pPath);

        ExFreePool(ustrDosName.Buffer);

        return TRUE;
}

BOOL QueryVolumeName(WCHAR ch, WCHAR * name, USHORT size)
{
        WCHAR szVolume = L"\\??\\C:";
        UNICODE_STRING LinkName;
        UNICODE_STRING VolName;
        UNICODE_STRING ustrTarget;
        NTSTATUS ntStatus = 0;
       
        RtlInitUnicodeString(&LinkName, szVolume);
       
        szVolume = ch;

        ustrTarget.Buffer = name;
        ustrTarget.Length = 0;
        ustrTarget.MaximumLength = size;
       
        ntStatus = QuerySymbolicLink(&LinkName, &VolName);
        if (NT_SUCCESS(ntStatus))
        {
                RtlCopyUnicodeString(&ustrTarget, &VolName);
                ExFreePool(VolName.Buffer);
        }
        return NT_SUCCESS(ntStatus);
       
}

//\\??\\c:\\windows\\hi.txt-->\\device\\harddiskvolume1\\windows\\hi.txt

BOOL NTAPI GetNtDeviceName(WCHAR * filename, WCHAR * ntname)
{
        UNICODE_STRING uVolName = {0,0,0};
        WCHAR volName = L"";
        WCHAR tmpName = L"";
        WCHAR chVol = L'\0';
        WCHAR * pPath = NULL;
        int i = 0;
       

        RtlStringCbCopyW(tmpName, MAX_PATH * sizeof(WCHAR), filename);
       
        for(i = 1; i < MAX_PATH - 1; i++)
        {
                if(tmpName == L':')
                {
                        pPath = &tmpName[(i + 1) % MAX_PATH];
                        chVol = tmpName;
                        break;
                }
        }
       
        if(pPath == NULL)
        {
                return FALSE;
        }
       
        if(chVol == L'?')
        {
                uVolName.Length = 0;
                uVolName.MaximumLength = MAX_PATH * sizeof(WCHAR);
                uVolName.Buffer = ntname;
                RtlAppendUnicodeToString(&uVolName, L"\\Device\\HarddiskVolume?");
                RtlAppendUnicodeToString(&uVolName, pPath);
                return TRUE;
        }
        else if(QueryVolumeName(chVol, volName, MAX_PATH * sizeof(WCHAR)))
        {
                uVolName.Length = 0;
                uVolName.MaximumLength = MAX_PATH * sizeof(WCHAR);
                uVolName.Buffer = ntname;
                RtlAppendUnicodeToString(&uVolName, volName);
                RtlAppendUnicodeToString(&uVolName, pPath);
                return TRUE;
        }
       
        return FALSE;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
        DbgPrint("Goodbye!\n");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
        UNICODE_STRING                ustrDeviceName                        = {0};
        UNICODE_STRING                ustrLinkName                        = {0};
        WCHAR                                *wszDeviceName                        = L"\\Device\\harddiskvolume1";
        NTSTATUS                        ntStatus                                = 0;
        WCHAR                        DeviceName                = L"\\Device\\harddiskvolume1\\windows\\hi.txt";
        WCHAR                        FileName                = {0};
        WCHAR                        szDeviceName= {0};

        RtlInitUnicodeString(&ustrDeviceName, wszDeviceName);

        ntStatus = MyRtlVolumeDeviceToDosName(&ustrDeviceName, &ustrLinkName);
        if (NT_SUCCESS(ntStatus))
        {
               
                DbgPrint("linkname:%wZ\n", &ustrLinkName);
                if (ustrLinkName.Buffer)
                {
                        ExFreePool(ustrLinkName.Buffer);
                }
        }
        if (GetNTLinkName(DeviceName, FileName))
        {
                DbgPrint("FileName:%ws\n", FileName);
                GetNtDeviceName(FileName, szDeviceName);
                DbgPrint("szDeviceName:%ws", szDeviceName);
        }

        pDriverObject->DriverUnload = DriverUnload;
       
        return STATUS_SUCCESS;

}
页: [1]
查看完整版本: 设备名与链接名的转换