在 C/C++ 中创建 Windows NTFS 目录联结时出现问题
Issue creating Windows NTFS directory junction in C/C++
我正在尝试使用 Visual C++ 执行此操作。这段代码似乎创建了一个连接点,设置了正确的目标,但是连接点的大小为 0,当我点击它时,我得到:
代码如下:
#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();
}
我几乎可以肯定我没有在某处正确设置大小,但不确定是什么地方。没有错误或警告,似乎只是创建了大小为 0 的联结(具有正确的名称、目标和联结类型)。
未在目标路径前加上 \??\
。这样做就是我需要做的。
我正在尝试使用 Visual C++ 执行此操作。这段代码似乎创建了一个连接点,设置了正确的目标,但是连接点的大小为 0,当我点击它时,我得到:
代码如下:
#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();
}
我几乎可以肯定我没有在某处正确设置大小,但不确定是什么地方。没有错误或警告,似乎只是创建了大小为 0 的联结(具有正确的名称、目标和联结类型)。
未在目标路径前加上 \??\
。这样做就是我需要做的。