FILE_NETWORK_PHYSICAL_NAME_INFORMATION - NtDoc

Native API online documentation, based on the System Informer (formerly Process Hacker) phnt headers
#ifndef _NTIOAPI_H

/**
 * The FILE_NETWORK_PHYSICAL_NAME_INFORMATION structure contains information about the network physical name of a file.
 * \sa https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_network_physical_name_information
 */
typedef struct _FILE_NETWORK_PHYSICAL_NAME_INFORMATION
{
    ULONG FileNameLength;
    _Field_size_bytes_(FileNameLength) WCHAR FileName[1];
} FILE_NETWORK_PHYSICAL_NAME_INFORMATION, *PFILE_NETWORK_PHYSICAL_NAME_INFORMATION;

#endif

View code on GitHub
// ntifs.h

typedef struct _FILE_NETWORK_PHYSICAL_NAME_INFORMATION {
  ULONG FileNameLength;
  WCHAR FileName[1];
} FILE_NETWORK_PHYSICAL_NAME_INFORMATION, *PFILE_NETWORK_PHYSICAL_NAME_INFORMATION;
View the official Windows Driver Kit DDI reference

NtDoc

This structure is documented in Windows Driver Kit.

Windows Driver Kit DDI reference (ns-ntifs-_file_network_physical_name_information)

FILE_NETWORK_PHYSICAL_NAME_INFORMATION structure

Description

The FILE_NETWORK_PHYSICAL_NAME_INFORMATION structure contains the full UNC physical pathname for a file or directory on a remote file share.

Members

FileNameLength

The length, in bytes, of the physical name in FileName.

FileName

The full UNC path of the network file share of the target.

Remarks

The FILE_NETWORK_PHYSICAL_NAME_INFORMATION structure is used to retrieve the network physical name information for a file. This operation can be performed in either of the following ways:

The FileName of FILE_NETWORK_PHYSICAL_NAME_INFORMATION will contain the network name of the file target handle passed to ZwQueryInformationFile. The physical network name returned is in the format of \;X:\Server\ShareName\Dir1\Dir2...\FileName.

If the physical name is longer than the length set in FileNameLength, then STATUS_BUFFER_OVERFLOW is returned from ZwQueryInformationFile and FileNameLength is updated with the number of bytes required to hold the entire name string. The count of characters in the name is FileNameLength / sizeof(WCHAR).

In the case where a file is cached on a client and its network physical name is queried, the path returned in FileName may not be known to the client cache. The caching system may not associate the cached file with the file opened using the path returned in FileName.

The following is an example of querying the network physical name information of a file target using ZwQueryInformationFile.

NTSTATUS GetPhysicalNetworkName(HANDLE Target, WCHAR *NetworkName, ULONG MaxNetworkNameLength)
{
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatus;
    ULONG NameInfoLength;
    PFILE_NETWORK_PHYSICAL_NAME_INFORMATION NetFileNameInfo = NULL;

    if ( MaxNetworkNameLength < sizeof(WCHAR) )
    {
        return STATUS_NAME_TOO_LONG;
    }
    if (NetworkName != NULL)
    {
        return STATUS_INVALID_PARAMETER;
    }

    NetworkName[0] = (WCHAR)0;  // initially terminate the output string;

    // set the initial name length, the one WCHAR in NetFileNameInfo.FileName is reserved for the terminating NULL
    NameInfoLength = sizeof(PFILE_NETWORK_PHYSICAL_NAME_INFORMATION) +
                     min(1024, MaxNetworkNameLength - sizeof(WCHAR));
    NetFileNameInfo = (PFILE_NETWORK_PHYSICAL_NAME_INFORMATION)ExAllocatePool(PagedPool, NameInfoLength);

    if (NetFileNameInfo == NULL)
    {
        Status = STATUS_NO_MEMORY;
    }
    else
    {
        Status = ZwQueryInformationFile(Target,
                                        &IoStatus,
                                        NetFileNameInfo,
                                        NameInfoLength,
                                        FileNetworkPhysicalNameInformation);
    }
    if (Status == STATUS_BUFFER_OVERFLOW)
    {
        if (NetFileNameInfo->FileNameLength <= (MaxNetworkNameLength - sizeof(WCHAR)))
        {
            NameInfoLength += sizeof(PFILE_NETWORK_PHYSICAL_NAME_INFORMATION) + NetFileNameInfo->FileNameLength;
            ExFreePool(NetFileNameInfo);
            NetFileNameInfo = (PFILE_NETWORK_PHYSICAL_NAME_INFORMATION)ExAllocatePool(PagedPool, NameInfoLength);
            if (NetFileNameInfo == NULL)
            {
                Status = STATUS_NO_MEMORY;
            }
            else
            {
                Status = ZwQueryInformationFile(Target,
                                                &IoStatus,
                                                NetFileNameInfo,
                                                NameInfoLength,
                                                FileNetworkPhysicalNameInformation);
            }
        }
    }
    if (NetFileNameInfo != NULL)
    {
        if (NT_SUCCESS(Status))
        {
            NameInfoLength = min(NameInfoLength, NetFileNameInfo->FileNameLength);
            RtlCopyMemory(NetworkName, NetFileNameInfo->FileName, NameInfoLength);
            NetworkName[NameInfoLength / sizeof(WCHAR)] = (WCHAR)0;
        }
        ExFreePool(NetFileNameInfo);
    }

    return Status;
}

See also

FILE_INFORMATION_CLASS

IRP_MJ_QUERY_INFORMATION

ZwQueryInformationFile