简体   繁体   English

在C / C ++中创建Windows NTFS目录联结时出现问题

[英]Issue creating Windows NTFS directory junction in C/C++

I am trying to do this using Visual C++. 我正在尝试使用Visual C ++做到这一点。 This code seems to create a junction, with the correct target set, but the junction has a size of 0 and when I click on it I get: 这段代码似乎创建了一个具有正确目标集的联结,但是联结的大小为0,当我单击它时,我得到:

错误信息

Here is the code: 这是代码:

#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <ole2.h>
#include <errno.h>

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;

#define REPARSE_MOUNTPOINT_HEADER_SIZE 8

bool createJunction(WCHAR *linkPath, WCHAR *newTargetPath) {
    int create_status = CreateDirectory(linkPath, NULL);

    // If the directory already existed, treat it as a success.
    if (create_status == 0 && (GetLastError() != ERROR_ALREADY_EXISTS || (GetFileAttributesW(linkPath) & FILE_ATTRIBUTE_DIRECTORY) != 0))
        return false;

    HANDLE handle = CreateFile(linkPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
    if (handle == INVALID_HANDLE_VALUE)
    {
        _tprintf(_T("Could not open dir '%s'; error: %d\n"), linkPath, GetLastError());
        CloseHandle(handle);
        return false;
    }

    int target_len = wcslen(newTargetPath);
    if (target_len > MAX_PATH - 1) {
        CloseHandle(handle);
        return false;
    }

    int reparse_data_buffer_size = sizeof REPARSE_DATA_BUFFER + 2 * MAX_PATH * sizeof WCHAR;
    REPARSE_DATA_BUFFER* reparse_data_buffer = static_cast<REPARSE_DATA_BUFFER*>(calloc(reparse_data_buffer_size, 1));

    reparse_data_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
    wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer, newTargetPath);
    wcscpy(reparse_data_buffer->MountPointReparseBuffer.PathBuffer + target_len + 1, newTargetPath);
    reparse_data_buffer->MountPointReparseBuffer.SubstituteNameOffset = 0;
    reparse_data_buffer->MountPointReparseBuffer.SubstituteNameLength = target_len * sizeof(WCHAR);
    reparse_data_buffer->MountPointReparseBuffer.PrintNameOffset = (target_len + 1) * sizeof(WCHAR);
    reparse_data_buffer->MountPointReparseBuffer.PrintNameLength = target_len * sizeof(WCHAR);
    reparse_data_buffer->ReparseDataLength = (target_len + 1) * 2 * sizeof(WCHAR) + REPARSE_MOUNTPOINT_HEADER_SIZE;

    DWORD dummy_received_bytes;
    int result = DeviceIoControl(
        handle,
        FSCTL_SET_REPARSE_POINT,
        reparse_data_buffer,
        reparse_data_buffer->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
        NULL,
        0,
        &dummy_received_bytes,
        NULL);
    if (CloseHandle(handle) == 0)
        return false;
    free(reparse_data_buffer);

    return (result != 0);
}

int _tmain(int argc, _TCHAR* argv[])
{
    createJunction(L"C:\\Users\\Weston\\Desktop\\New folder\\Junction of asdf", L"C:\\Users\\Weston\\Desktop\\New folder\\asdf");

    _tprintf(_T("Execution complete.\n"));
    getchar();
}

I am almost sure I am not setting the size correctly somewhere, but no sure what and where. 我几乎可以肯定我没有在某个地方正确设置大小,但是不确定什么地方。 There are no errors or warnings, the junction simply seems to be created (with the correct name and target and type of junction) with a size of 0. 没有错误或警告,似乎只是创建了大小为0的联结(具有正确的名称,目标和联结类型)。

Was not prefixing target path with \\??\\ . 没有在目标路径前加上\\??\\ Doing so was all I needed to do. 这样做是我要做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM