Skip to content

Instantly share code, notes, and snippets.

@rbmm
Created July 28, 2025 16:56
Show Gist options
  • Select an option

  • Save rbmm/da51ff407c86d3ede348689de0d11725 to your computer and use it in GitHub Desktop.

Select an option

Save rbmm/da51ff407c86d3ede348689de0d11725 to your computer and use it in GitHub Desktop.
NTSTATUS CreateReparse(ULONG ReparseTag, PCWSTR pszFileName, PCWSTR SubstituteName, PCWSTR PrintName)
{
NTSTATUS status;
PREPARSE_DATA_BUFFER prdb = 0;
int len = 0;
PWSTR PathBuffer = 0;
ULONG cb = 0;
UNICODE_STRING ObjectName;
if (0 <= (status = RtlDosPathNameToNtPathName_U_WithStatus(SubstituteName, &ObjectName, 0, 0)))
{
status = STATUS_INTERNAL_ERROR;
while (0 < (len = _snwprintf(PathBuffer, len, L"%wZ%c%ws", &ObjectName, 0, PrintName)))
{
if (PathBuffer)
{
if (IO_REPARSE_TAG_SYMLINK == ReparseTag)
{
prdb->SymbolicLinkReparseBuffer.Flags = 0;
}
prdb->ReparseTag = ReparseTag;
prdb->ReparseDataLength = (USHORT)(cb - offsetof(REPARSE_DATA_BUFFER, GenericReparseBuffer));
prdb->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
prdb->SymbolicLinkReparseBuffer.SubstituteNameLength = ObjectName.Length;
prdb->SymbolicLinkReparseBuffer.PrintNameOffset = ObjectName.Length + sizeof(WCHAR);
prdb->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)wcslen(PrintName) * sizeof(WCHAR);
status = STATUS_SUCCESS;
break;
}
++len;
cb = IO_REPARSE_TAG_SYMLINK == ReparseTag
? FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[len])
: FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer[len]);
prdb = (PREPARSE_DATA_BUFFER)alloca(cb);
PathBuffer = IO_REPARSE_TAG_SYMLINK == ReparseTag
? prdb->SymbolicLinkReparseBuffer.PathBuffer : prdb->MountPointReparseBuffer.PathBuffer;
}
RtlFreeUnicodeString(&ObjectName);
if (0 <= status)
{
HANDLE hFile;
IO_STATUS_BLOCK iosb;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName, OBJ_CASE_INSENSITIVE };
if (0 <= (status = RtlDosPathNameToNtPathName_U_WithStatus(pszFileName, &ObjectName, 0, 0)))
{
status = NtCreateFile(&hFile, FILE_ALL_ACCESS, &oa, &iosb, 0, 0, 0,
FILE_OVERWRITE_IF, FILE_OPEN_REPARSE_POINT|FILE_NON_DIRECTORY_FILE, 0, 0);
RtlFreeUnicodeString(&ObjectName);
if (0 <= status)
{
status = NtFsControlFile(hFile, 0, 0, 0, &iosb, FSCTL_SET_REPARSE_POINT, prdb, cb, 0, 0);
NtClose(hFile);
}
}
}
}
return status;
}
void TestDel(ULONG ReparseTag, PCWSTR pszFileName, PCWSTR SubstituteName)
{
if (HANDLE hFile = fixH(CreateFileW(SubstituteName, FILE_APPEND_DATA, 0, 0, CREATE_ALWAYS, 0, 0)))
{
ULONG n;
WriteFile(hFile, "1234567890\r\n", 12, &n, 0);
NtClose(hFile);
if (0 <= CreateReparse(ReparseTag, pszFileName, SubstituteName, L"[test]"))
{
if (!DeleteFileW(pszFileName))
{
GetLastErrorEx();
}
}
}
}
void TestDel(PCWSTR pszFileName, PCWSTR SubstituteName)
{
BOOLEAN bi;
RtlAdjustPrivilege(SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, TRUE, FALSE, &bi);
TestDel(IO_REPARSE_TAG_SYMLINK, pszFileName, SubstituteName);
// A requested opened file is not a directory.
TestDel(IO_REPARSE_TAG_MOUNT_POINT, pszFileName, SubstituteName);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment