一个驱动器作为重新分析点

时间:2017-11-13 13:02:28

标签: c++ winapi windows-10 deviceiocontrol reparsepoint

考虑以下独立源代码,我正在试验Win 10 Fall Creators更新版本10.0.16299 Build 16299

    #include <Windows.h>
    #include <iostream>
    #include <string>
    #include <memory>

    #if !defined (REPARSE_DATA_BUFFER_HEADER_SIZE)  // 

    // Note:
    // See http://msdn.microsoft.com/en-us/library/ff552012.aspx for information about
    // the following structure.
    //
    typedef struct _REPARSE_DATA_BUFFER
    {
        ULONG   ReparseTag;
        USHORT  ReparseDataLength;
        USHORT  Reserved;
        union
        {
            struct
            {
                USHORT  SubstituteNameOffset;
                USHORT  SubstituteNameLength;
                USHORT  PrintNameOffset;
                USHORT  PrintNameLength;
                ULONG   Flags;
                WCHAR   PathBuffer[1];
            } SymbolicLinkReparseBuffer;
            struct
            {
                USHORT  SubstituteNameOffset;
                USHORT  SubstituteNameLength;
                USHORT  PrintNameOffset;
                USHORT  PrintNameLength;
                WCHAR   PathBuffer[1];
            } MountPointReparseBuffer;
            struct
            {
                UCHAR   DataBuffer[1];
            } GenericReparseBuffer;
        };
    } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

    #define REPARSE_DATA_BUFFER_HEADER_SIZE  FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
    #endif

    #if !defined(IO_REPARSE_TAG_CLOUD_7)
    #define IO_REPARSE_TAG_CLOUD_7                  (0x9000701AL)   
    #endif 

    struct file_handle_close
    {   
        void operator()(void *handle) const
        {   
            if (static_cast<HANDLE>(handle) != INVALID_HANDLE_VALUE)
            {   
                CloseHandle(static_cast<HANDLE>(handle));
            }   
        }   
    }; // end of file_handle_close structure

    typedef std::unique_ptr<void, file_handle_close>  file_handle_uptr;


    bool is_link(DWORD file_attrib)
    {
        return ((file_attrib & FILE_ATTRIBUTE_REPARSE_POINT) && !(file_attrib & FILE_ATTRIBUTE_SPARSE_FILE));
    } // end of is_link()

    union reparse_data_context
    {
        char                 buff[REPARSE_DATA_BUFFER_HEADER_SIZE + MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
        REPARSE_DATA_BUFFER  reparse_data_buff;
    }; // end of reparse_data_context union


    void foo(const std::string& var,const std::wstring& path_name)
    {
        WIN32_FILE_ATTRIBUTE_DATA attr_ctx;
        if (GetFileAttributesExW(path_name.c_str(), GetFileExInfoStandard, &attr_ctx) == 0)
        {    

            DWORD  error_code(GetLastError());
            std::cout << "Error occurred "<< error_code << "\n";
        }
        else
        { 
            std::cout << var << '\n';
            std::cout << "attr_ctx.dwFileAttributes  :" << attr_ctx.dwFileAttributes << '\n';
            bool islink = is_link(attr_ctx.dwFileAttributes);

            if(islink)
            {
                file_handle_uptr  handle_uptr(CreateFileW(path_name.c_str(),
                                                          FILE_READ_EA,
                                                         (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
                                                          0,
                                                         OPEN_EXISTING,
                                                        (FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT),
                                                        0));
                HANDLE  handle(static_cast<HANDLE>(handle_uptr.get()));
                if (handle == INVALID_HANDLE_VALUE)
                {
                    std::cout << "CreateFileW failed with : "<<GetLastError()<<'\n';
                    return;
                }

                DWORD ret_len;
                reparse_data_context rctx;

                if(!DeviceIoControl(handle,
                                    FSCTL_GET_REPARSE_POINT,
                                    nullptr,
                                    0,
                                    rctx.buff,
                                    sizeof(rctx),
                                    &ret_len,
                                    nullptr))
                {
                    std::cout << "DeviceIoControl failed with : "<<GetLastError()<<'\n';
                    return;
                }
                else
                {
                    ULONG  reparse_tag(reinterpret_cast<const REPARSE_DATA_BUFFER*>(rctx.buff)->ReparseTag);
                    if (!IsReparseTagMicrosoft(reparse_tag))
                    {
                        std::cout << "Not a supported reparse tag" << std::endl;
                        return;
                    }
                    if (reparse_tag == IO_REPARSE_TAG_SYMLINK)
                    {

                        std::wstring  target_name;

                        {
                            size_t len = static_cast<size_t>((rctx.reparse_data_buff.SymbolicLinkReparseBuffer.PrintNameLength) / sizeof(wchar_t));
                            const size_t another = len;
                            std::wcout << "Target " <<  std::wstring(static_cast<wchar_t*>(rctx.reparse_data_buff.SymbolicLinkReparseBuffer.PathBuffer) +
                                                                     (rctx.reparse_data_buff.SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t)),
                                                                     len);
                        }

                        {
                            size_t len = static_cast<size_t>((rctx.reparse_data_buff.SymbolicLinkReparseBuffer.SubstituteNameLength) / sizeof(wchar_t));

                            std::wcout << "Target " << std::wstring(static_cast<wchar_t*>(rctx.reparse_data_buff.SymbolicLinkReparseBuffer.PathBuffer) +
                                    (rctx.reparse_data_buff.SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t)),
                                    len);
                        }
                    }
                    else if(reparse_tag == IO_REPARSE_TAG_MOUNT_POINT)
                    {
                        // Do something similar to previous block
                    }
                    else if(reparse_tag == IO_REPARSE_TAG_CLOUD_7)
                    { 
                       std::cout << " this is not a valid Reparse Point"<<std::endl;
                       // How to resolve a target for this ?
                    }
                }
            }
            else
            {
                std::cout << var << "  is not a link or junction "<< '\n';
            }
        }
    }

    int main()
    {    
        std::wstring path_name = L"C:\\Users\\someuser\\OneDrive";

        foo("OneDrive",path_name);
        return 0;
    }

这是我用来解析一个驱动器的目标的代码,该驱动器被IO_REPARSE_TAG_CLOUD_7函数视为GetFileAttributesExW

我知道_REPARSE_DATA_STRUCTURE仅包含SymbolicLinkReparseBufferMountPointReparseBuffer的信息,并且没有与重新分析点相关的任何字段,例如One Drive。

我检查了Windows驱动程序工具包(针对秋季创建者更新)ntifs.h文件,以查看结构是否已更新以支持One Drive。然而,似乎并非如此。

我还尝试从SymbolicLinkReparseBufferMountPointReparseBuffer中获取One Drive目标信息,就像在第一个if块中一样。然而,它最终给了我垃圾。

问题:

1)如何正确确定REPARSE_POINTS的目标,例如One Drive?

2)Windows 10 Fall Creators更新SDK添加了更多此类REPARSE_POINT标记。 如果一个人无法解决它的目标(例如One Drive),那么对它们进行处理的一般拇指规则是什么(即源REPARSE_POINTS)?作为文件还是作为目录?

0 个答案:

没有答案