Skip to content

Instantly share code, notes, and snippets.

@rbmm
Created July 25, 2025 07:52
Show Gist options
  • Select an option

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

Select an option

Save rbmm/8f49c14f5491438de835a83e75d17e8e to your computer and use it in GitHub Desktop.
BOOL InternalDeleteFileW(_In_ PCWSTR lpFileName)
{
union {
FILE_ATTRIBUTE_TAG_INFORMATION attr;
FILE_DISPOSITION_INFORMATION_EX fdi;
};
UNICODE_STRING ObjectName;
NTSTATUS status = RtlDosPathNameToNtPathName_U_WithStatus(lpFileName, &ObjectName, 0, 0);
if (0 <= status)
{
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName, OBJ_CASE_INSENSITIVE };
IO_STATUS_BLOCK iosb;
HANDLE hFile;
if (0 <= (status = NtOpenFile(&hFile, DELETE|FILE_READ_ATTRIBUTES, &oa, &iosb, FILE_SHARE_READ,
FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_NON_DIRECTORY_FILE)))
{
if (0 <= (status = NtQueryInformationFile(hFile, &iosb, &attr, sizeof(attr), FileAttributeTagInformation)))
{
if (attr.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
{
switch (attr.ReparseTag)
{
case IO_REPARSE_TAG_MOUNT_POINT:
case IO_REPARSE_TAG_SYMLINK:
case IO_REPARSE_TAG_GLOBAL_REPARSE:
break;
default:
NtClose(hFile);
if (0 > (status = NtOpenFile(&hFile, DELETE, &oa,
&iosb, FILE_SHARE_READ, FILE_OPEN_FOR_BACKUP_INTENT|FILE_NON_DIRECTORY_FILE)))
{
switch (status)
{
case STATUS_IO_REPARSE_TAG_INVALID:
case STATUS_IO_REPARSE_DATA_INVALID:
case STATUS_IO_REPARSE_TAG_NOT_HANDLED:
if (0 <= (status = NtOpenFile(&hFile, DELETE, &oa, &iosb, FILE_SHARE_READ,
FILE_OPEN_REPARSE_POINT|FILE_OPEN_FOR_BACKUP_INTENT|FILE_NON_DIRECTORY_FILE)))
{
break;
}
default:
goto __exit;
}
}
break;
}
}
fdi.Flags = FILE_DISPOSITION_DELETE|FILE_DISPOSITION_POSIX_SEMANTICS;
status = NtSetInformationFile(hFile, &iosb, &fdi, sizeof(fdi), FileDispositionInformationEx);
}
NtClose(hFile);
}
__exit:
RtlFreeUnicodeString(&ObjectName);
}
return NOERROR == RtlNtStatusToDosError(status);
}
//*****************************************************************************************************************
// https://github.com/wisny101/Windows-Server-2003-Source/blob/master/base/ntos/io/iomgr/iosubs.c#L3567
if (Irp->Flags & IRP_ASSOCIATED_IRP) {
//...
}
//
// Check to see if we have a name junction. If so set the stage to
// transmogrify the reparse point data in IopCompleteRequest.
//
if ((Irp->IoStatus.Status == STATUS_REPARSE ) &&
(Irp->IoStatus.Information > IO_REPARSE_TAG_RESERVED_RANGE)) {
switch (Irp->IoStatus.Information)
{
case IO_REPARSE_TAG_MOUNT_POINT:
case IO_REPARSE_TAG_SYMLINK:
case IO_REPARSE_TAG_GLOBAL_REPARSE:
//
// For name junctions, we save the pointer to the auxiliary
// buffer and use it below.
//
ASSERT( Irp->Tail.Overlay.AuxiliaryBuffer != NULL );
saveAuxiliaryPointer = (PVOID) Irp->Tail.Overlay.AuxiliaryBuffer;
//
// We NULL the entry to avoid its de-allocation at this time.
// This buffer get deallocated in IopDoNameTransmogrify
//
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
break;
default:
//
// Fail the request. A driver needed to act on this IRP prior
// to getting to this point.
//
Irp->IoStatus.Status = STATUS_IO_REPARSE_TAG_NOT_HANDLED;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment