mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 16:26:02 +00:00
[RTL]: Document and flesh out Boot Status Data (BSD) API/Structures
[NDK]: Document latest RTL_BSD_DATA as of RS3 based on ext.dll WinDBG extension "!blackboxbsd" which outputs the entire structure field by field :). [NDK]: Update RTL_BSD_ITEM_TYPE thanks to ole32 symbols [RTL]: Move system volume APIs to sysvol.c [RTL]: Fill out BsdItemTable based on actual field offsets/sizes and not hardcoded magic numbers which we won't ask where they came from. [RTL]: Make RtlCreateBootStatusDataFile use an appropriate structure for initializing the buffer instead of "UCHAR Buffer[12] = {0xC,0,0,0, 1,0,0,0, 1, 0x1e, 1, 0};" which appears like magic knowledge. [RTL]: Rename "WriteMode" to "Read" in RtlGetSetBootStatusData since it's much less confusing. [RTL]: Some formatting fixes, SAL updates.
This commit is contained in:
parent
adcb9bd175
commit
16e0cca7e1
4 changed files with 888 additions and 709 deletions
|
@ -414,9 +414,6 @@ C_ASSERT(FIELD_OFFSET(LARGE_INTEGER, LowPart) == 0);
|
||||||
#define RTL_CONSTANT_LARGE_INTEGER(quad_part) { { (quad_part), (quad_part)>>32 } }
|
#define RTL_CONSTANT_LARGE_INTEGER(quad_part) { { (quad_part), (quad_part)>>32 } }
|
||||||
#define RTL_MAKE_LARGE_INTEGER(low_part, high_part) { { (low_part), (high_part) } }
|
#define RTL_MAKE_LARGE_INTEGER(low_part, high_part) { { (low_part), (high_part) } }
|
||||||
|
|
||||||
|
|
||||||
#ifdef NTOS_MODE_USER
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Boot Status Data Field Types
|
// Boot Status Data Field Types
|
||||||
//
|
//
|
||||||
|
@ -428,9 +425,20 @@ typedef enum _RTL_BSD_ITEM_TYPE
|
||||||
RtlBsdItemAabTimeout,
|
RtlBsdItemAabTimeout,
|
||||||
RtlBsdItemBootGood,
|
RtlBsdItemBootGood,
|
||||||
RtlBsdItemBootShutdown,
|
RtlBsdItemBootShutdown,
|
||||||
|
RtlBsdSleepInProgress,
|
||||||
|
RtlBsdPowerTransition,
|
||||||
|
RtlBsdItemBootAttemptCount,
|
||||||
|
RtlBsdItemBootCheckpoint,
|
||||||
|
RtlBsdItemBootId,
|
||||||
|
RtlBsdItemShutdownBootId,
|
||||||
|
RtlBsdItemReportedAbnormalShutdownBootId,
|
||||||
|
RtlBsdItemErrorInfo,
|
||||||
|
RtlBsdItemPowerButtonPressInfo,
|
||||||
|
RtlBsdItemChecksum,
|
||||||
RtlBsdItemMax
|
RtlBsdItemMax
|
||||||
} RTL_BSD_ITEM_TYPE, *PRTL_BSD_ITEM_TYPE;
|
} RTL_BSD_ITEM_TYPE, *PRTL_BSD_ITEM_TYPE;
|
||||||
|
|
||||||
|
#ifdef NTOS_MODE_USER
|
||||||
//
|
//
|
||||||
// Table and Compare result types
|
// Table and Compare result types
|
||||||
//
|
//
|
||||||
|
@ -1238,6 +1246,92 @@ typedef struct _RTL_HANDLE_TABLE
|
||||||
PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles;
|
PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles;
|
||||||
} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;
|
} RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// RTL Boot Status Data Item
|
||||||
|
//
|
||||||
|
typedef struct _RTL_BSD_ITEM
|
||||||
|
{
|
||||||
|
RTL_BSD_ITEM_TYPE Type;
|
||||||
|
PVOID DataBuffer;
|
||||||
|
ULONG DataLength;
|
||||||
|
} RTL_BSD_ITEM, *PRTL_BSD_ITEM;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Data Sub-Structures for "bootstat.dat" RTL Data File
|
||||||
|
//
|
||||||
|
typedef struct _RTL_BSD_DATA_POWER_TRANSITION
|
||||||
|
{
|
||||||
|
LARGE_INTEGER PowerButtonTimestamp;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UCHAR SystemRunning : 1;
|
||||||
|
UCHAR ConnectedStandbyInProgress : 1;
|
||||||
|
UCHAR UserShutdownInProgress : 1;
|
||||||
|
UCHAR SystemShutdownInProgress : 1;
|
||||||
|
UCHAR SleepInProgress : 4;
|
||||||
|
} Flags;
|
||||||
|
UCHAR ConnectedStandbyScenarioInstanceId;
|
||||||
|
UCHAR ConnectedStandbyEntryReason;
|
||||||
|
UCHAR ConnectedStandbyExitReason;
|
||||||
|
USHORT SystemSleepTransitionCount;
|
||||||
|
LARGE_INTEGER LastReferenceTime;
|
||||||
|
ULONG LastReferenceTimeChecksum;
|
||||||
|
ULONG LastUpdateBootId;
|
||||||
|
} RTL_BSD_DATA_POWER_TRANSITION, *PRTL_BSD_DATA_POWER_TRANSITION;
|
||||||
|
|
||||||
|
typedef struct _RTL_BSD_DATA_ERROR_INFO
|
||||||
|
{
|
||||||
|
ULONG BootId;
|
||||||
|
ULONG RepeatCount;
|
||||||
|
ULONG OtherErrorCount;
|
||||||
|
ULONG Code;
|
||||||
|
ULONG OtherErrorCount2;
|
||||||
|
} RTL_BSD_DATA_ERROR_INFO, *PRTL_BSD_DATA_ERROR_INFO;
|
||||||
|
|
||||||
|
typedef struct _RTL_BSD_POWER_BUTTON_PRESS_INFO
|
||||||
|
{
|
||||||
|
LARGE_INTEGER LastPressTime;
|
||||||
|
ULONG CumulativePressCount;
|
||||||
|
USHORT LastPressBootId;
|
||||||
|
UCHAR LastPowerWatchdogStage;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UCHAR WatchdogArmed : 1;
|
||||||
|
UCHAR ShutdownInProgress : 1;
|
||||||
|
} Flags;
|
||||||
|
LARGE_INTEGER LastReleaseTime;
|
||||||
|
ULONG CumulativeReleaseCount;
|
||||||
|
USHORT LastReleaseBootId;
|
||||||
|
USHORT ErrorCount;
|
||||||
|
UCHAR CurrentConnectedStandbyPhase;
|
||||||
|
ULONG TransitionLatestCheckpointId;
|
||||||
|
ULONG TransitionLatestCheckpointType;
|
||||||
|
ULONG TransitionLatestCheckpointSequenceNumber;
|
||||||
|
} RTL_BSD_POWER_BUTTON_PRESS_INFO, *PRTL_BSD_POWER_BUTTON_PRESS_INFO;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Main Structure for "bootstat.dat" RTL Data File
|
||||||
|
//
|
||||||
|
typedef struct _RTL_BSD_DATA
|
||||||
|
{
|
||||||
|
ULONG Version; // RtlBsdItemVersionNumber
|
||||||
|
ULONG ProductType; // RtlBsdItemProductType
|
||||||
|
BOOLEAN AabEnabled; // RtlBsdItemAabEnabled
|
||||||
|
UCHAR AabTimeout; // RtlBsdItemAabTimeout
|
||||||
|
BOOLEAN LastBootSucceeded; // RtlBsdItemBootGood
|
||||||
|
BOOLEAN LastBootShutdown; // RtlBsdItemBootShutdown
|
||||||
|
BOOLEAN SleepInProgress; // RtlBsdSleepInProgress
|
||||||
|
RTL_BSD_DATA_POWER_TRANSITION PowerTransition; // RtlBsdPowerTransition
|
||||||
|
UCHAR BootAttemptCount; // RtlBsdItemBootAttemptCount
|
||||||
|
UCHAR LastBootCheckpoint; // RtlBsdItemBootCheckpoint
|
||||||
|
UCHAR Checksum; // RtlBsdItemChecksum
|
||||||
|
ULONG LastBootId; // RtlBsdItemBootId
|
||||||
|
ULONG LastSuccessfulShutdownBootId; // RtlBsdItemShutdownBootId
|
||||||
|
ULONG LastReportedAbnormalShutdownBootId; // RtlBsdItemReportedAbnormalShutdownBootId
|
||||||
|
RTL_BSD_DATA_ERROR_INFO ErrorInfo; // RtlBsdItemErrorInfo
|
||||||
|
RTL_BSD_POWER_BUTTON_PRESS_INFO PowerButtonPressInfo; // RtlBsdItemPowerButtonPressInfo
|
||||||
|
} RTL_BSD_DATA, *PRTL_BSD_DATA;
|
||||||
|
|
||||||
#ifdef NTOS_MODE_USER
|
#ifdef NTOS_MODE_USER
|
||||||
//
|
//
|
||||||
// Exception Record
|
// Exception Record
|
||||||
|
|
|
@ -56,6 +56,7 @@ list(APPEND SOURCE
|
||||||
slist.c
|
slist.c
|
||||||
sid.c
|
sid.c
|
||||||
splaytree.c
|
splaytree.c
|
||||||
|
sysvol.c
|
||||||
thread.c
|
thread.c
|
||||||
time.c
|
time.c
|
||||||
timezone.c
|
timezone.c
|
||||||
|
|
|
@ -1,715 +1,118 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* PROJECT: ReactOS Runtime Library
|
||||||
* PROJECT: ReactOS system libraries
|
* LICENSE: See COPYING in the top level directory
|
||||||
* PURPOSE: Boot Data implementation
|
|
||||||
* FILE: lib/rtl/bootdata.c
|
* FILE: lib/rtl/bootdata.c
|
||||||
* PROGRAMMERS:
|
* PURPOSE: Boot Status Data Implementation
|
||||||
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
|
* Eric Kohl
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include <rtl.h>
|
#include <rtl.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
typedef struct _RTL_BSD_ITEM
|
typedef struct _RTL_BSD_ITEM_TABLE_ENTRY
|
||||||
{
|
{
|
||||||
ULONG Offset;
|
UCHAR Offset;
|
||||||
ULONG Size;
|
UCHAR Size;
|
||||||
} RTL_BSD_ITEM, *PRTL_BSD_ITEM;
|
} RTL_BSD_ITEM_TABLE_ENTRY;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = {SECURITY_NT_AUTHORITY};
|
PRTL_BSD_DATA DummyBsd;
|
||||||
|
RTL_BSD_ITEM_TABLE_ENTRY BsdItemTable[RtlBsdItemMax] =
|
||||||
static RTL_BSD_ITEM BsdItemTable[6] = {{0, 4}, {4, 4,}, {8, 1}, {9, 1}, {10, 1}, {11, 1}};
|
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
RtlpSysVolCreateSecurityDescriptor(OUT PISECURITY_DESCRIPTOR *SecurityDescriptor,
|
|
||||||
OUT PSID *SystemSid)
|
|
||||||
{
|
{
|
||||||
PSECURITY_DESCRIPTOR AbsSD = NULL;
|
|
||||||
PSID LocalSystemSid = NULL;
|
|
||||||
PACL Dacl = NULL;
|
|
||||||
ULONG DaclSize;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* create the local SYSTEM SID */
|
|
||||||
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
|
||||||
1,
|
|
||||||
SECURITY_LOCAL_SYSTEM_RID,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&LocalSystemSid);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
return Status;
|
FIELD_OFFSET(RTL_BSD_DATA, Version),
|
||||||
}
|
sizeof(&DummyBsd->Version)
|
||||||
|
}, // RtlBsdItemVersionNumber
|
||||||
/* allocate and initialize the security descriptor */
|
|
||||||
AbsSD = RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR),
|
|
||||||
'dSeS');
|
|
||||||
if (AbsSD == NULL)
|
|
||||||
{
|
{
|
||||||
Status = STATUS_NO_MEMORY;
|
FIELD_OFFSET(RTL_BSD_DATA, ProductType),
|
||||||
goto Cleanup;
|
sizeof(&DummyBsd->ProductType)
|
||||||
}
|
}, // RtlBsdItemProductType
|
||||||
|
|
||||||
Status = RtlCreateSecurityDescriptor(AbsSD,
|
|
||||||
SECURITY_DESCRIPTOR_REVISION);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, AabEnabled),
|
||||||
}
|
sizeof(&DummyBsd->AabEnabled)
|
||||||
|
}, // RtlBsdItemAabEnabled
|
||||||
/* allocate and create the DACL */
|
|
||||||
DaclSize = sizeof(ACL) + sizeof(ACE) +
|
|
||||||
RtlLengthSid(LocalSystemSid);
|
|
||||||
Dacl = RtlpAllocateMemory(DaclSize,
|
|
||||||
'cAeS');
|
|
||||||
if (Dacl == NULL)
|
|
||||||
{
|
{
|
||||||
Status = STATUS_NO_MEMORY;
|
FIELD_OFFSET(RTL_BSD_DATA, AabTimeout),
|
||||||
goto Cleanup;
|
sizeof(&DummyBsd->AabTimeout)
|
||||||
}
|
}, // RtlBsdItemAabTimeout
|
||||||
|
|
||||||
Status = RtlCreateAcl(Dacl,
|
|
||||||
DaclSize,
|
|
||||||
ACL_REVISION);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded),
|
||||||
}
|
sizeof(&DummyBsd->LastBootSucceeded)
|
||||||
|
}, // RtlBsdItemBootGood
|
||||||
Status = RtlAddAccessAllowedAceEx(Dacl,
|
|
||||||
ACL_REVISION,
|
|
||||||
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
|
|
||||||
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
|
|
||||||
LocalSystemSid);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown),
|
||||||
}
|
sizeof(&DummyBsd->LastBootShutdown)
|
||||||
|
}, // RtlBsdItemBootShutdown
|
||||||
/* set the DACL in the security descriptor */
|
|
||||||
Status = RtlSetDaclSecurityDescriptor(AbsSD,
|
|
||||||
TRUE,
|
|
||||||
Dacl,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
/* all done */
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
*SecurityDescriptor = AbsSD;
|
FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress),
|
||||||
*SystemSid = LocalSystemSid;
|
sizeof(&DummyBsd->SleepInProgress)
|
||||||
}
|
}, // RtlBsdSleepInProgress
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Cleanup:
|
FIELD_OFFSET(RTL_BSD_DATA, PowerTransition),
|
||||||
if (LocalSystemSid != NULL)
|
sizeof(&DummyBsd->PowerTransition)
|
||||||
{
|
}, // RtlBsdPowerTransition
|
||||||
RtlFreeSid(LocalSystemSid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Dacl != NULL)
|
|
||||||
{
|
|
||||||
RtlpFreeMemory(Dacl,
|
|
||||||
'cAeS');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AbsSD != NULL)
|
|
||||||
{
|
|
||||||
RtlpFreeMemory(AbsSD,
|
|
||||||
'dSeS');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle,
|
|
||||||
IN PISECURITY_DESCRIPTOR SecurityDescriptor)
|
|
||||||
{
|
|
||||||
PSECURITY_DESCRIPTOR RelSD = NULL;
|
|
||||||
PSECURITY_DESCRIPTOR NewRelSD = NULL;
|
|
||||||
PSECURITY_DESCRIPTOR AbsSD = NULL;
|
|
||||||
#ifdef _WIN64
|
|
||||||
BOOLEAN AbsSDAllocated = FALSE;
|
|
||||||
#endif
|
|
||||||
PSID AdminSid = NULL;
|
|
||||||
PSID LocalSystemSid = NULL;
|
|
||||||
ULONG DescriptorSize;
|
|
||||||
ULONG AbsSDSize, RelSDSize = 0;
|
|
||||||
PACL Dacl;
|
|
||||||
BOOLEAN DaclPresent, DaclDefaulted;
|
|
||||||
PSID OwnerSid;
|
|
||||||
BOOLEAN OwnerDefaulted;
|
|
||||||
ULONG AceIndex;
|
|
||||||
PACE Ace = NULL;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
/* find out how much memory we need to allocate for the self-relative
|
|
||||||
descriptor we're querying */
|
|
||||||
Status = ZwQuerySecurityObject(DirectoryHandle,
|
|
||||||
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
&DescriptorSize);
|
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
||||||
{
|
{
|
||||||
/* looks like the FS doesn't support security... return success */
|
FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount),
|
||||||
Status = STATUS_SUCCESS;
|
sizeof(&DummyBsd->BootAttemptCount)
|
||||||
goto Cleanup;
|
}, // RtlBsdItemBootAttemptCount
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate enough memory for the security descriptor */
|
|
||||||
RelSD = RtlpAllocateMemory(DescriptorSize,
|
|
||||||
'dSeS');
|
|
||||||
if (RelSD == NULL)
|
|
||||||
{
|
{
|
||||||
Status = STATUS_NO_MEMORY;
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint),
|
||||||
goto Cleanup;
|
sizeof(&DummyBsd->LastBootCheckpoint)
|
||||||
}
|
}, // RtlBsdItemBootCheckpoint
|
||||||
|
|
||||||
/* query the self-relative security descriptor */
|
|
||||||
Status = ZwQuerySecurityObject(DirectoryHandle,
|
|
||||||
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
|
||||||
RelSD,
|
|
||||||
DescriptorSize,
|
|
||||||
&DescriptorSize);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
/* FIXME - handle the case where someone else modified the owner and/or
|
FIELD_OFFSET(RTL_BSD_DATA, LastBootId),
|
||||||
DACL while we allocated memory. But that should be *very*
|
sizeof(&DummyBsd->LastBootId)
|
||||||
unlikely.... */
|
}, // RtlBsdItemBootId
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* query the owner and DACL from the descriptor */
|
|
||||||
Status = RtlGetOwnerSecurityDescriptor(RelSD,
|
|
||||||
&OwnerSid,
|
|
||||||
&OwnerDefaulted);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId),
|
||||||
}
|
sizeof(&DummyBsd->LastSuccessfulShutdownBootId)
|
||||||
|
}, // RtlBsdItemShutdownBootId
|
||||||
Status = RtlGetDaclSecurityDescriptor(RelSD,
|
|
||||||
&DaclPresent,
|
|
||||||
&Dacl,
|
|
||||||
&DaclDefaulted);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId),
|
||||||
}
|
sizeof(&DummyBsd->LastReportedAbnormalShutdownBootId)
|
||||||
|
}, // RtlBsdItemReportedAbnormalShutdownBootId
|
||||||
/* create the Administrators SID */
|
|
||||||
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
|
||||||
2,
|
|
||||||
SECURITY_BUILTIN_DOMAIN_RID,
|
|
||||||
DOMAIN_ALIAS_RID_ADMINS,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&AdminSid);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo),
|
||||||
}
|
sizeof(&DummyBsd->ErrorInfo)
|
||||||
|
}, // RtlBsdItemErrorInfo
|
||||||
/* create the local SYSTEM SID */
|
|
||||||
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
|
||||||
1,
|
|
||||||
SECURITY_LOCAL_SYSTEM_RID,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&LocalSystemSid);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
goto Cleanup;
|
FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo),
|
||||||
}
|
sizeof(&DummyBsd->PowerButtonPressInfo)
|
||||||
|
}, // RtlBsdItemPowerButtonPressInfo
|
||||||
/* check if the Administrators are the owner and at least a not-NULL DACL
|
|
||||||
is present */
|
|
||||||
if (OwnerSid != NULL &&
|
|
||||||
RtlEqualSid(OwnerSid,
|
|
||||||
AdminSid) &&
|
|
||||||
DaclPresent && Dacl != NULL)
|
|
||||||
{
|
{
|
||||||
/* check the DACL for an Allowed ACE for the SYSTEM account */
|
FIELD_OFFSET(RTL_BSD_DATA, Checksum),
|
||||||
AceIndex = 0;
|
sizeof(&DummyBsd->Checksum)
|
||||||
do
|
}, // RtlBsdItemChecksum
|
||||||
{
|
};
|
||||||
Status = RtlGetAce(Dacl,
|
|
||||||
AceIndex++,
|
|
||||||
(PVOID*)&Ace);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
Ace = NULL;
|
|
||||||
}
|
|
||||||
else if (Ace != NULL && Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
|
||||||
{
|
|
||||||
/* check if the the ACE is a set of allowed permissions for the
|
|
||||||
local SYSTEM account */
|
|
||||||
if (RtlEqualSid((PSID)(Ace + 1),
|
|
||||||
LocalSystemSid))
|
|
||||||
{
|
|
||||||
/* check if the ACE is inherited by noncontainer and
|
|
||||||
container objects, if not attempt to change that */
|
|
||||||
if (!(Ace->Header.AceFlags & OBJECT_INHERIT_ACE) ||
|
|
||||||
!(Ace->Header.AceFlags & CONTAINER_INHERIT_ACE))
|
|
||||||
{
|
|
||||||
Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
|
|
||||||
Status = ZwSetSecurityObject(DirectoryHandle,
|
|
||||||
DACL_SECURITY_INFORMATION,
|
|
||||||
RelSD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* all done, we have access */
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (Ace != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
AbsSDSize = DescriptorSize;
|
|
||||||
|
|
||||||
/* because we need to change any existing data we need to convert it to
|
|
||||||
an absolute security descriptor first */
|
|
||||||
Status = RtlSelfRelativeToAbsoluteSD2(RelSD,
|
|
||||||
&AbsSDSize);
|
|
||||||
#ifdef _WIN64
|
|
||||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
|
||||||
{
|
|
||||||
/* this error code can only be returned on 64 bit builds because
|
|
||||||
the size of an absolute security descriptor is greater than the
|
|
||||||
size of a self-relative security descriptor */
|
|
||||||
ASSERT(AbsSDSize > DescriptorSize);
|
|
||||||
|
|
||||||
AbsSD = RtlpAllocateMemory(DescriptorSize,
|
|
||||||
'dSeS');
|
|
||||||
if (AbsSD == NULL)
|
|
||||||
{
|
|
||||||
Status = STATUS_NO_MEMORY;
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbsSDAllocated = TRUE;
|
|
||||||
|
|
||||||
/* make a raw copy of the self-relative descriptor */
|
|
||||||
RtlCopyMemory(AbsSD,
|
|
||||||
RelSD,
|
|
||||||
DescriptorSize);
|
|
||||||
|
|
||||||
/* finally convert it */
|
|
||||||
Status = RtlSelfRelativeToAbsoluteSD2(AbsSD,
|
|
||||||
&AbsSDSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
AbsSD = RelSD;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the owner SID */
|
|
||||||
Status = RtlSetOwnerSecurityDescriptor(AbsSD,
|
|
||||||
AdminSid,
|
|
||||||
FALSE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the DACL in the security descriptor */
|
|
||||||
Status = RtlSetDaclSecurityDescriptor(AbsSD,
|
|
||||||
TRUE,
|
|
||||||
SecurityDescriptor->Dacl,
|
|
||||||
FALSE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert it back to a self-relative descriptor, find out how much
|
|
||||||
memory we need */
|
|
||||||
Status = RtlAbsoluteToSelfRelativeSD(AbsSD,
|
|
||||||
NULL,
|
|
||||||
&RelSDSize);
|
|
||||||
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate enough memory for the new self-relative descriptor */
|
|
||||||
NewRelSD = RtlpAllocateMemory(RelSDSize,
|
|
||||||
'dSeS');
|
|
||||||
if (NewRelSD == NULL)
|
|
||||||
{
|
|
||||||
Status = STATUS_NO_MEMORY;
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert the security descriptor to self-relative format */
|
|
||||||
Status = RtlAbsoluteToSelfRelativeSD(AbsSD,
|
|
||||||
NewRelSD,
|
|
||||||
&RelSDSize);
|
|
||||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* finally attempt to change the security information */
|
|
||||||
Status = ZwSetSecurityObject(DirectoryHandle,
|
|
||||||
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
|
||||||
NewRelSD);
|
|
||||||
|
|
||||||
Cleanup:
|
|
||||||
if (AdminSid != NULL)
|
|
||||||
{
|
|
||||||
RtlFreeSid(AdminSid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LocalSystemSid != NULL)
|
|
||||||
{
|
|
||||||
RtlFreeSid(LocalSystemSid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RelSD != NULL)
|
|
||||||
{
|
|
||||||
RtlpFreeMemory(RelSD,
|
|
||||||
'dSeS');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NewRelSD != NULL)
|
|
||||||
{
|
|
||||||
RtlpFreeMemory(NewRelSD,
|
|
||||||
'dSeS');
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN64
|
|
||||||
if (AbsSDAllocated)
|
|
||||||
{
|
|
||||||
RtlpFreeMemory(AbsSD,
|
|
||||||
'dSeS');
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath,
|
|
||||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
|
||||||
{
|
|
||||||
TOKEN_PRIVILEGES TokenPrivileges;
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
SECURITY_DESCRIPTOR AbsSD;
|
|
||||||
PSID AdminSid = NULL;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
BOOLEAN TokenEnabled = FALSE;
|
|
||||||
HANDLE hToken = NULL;
|
|
||||||
HANDLE hDirectory = NULL;
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG ReturnLength;
|
|
||||||
|
|
||||||
Status = ZwOpenProcessToken(NtCurrentProcess(),
|
|
||||||
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
|
||||||
&hToken);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */
|
|
||||||
TokenPrivileges.PrivilegeCount = 1;
|
|
||||||
TokenPrivileges.Privileges[0].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
|
|
||||||
TokenPrivileges.Privileges[0].Luid.HighPart = 0;
|
|
||||||
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
Status = ZwAdjustPrivilegesToken(hToken,
|
|
||||||
FALSE,
|
|
||||||
&TokenPrivileges,
|
|
||||||
sizeof(TokenPrivileges),
|
|
||||||
&TokenPrivileges,
|
|
||||||
&ReturnLength);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
TokenEnabled = (TokenPrivileges.PrivilegeCount != 0);
|
|
||||||
|
|
||||||
/* open the directory */
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
DirectoryPath,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
SecurityDescriptor);
|
|
||||||
|
|
||||||
Status = ZwOpenFile(&hDirectory,
|
|
||||||
SYNCHRONIZE | WRITE_OWNER,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the Administrators SID */
|
|
||||||
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
|
||||||
2,
|
|
||||||
SECURITY_BUILTIN_DOMAIN_RID,
|
|
||||||
DOMAIN_ALIAS_RID_ADMINS,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
&AdminSid);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the security descriptor */
|
|
||||||
Status = RtlCreateSecurityDescriptor(&AbsSD,
|
|
||||||
SECURITY_DESCRIPTOR_REVISION);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = RtlSetOwnerSecurityDescriptor(&AbsSD,
|
|
||||||
AdminSid,
|
|
||||||
FALSE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto Cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attempt to take ownership */
|
|
||||||
Status = ZwSetSecurityObject(hDirectory,
|
|
||||||
OWNER_SECURITY_INFORMATION,
|
|
||||||
&AbsSD);
|
|
||||||
|
|
||||||
Cleanup:
|
|
||||||
if (TokenEnabled)
|
|
||||||
{
|
|
||||||
ZwAdjustPrivilegesToken(hToken,
|
|
||||||
FALSE,
|
|
||||||
&TokenPrivileges,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AdminSid != NULL)
|
|
||||||
{
|
|
||||||
RtlFreeSid(AdminSid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hDirectory != NULL)
|
|
||||||
{
|
|
||||||
ZwClose(hDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hToken != NULL)
|
|
||||||
{
|
|
||||||
ZwClose(hToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath)
|
RtlCreateBootStatusDataFile (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
|
||||||
HANDLE hDirectory;
|
|
||||||
UNICODE_STRING DirectoryName, NewPath;
|
|
||||||
ULONG PathLen;
|
|
||||||
PISECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
||||||
PSID SystemSid = NULL;
|
|
||||||
BOOLEAN AddSep = FALSE;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
PAGED_CODE_RTL();
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&DirectoryName,
|
|
||||||
L"System Volume Information");
|
|
||||||
|
|
||||||
PathLen = VolumeRootPath->Length + DirectoryName.Length;
|
|
||||||
|
|
||||||
/* make sure we don't overflow while appending the strings */
|
|
||||||
if (PathLen > 0xFFFC)
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VolumeRootPath->Buffer[(VolumeRootPath->Length / sizeof(WCHAR)) - 1] != L'\\')
|
|
||||||
{
|
|
||||||
AddSep = TRUE;
|
|
||||||
PathLen += sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate the new string */
|
|
||||||
NewPath.MaximumLength = (USHORT)PathLen + sizeof(WCHAR);
|
|
||||||
NewPath.Buffer = RtlpAllocateStringMemory(NewPath.MaximumLength,
|
|
||||||
TAG_USTR);
|
|
||||||
if (NewPath.Buffer == NULL)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the new path string */
|
|
||||||
NewPath.Length = VolumeRootPath->Length;
|
|
||||||
RtlCopyMemory(NewPath.Buffer,
|
|
||||||
VolumeRootPath->Buffer,
|
|
||||||
NewPath.Length);
|
|
||||||
if (AddSep)
|
|
||||||
{
|
|
||||||
NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\\';
|
|
||||||
NewPath.Length += sizeof(WCHAR);
|
|
||||||
}
|
|
||||||
RtlCopyMemory(NewPath.Buffer + (NewPath.Length / sizeof(WCHAR)),
|
|
||||||
DirectoryName.Buffer,
|
|
||||||
DirectoryName.Length);
|
|
||||||
NewPath.Length += DirectoryName.Length;
|
|
||||||
NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\0';
|
|
||||||
|
|
||||||
ASSERT(NewPath.Length == PathLen);
|
|
||||||
ASSERT(NewPath.Length == NewPath.MaximumLength - sizeof(WCHAR));
|
|
||||||
|
|
||||||
/* create the security descriptor for the new directory */
|
|
||||||
Status = RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor,
|
|
||||||
&SystemSid);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* create or open the directory */
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&NewPath,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
SecurityDescriptor);
|
|
||||||
|
|
||||||
Status = ZwCreateFile(&hDirectory,
|
|
||||||
SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
NULL,
|
|
||||||
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
FILE_OPEN_IF,
|
|
||||||
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
||||||
NULL,
|
|
||||||
0);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
Status = RtlpSysVolTakeOwnership(&NewPath,
|
|
||||||
SecurityDescriptor);
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* successfully took ownership, attempt to open it */
|
|
||||||
Status = ZwCreateFile(&hDirectory,
|
|
||||||
SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
NULL,
|
|
||||||
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
||||||
FILE_OPEN_IF,
|
|
||||||
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
||||||
NULL,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* check security now and adjust it if neccessary */
|
|
||||||
Status = RtlpSysVolCheckOwnerAndSecurity(hDirectory,
|
|
||||||
SecurityDescriptor);
|
|
||||||
ZwClose(hDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free allocated memory */
|
|
||||||
ASSERT(SecurityDescriptor != NULL);
|
|
||||||
ASSERT(SecurityDescriptor->Dacl != NULL);
|
|
||||||
|
|
||||||
RtlpFreeMemory(SecurityDescriptor->Dacl,
|
|
||||||
'cAeS');
|
|
||||||
RtlpFreeMemory(SecurityDescriptor,
|
|
||||||
'dSeS');
|
|
||||||
|
|
||||||
RtlFreeSid(SystemSid);
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlpFreeStringMemory(NewPath.Buffer,
|
|
||||||
TAG_USTR);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
RtlCreateBootStatusDataFile(VOID)
|
|
||||||
{
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
LARGE_INTEGER AllocationSize;
|
LARGE_INTEGER AllocationSize;
|
||||||
LARGE_INTEGER ByteOffset;
|
LARGE_INTEGER ByteOffset;
|
||||||
UNICODE_STRING FileName;
|
UNICODE_STRING FileName =
|
||||||
|
RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat");
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes =
|
||||||
|
RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE);
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
RTL_BSD_DATA InitialBsd;
|
||||||
/* Initialize the file name */
|
|
||||||
RtlInitUnicodeString(&FileName,
|
|
||||||
L"\\SystemRoot\\bootstat.dat");
|
|
||||||
|
|
||||||
/* Initialize the object attributes */
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&FileName,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
AllocationSize.QuadPart = 0x800;
|
|
||||||
DBG_UNREFERENCED_LOCAL_VARIABLE(AllocationSize);
|
|
||||||
|
|
||||||
/* Create the boot status data file */
|
/* Create the boot status data file */
|
||||||
|
AllocationSize.QuadPart = 0x800;
|
||||||
|
DBG_UNREFERENCED_LOCAL_VARIABLE(AllocationSize);
|
||||||
Status = ZwCreateFile(&FileHandle,
|
Status = ZwCreateFile(&FileHandle,
|
||||||
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
|
@ -723,17 +126,23 @@ RtlCreateBootStatusDataFile(VOID)
|
||||||
0);
|
0);
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
// FIXME: Initialize the buffer in a better way.
|
/* Setup a sane looking initial BSD */
|
||||||
UCHAR Buffer[12] = {0xC,0,0,0, 1,0,0,0, 1, 0x1e, 1, 0};
|
RtlZeroMemory(&InitialBsd, sizeof(InitialBsd));
|
||||||
|
InitialBsd.Version = sizeof(InitialBsd);
|
||||||
|
InitialBsd.ProductType = NtProductWinNt;
|
||||||
|
InitialBsd.AabEnabled = 1;
|
||||||
|
InitialBsd.AabTimeout = 30;
|
||||||
|
InitialBsd.LastBootSucceeded = TRUE;
|
||||||
|
|
||||||
|
/* Write it to disk */
|
||||||
ByteOffset.QuadPart = 0;
|
ByteOffset.QuadPart = 0;
|
||||||
Status = ZwWriteFile(FileHandle,
|
Status = ZwWriteFile(FileHandle,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
&Buffer,
|
&InitialBsd,
|
||||||
12, //BufferSize,
|
sizeof(InitialBsd),
|
||||||
&ByteOffset,
|
&ByteOffset,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -745,34 +154,40 @@ RtlCreateBootStatusDataFile(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlGetSetBootStatusData(IN HANDLE FileHandle,
|
RtlGetSetBootStatusData (
|
||||||
IN BOOLEAN WriteMode,
|
_In_ HANDLE FileHandle,
|
||||||
IN RTL_BSD_ITEM_TYPE DataClass,
|
_In_ BOOLEAN Read,
|
||||||
IN PVOID Buffer,
|
_In_ RTL_BSD_ITEM_TYPE DataClass,
|
||||||
IN ULONG BufferSize,
|
_In_ PVOID Buffer,
|
||||||
OUT PULONG ReturnLength)
|
_In_ ULONG BufferSize,
|
||||||
|
_Out_opt_ PULONG ReturnLength
|
||||||
|
)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
LARGE_INTEGER ByteOffset;
|
LARGE_INTEGER ByteOffset;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("RtlGetSetBootStatusData (%p %u %d %p %lu %p)\n",
|
DPRINT("RtlGetSetBootStatusData (%p %u %d %p %lu %p)\n",
|
||||||
FileHandle, WriteMode, DataClass, Buffer, BufferSize, ReturnLength);
|
FileHandle, Read, DataClass, Buffer, BufferSize, ReturnLength);
|
||||||
|
|
||||||
if (DataClass >= RtlBsdItemMax)
|
if (DataClass >= RtlBsdItemMax)
|
||||||
|
{
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
if (BufferSize > BsdItemTable[DataClass].Size)
|
if (BufferSize > BsdItemTable[DataClass].Size)
|
||||||
|
{
|
||||||
return STATUS_BUFFER_TOO_SMALL;
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
ByteOffset.HighPart = 0;
|
ByteOffset.HighPart = 0;
|
||||||
ByteOffset.LowPart = BsdItemTable[DataClass].Offset;
|
ByteOffset.LowPart = BsdItemTable[DataClass].Offset;
|
||||||
|
|
||||||
if (WriteMode)
|
if (Read)
|
||||||
{
|
{
|
||||||
Status = ZwReadFile(FileHandle,
|
Status = ZwReadFile(FileHandle,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -800,39 +215,34 @@ RtlGetSetBootStatusData(IN HANDLE FileHandle,
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
if (ReturnLength)
|
if (ReturnLength)
|
||||||
|
{
|
||||||
*ReturnLength = BsdItemTable[DataClass].Size;
|
*ReturnLength = BsdItemTable[DataClass].Size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlLockBootStatusData(OUT PHANDLE FileHandle)
|
RtlLockBootStatusData (
|
||||||
|
_Out_ PHANDLE FileHandle
|
||||||
|
)
|
||||||
{
|
{
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
UNICODE_STRING FileName =
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat");
|
||||||
UNICODE_STRING FileName;
|
OBJECT_ATTRIBUTES ObjectAttributes =
|
||||||
|
RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE);
|
||||||
HANDLE LocalFileHandle;
|
HANDLE LocalFileHandle;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
|
||||||
/* Intialize the file handle */
|
/* Intialize the file handle */
|
||||||
*FileHandle = NULL;
|
*FileHandle = NULL;
|
||||||
|
|
||||||
/* Initialize the file name */
|
|
||||||
RtlInitUnicodeString(&FileName,
|
|
||||||
L"\\SystemRoot\\bootstat.dat");
|
|
||||||
|
|
||||||
/* Initialize the object attributes */
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&FileName,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* Open the boot status data file */
|
/* Open the boot status data file */
|
||||||
Status = ZwOpenFile(&LocalFileHandle,
|
Status = ZwOpenFile(&LocalFileHandle,
|
||||||
FILE_ALL_ACCESS,
|
FILE_ALL_ACCESS,
|
||||||
|
@ -850,18 +260,18 @@ RtlLockBootStatusData(OUT PHANDLE FileHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlUnlockBootStatusData(IN HANDLE FileHandle)
|
RtlUnlockBootStatusData (
|
||||||
|
_In_ HANDLE FileHandle
|
||||||
|
)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
|
||||||
/* Flush the file and close it */
|
/* Flush the file and close it */
|
||||||
ZwFlushBuffersFile(FileHandle,
|
ZwFlushBuffersFile(FileHandle, &IoStatusBlock);
|
||||||
&IoStatusBlock);
|
|
||||||
|
|
||||||
return ZwClose(FileHandle);
|
return ZwClose(FileHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
674
sdk/lib/rtl/sysvol.c
Normal file
674
sdk/lib/rtl/sysvol.c
Normal file
|
@ -0,0 +1,674 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* PURPOSE: Boot Data implementation
|
||||||
|
* FILE: lib/rtl/bootdata.c
|
||||||
|
* PROGRAMMERS:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <rtl.h>
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = {SECURITY_NT_AUTHORITY};
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
RtlpSysVolCreateSecurityDescriptor(OUT PISECURITY_DESCRIPTOR *SecurityDescriptor,
|
||||||
|
OUT PSID *SystemSid)
|
||||||
|
{
|
||||||
|
PSECURITY_DESCRIPTOR AbsSD = NULL;
|
||||||
|
PSID LocalSystemSid = NULL;
|
||||||
|
PACL Dacl = NULL;
|
||||||
|
ULONG DaclSize;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* create the local SYSTEM SID */
|
||||||
|
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
||||||
|
1,
|
||||||
|
SECURITY_LOCAL_SYSTEM_RID,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&LocalSystemSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate and initialize the security descriptor */
|
||||||
|
AbsSD = RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR),
|
||||||
|
'dSeS');
|
||||||
|
if (AbsSD == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlCreateSecurityDescriptor(AbsSD,
|
||||||
|
SECURITY_DESCRIPTOR_REVISION);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate and create the DACL */
|
||||||
|
DaclSize = sizeof(ACL) + sizeof(ACE) +
|
||||||
|
RtlLengthSid(LocalSystemSid);
|
||||||
|
Dacl = RtlpAllocateMemory(DaclSize,
|
||||||
|
'cAeS');
|
||||||
|
if (Dacl == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlCreateAcl(Dacl,
|
||||||
|
DaclSize,
|
||||||
|
ACL_REVISION);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlAddAccessAllowedAceEx(Dacl,
|
||||||
|
ACL_REVISION,
|
||||||
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
|
||||||
|
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
|
||||||
|
LocalSystemSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the DACL in the security descriptor */
|
||||||
|
Status = RtlSetDaclSecurityDescriptor(AbsSD,
|
||||||
|
TRUE,
|
||||||
|
Dacl,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
/* all done */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
*SecurityDescriptor = AbsSD;
|
||||||
|
*SystemSid = LocalSystemSid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Cleanup:
|
||||||
|
if (LocalSystemSid != NULL)
|
||||||
|
{
|
||||||
|
RtlFreeSid(LocalSystemSid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Dacl != NULL)
|
||||||
|
{
|
||||||
|
RtlpFreeMemory(Dacl,
|
||||||
|
'cAeS');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AbsSD != NULL)
|
||||||
|
{
|
||||||
|
RtlpFreeMemory(AbsSD,
|
||||||
|
'dSeS');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle,
|
||||||
|
IN PISECURITY_DESCRIPTOR SecurityDescriptor)
|
||||||
|
{
|
||||||
|
PSECURITY_DESCRIPTOR RelSD = NULL;
|
||||||
|
PSECURITY_DESCRIPTOR NewRelSD = NULL;
|
||||||
|
PSECURITY_DESCRIPTOR AbsSD = NULL;
|
||||||
|
#ifdef _WIN64
|
||||||
|
BOOLEAN AbsSDAllocated = FALSE;
|
||||||
|
#endif
|
||||||
|
PSID AdminSid = NULL;
|
||||||
|
PSID LocalSystemSid = NULL;
|
||||||
|
ULONG DescriptorSize;
|
||||||
|
ULONG AbsSDSize, RelSDSize = 0;
|
||||||
|
PACL Dacl;
|
||||||
|
BOOLEAN DaclPresent, DaclDefaulted;
|
||||||
|
PSID OwnerSid;
|
||||||
|
BOOLEAN OwnerDefaulted;
|
||||||
|
ULONG AceIndex;
|
||||||
|
PACE Ace = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* find out how much memory we need to allocate for the self-relative
|
||||||
|
descriptor we're querying */
|
||||||
|
Status = ZwQuerySecurityObject(DirectoryHandle,
|
||||||
|
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&DescriptorSize);
|
||||||
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
/* looks like the FS doesn't support security... return success */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate enough memory for the security descriptor */
|
||||||
|
RelSD = RtlpAllocateMemory(DescriptorSize,
|
||||||
|
'dSeS');
|
||||||
|
if (RelSD == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the self-relative security descriptor */
|
||||||
|
Status = ZwQuerySecurityObject(DirectoryHandle,
|
||||||
|
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||||
|
RelSD,
|
||||||
|
DescriptorSize,
|
||||||
|
&DescriptorSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* FIXME - handle the case where someone else modified the owner and/or
|
||||||
|
DACL while we allocated memory. But that should be *very*
|
||||||
|
unlikely.... */
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the owner and DACL from the descriptor */
|
||||||
|
Status = RtlGetOwnerSecurityDescriptor(RelSD,
|
||||||
|
&OwnerSid,
|
||||||
|
&OwnerDefaulted);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlGetDaclSecurityDescriptor(RelSD,
|
||||||
|
&DaclPresent,
|
||||||
|
&Dacl,
|
||||||
|
&DaclDefaulted);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the Administrators SID */
|
||||||
|
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
||||||
|
2,
|
||||||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||||||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&AdminSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the local SYSTEM SID */
|
||||||
|
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
||||||
|
1,
|
||||||
|
SECURITY_LOCAL_SYSTEM_RID,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&LocalSystemSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the Administrators are the owner and at least a not-NULL DACL
|
||||||
|
is present */
|
||||||
|
if (OwnerSid != NULL &&
|
||||||
|
RtlEqualSid(OwnerSid,
|
||||||
|
AdminSid) &&
|
||||||
|
DaclPresent && Dacl != NULL)
|
||||||
|
{
|
||||||
|
/* check the DACL for an Allowed ACE for the SYSTEM account */
|
||||||
|
AceIndex = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Status = RtlGetAce(Dacl,
|
||||||
|
AceIndex++,
|
||||||
|
(PVOID*)&Ace);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Ace = NULL;
|
||||||
|
}
|
||||||
|
else if (Ace != NULL && Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
{
|
||||||
|
/* check if the the ACE is a set of allowed permissions for the
|
||||||
|
local SYSTEM account */
|
||||||
|
if (RtlEqualSid((PSID)(Ace + 1),
|
||||||
|
LocalSystemSid))
|
||||||
|
{
|
||||||
|
/* check if the ACE is inherited by noncontainer and
|
||||||
|
container objects, if not attempt to change that */
|
||||||
|
if (!(Ace->Header.AceFlags & OBJECT_INHERIT_ACE) ||
|
||||||
|
!(Ace->Header.AceFlags & CONTAINER_INHERIT_ACE))
|
||||||
|
{
|
||||||
|
Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
|
||||||
|
Status = ZwSetSecurityObject(DirectoryHandle,
|
||||||
|
DACL_SECURITY_INFORMATION,
|
||||||
|
RelSD);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* all done, we have access */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (Ace != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
AbsSDSize = DescriptorSize;
|
||||||
|
|
||||||
|
/* because we need to change any existing data we need to convert it to
|
||||||
|
an absolute security descriptor first */
|
||||||
|
Status = RtlSelfRelativeToAbsoluteSD2(RelSD,
|
||||||
|
&AbsSDSize);
|
||||||
|
#ifdef _WIN64
|
||||||
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
/* this error code can only be returned on 64 bit builds because
|
||||||
|
the size of an absolute security descriptor is greater than the
|
||||||
|
size of a self-relative security descriptor */
|
||||||
|
ASSERT(AbsSDSize > DescriptorSize);
|
||||||
|
|
||||||
|
AbsSD = RtlpAllocateMemory(DescriptorSize,
|
||||||
|
'dSeS');
|
||||||
|
if (AbsSD == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbsSDAllocated = TRUE;
|
||||||
|
|
||||||
|
/* make a raw copy of the self-relative descriptor */
|
||||||
|
RtlCopyMemory(AbsSD,
|
||||||
|
RelSD,
|
||||||
|
DescriptorSize);
|
||||||
|
|
||||||
|
/* finally convert it */
|
||||||
|
Status = RtlSelfRelativeToAbsoluteSD2(AbsSD,
|
||||||
|
&AbsSDSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
AbsSD = RelSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the owner SID */
|
||||||
|
Status = RtlSetOwnerSecurityDescriptor(AbsSD,
|
||||||
|
AdminSid,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the DACL in the security descriptor */
|
||||||
|
Status = RtlSetDaclSecurityDescriptor(AbsSD,
|
||||||
|
TRUE,
|
||||||
|
SecurityDescriptor->Dacl,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert it back to a self-relative descriptor, find out how much
|
||||||
|
memory we need */
|
||||||
|
Status = RtlAbsoluteToSelfRelativeSD(AbsSD,
|
||||||
|
NULL,
|
||||||
|
&RelSDSize);
|
||||||
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate enough memory for the new self-relative descriptor */
|
||||||
|
NewRelSD = RtlpAllocateMemory(RelSDSize,
|
||||||
|
'dSeS');
|
||||||
|
if (NewRelSD == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert the security descriptor to self-relative format */
|
||||||
|
Status = RtlAbsoluteToSelfRelativeSD(AbsSD,
|
||||||
|
NewRelSD,
|
||||||
|
&RelSDSize);
|
||||||
|
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* finally attempt to change the security information */
|
||||||
|
Status = ZwSetSecurityObject(DirectoryHandle,
|
||||||
|
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||||
|
NewRelSD);
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if (AdminSid != NULL)
|
||||||
|
{
|
||||||
|
RtlFreeSid(AdminSid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LocalSystemSid != NULL)
|
||||||
|
{
|
||||||
|
RtlFreeSid(LocalSystemSid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RelSD != NULL)
|
||||||
|
{
|
||||||
|
RtlpFreeMemory(RelSD,
|
||||||
|
'dSeS');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewRelSD != NULL)
|
||||||
|
{
|
||||||
|
RtlpFreeMemory(NewRelSD,
|
||||||
|
'dSeS');
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
if (AbsSDAllocated)
|
||||||
|
{
|
||||||
|
RtlpFreeMemory(AbsSD,
|
||||||
|
'dSeS');
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath,
|
||||||
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||||
|
{
|
||||||
|
TOKEN_PRIVILEGES TokenPrivileges;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
SECURITY_DESCRIPTOR AbsSD;
|
||||||
|
PSID AdminSid = NULL;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
BOOLEAN TokenEnabled = FALSE;
|
||||||
|
HANDLE hToken = NULL;
|
||||||
|
HANDLE hDirectory = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG ReturnLength;
|
||||||
|
|
||||||
|
Status = ZwOpenProcessToken(NtCurrentProcess(),
|
||||||
|
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||||
|
&hToken);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */
|
||||||
|
TokenPrivileges.PrivilegeCount = 1;
|
||||||
|
TokenPrivileges.Privileges[0].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
|
||||||
|
TokenPrivileges.Privileges[0].Luid.HighPart = 0;
|
||||||
|
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
Status = ZwAdjustPrivilegesToken(hToken,
|
||||||
|
FALSE,
|
||||||
|
&TokenPrivileges,
|
||||||
|
sizeof(TokenPrivileges),
|
||||||
|
&TokenPrivileges,
|
||||||
|
&ReturnLength);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
TokenEnabled = (TokenPrivileges.PrivilegeCount != 0);
|
||||||
|
|
||||||
|
/* open the directory */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
DirectoryPath,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
SecurityDescriptor);
|
||||||
|
|
||||||
|
Status = ZwOpenFile(&hDirectory,
|
||||||
|
SYNCHRONIZE | WRITE_OWNER,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the Administrators SID */
|
||||||
|
Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority,
|
||||||
|
2,
|
||||||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||||||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&AdminSid);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the security descriptor */
|
||||||
|
Status = RtlCreateSecurityDescriptor(&AbsSD,
|
||||||
|
SECURITY_DESCRIPTOR_REVISION);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = RtlSetOwnerSecurityDescriptor(&AbsSD,
|
||||||
|
AdminSid,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to take ownership */
|
||||||
|
Status = ZwSetSecurityObject(hDirectory,
|
||||||
|
OWNER_SECURITY_INFORMATION,
|
||||||
|
&AbsSD);
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if (TokenEnabled)
|
||||||
|
{
|
||||||
|
ZwAdjustPrivilegesToken(hToken,
|
||||||
|
FALSE,
|
||||||
|
&TokenPrivileges,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AdminSid != NULL)
|
||||||
|
{
|
||||||
|
RtlFreeSid(AdminSid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hDirectory != NULL)
|
||||||
|
{
|
||||||
|
ZwClose(hDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hToken != NULL)
|
||||||
|
{
|
||||||
|
ZwClose(hToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
RtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath)
|
||||||
|
{
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
HANDLE hDirectory;
|
||||||
|
UNICODE_STRING DirectoryName, NewPath;
|
||||||
|
ULONG PathLen;
|
||||||
|
PISECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
||||||
|
PSID SystemSid = NULL;
|
||||||
|
BOOLEAN AddSep = FALSE;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
PAGED_CODE_RTL();
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&DirectoryName,
|
||||||
|
L"System Volume Information");
|
||||||
|
|
||||||
|
PathLen = VolumeRootPath->Length + DirectoryName.Length;
|
||||||
|
|
||||||
|
/* make sure we don't overflow while appending the strings */
|
||||||
|
if (PathLen > 0xFFFC)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VolumeRootPath->Buffer[(VolumeRootPath->Length / sizeof(WCHAR)) - 1] != L'\\')
|
||||||
|
{
|
||||||
|
AddSep = TRUE;
|
||||||
|
PathLen += sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate the new string */
|
||||||
|
NewPath.MaximumLength = (USHORT)PathLen + sizeof(WCHAR);
|
||||||
|
NewPath.Buffer = RtlpAllocateStringMemory(NewPath.MaximumLength,
|
||||||
|
TAG_USTR);
|
||||||
|
if (NewPath.Buffer == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the new path string */
|
||||||
|
NewPath.Length = VolumeRootPath->Length;
|
||||||
|
RtlCopyMemory(NewPath.Buffer,
|
||||||
|
VolumeRootPath->Buffer,
|
||||||
|
NewPath.Length);
|
||||||
|
if (AddSep)
|
||||||
|
{
|
||||||
|
NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\\';
|
||||||
|
NewPath.Length += sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
RtlCopyMemory(NewPath.Buffer + (NewPath.Length / sizeof(WCHAR)),
|
||||||
|
DirectoryName.Buffer,
|
||||||
|
DirectoryName.Length);
|
||||||
|
NewPath.Length += DirectoryName.Length;
|
||||||
|
NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
ASSERT(NewPath.Length == PathLen);
|
||||||
|
ASSERT(NewPath.Length == NewPath.MaximumLength - sizeof(WCHAR));
|
||||||
|
|
||||||
|
/* create the security descriptor for the new directory */
|
||||||
|
Status = RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor,
|
||||||
|
&SystemSid);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* create or open the directory */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&NewPath,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
SecurityDescriptor);
|
||||||
|
|
||||||
|
Status = ZwCreateFile(&hDirectory,
|
||||||
|
SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
FILE_OPEN_IF,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = RtlpSysVolTakeOwnership(&NewPath,
|
||||||
|
SecurityDescriptor);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* successfully took ownership, attempt to open it */
|
||||||
|
Status = ZwCreateFile(&hDirectory,
|
||||||
|
SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
FILE_OPEN_IF,
|
||||||
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* check security now and adjust it if neccessary */
|
||||||
|
Status = RtlpSysVolCheckOwnerAndSecurity(hDirectory,
|
||||||
|
SecurityDescriptor);
|
||||||
|
ZwClose(hDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free allocated memory */
|
||||||
|
ASSERT(SecurityDescriptor != NULL);
|
||||||
|
ASSERT(SecurityDescriptor->Dacl != NULL);
|
||||||
|
|
||||||
|
RtlpFreeMemory(SecurityDescriptor->Dacl,
|
||||||
|
'cAeS');
|
||||||
|
RtlpFreeMemory(SecurityDescriptor,
|
||||||
|
'dSeS');
|
||||||
|
|
||||||
|
RtlFreeSid(SystemSid);
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlpFreeStringMemory(NewPath.Buffer,
|
||||||
|
TAG_USTR);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue