I am trying to do this using 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:
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.
Was not prefixing target path with \??\
. Doing so was all I needed to do.