Reactos

[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.

+887 -708
+97 -3
sdk/include/ndk/rtltypes.h
··· 414 414 #define RTL_CONSTANT_LARGE_INTEGER(quad_part) { { (quad_part), (quad_part)>>32 } } 415 415 #define RTL_MAKE_LARGE_INTEGER(low_part, high_part) { { (low_part), (high_part) } } 416 416 417 - 418 - #ifdef NTOS_MODE_USER 419 - 420 417 // 421 418 // Boot Status Data Field Types 422 419 // ··· 428 425 RtlBsdItemAabTimeout, 429 426 RtlBsdItemBootGood, 430 427 RtlBsdItemBootShutdown, 428 + RtlBsdSleepInProgress, 429 + RtlBsdPowerTransition, 430 + RtlBsdItemBootAttemptCount, 431 + RtlBsdItemBootCheckpoint, 432 + RtlBsdItemBootId, 433 + RtlBsdItemShutdownBootId, 434 + RtlBsdItemReportedAbnormalShutdownBootId, 435 + RtlBsdItemErrorInfo, 436 + RtlBsdItemPowerButtonPressInfo, 437 + RtlBsdItemChecksum, 431 438 RtlBsdItemMax 432 439 } RTL_BSD_ITEM_TYPE, *PRTL_BSD_ITEM_TYPE; 433 440 441 + #ifdef NTOS_MODE_USER 434 442 // 435 443 // Table and Compare result types 436 444 // ··· 1237 1245 PRTL_HANDLE_TABLE_ENTRY UnCommittedHandles; 1238 1246 PRTL_HANDLE_TABLE_ENTRY MaxReservedHandles; 1239 1247 } RTL_HANDLE_TABLE, *PRTL_HANDLE_TABLE; 1248 + 1249 + // 1250 + // RTL Boot Status Data Item 1251 + // 1252 + typedef struct _RTL_BSD_ITEM 1253 + { 1254 + RTL_BSD_ITEM_TYPE Type; 1255 + PVOID DataBuffer; 1256 + ULONG DataLength; 1257 + } RTL_BSD_ITEM, *PRTL_BSD_ITEM; 1258 + 1259 + // 1260 + // Data Sub-Structures for "bootstat.dat" RTL Data File 1261 + // 1262 + typedef struct _RTL_BSD_DATA_POWER_TRANSITION 1263 + { 1264 + LARGE_INTEGER PowerButtonTimestamp; 1265 + struct 1266 + { 1267 + UCHAR SystemRunning : 1; 1268 + UCHAR ConnectedStandbyInProgress : 1; 1269 + UCHAR UserShutdownInProgress : 1; 1270 + UCHAR SystemShutdownInProgress : 1; 1271 + UCHAR SleepInProgress : 4; 1272 + } Flags; 1273 + UCHAR ConnectedStandbyScenarioInstanceId; 1274 + UCHAR ConnectedStandbyEntryReason; 1275 + UCHAR ConnectedStandbyExitReason; 1276 + USHORT SystemSleepTransitionCount; 1277 + LARGE_INTEGER LastReferenceTime; 1278 + ULONG LastReferenceTimeChecksum; 1279 + ULONG LastUpdateBootId; 1280 + } RTL_BSD_DATA_POWER_TRANSITION, *PRTL_BSD_DATA_POWER_TRANSITION; 1281 + 1282 + typedef struct _RTL_BSD_DATA_ERROR_INFO 1283 + { 1284 + ULONG BootId; 1285 + ULONG RepeatCount; 1286 + ULONG OtherErrorCount; 1287 + ULONG Code; 1288 + ULONG OtherErrorCount2; 1289 + } RTL_BSD_DATA_ERROR_INFO, *PRTL_BSD_DATA_ERROR_INFO; 1290 + 1291 + typedef struct _RTL_BSD_POWER_BUTTON_PRESS_INFO 1292 + { 1293 + LARGE_INTEGER LastPressTime; 1294 + ULONG CumulativePressCount; 1295 + USHORT LastPressBootId; 1296 + UCHAR LastPowerWatchdogStage; 1297 + struct 1298 + { 1299 + UCHAR WatchdogArmed : 1; 1300 + UCHAR ShutdownInProgress : 1; 1301 + } Flags; 1302 + LARGE_INTEGER LastReleaseTime; 1303 + ULONG CumulativeReleaseCount; 1304 + USHORT LastReleaseBootId; 1305 + USHORT ErrorCount; 1306 + UCHAR CurrentConnectedStandbyPhase; 1307 + ULONG TransitionLatestCheckpointId; 1308 + ULONG TransitionLatestCheckpointType; 1309 + ULONG TransitionLatestCheckpointSequenceNumber; 1310 + } RTL_BSD_POWER_BUTTON_PRESS_INFO, *PRTL_BSD_POWER_BUTTON_PRESS_INFO; 1311 + 1312 + // 1313 + // Main Structure for "bootstat.dat" RTL Data File 1314 + // 1315 + typedef struct _RTL_BSD_DATA 1316 + { 1317 + ULONG Version; // RtlBsdItemVersionNumber 1318 + ULONG ProductType; // RtlBsdItemProductType 1319 + BOOLEAN AabEnabled; // RtlBsdItemAabEnabled 1320 + UCHAR AabTimeout; // RtlBsdItemAabTimeout 1321 + BOOLEAN LastBootSucceeded; // RtlBsdItemBootGood 1322 + BOOLEAN LastBootShutdown; // RtlBsdItemBootShutdown 1323 + BOOLEAN SleepInProgress; // RtlBsdSleepInProgress 1324 + RTL_BSD_DATA_POWER_TRANSITION PowerTransition; // RtlBsdPowerTransition 1325 + UCHAR BootAttemptCount; // RtlBsdItemBootAttemptCount 1326 + UCHAR LastBootCheckpoint; // RtlBsdItemBootCheckpoint 1327 + UCHAR Checksum; // RtlBsdItemChecksum 1328 + ULONG LastBootId; // RtlBsdItemBootId 1329 + ULONG LastSuccessfulShutdownBootId; // RtlBsdItemShutdownBootId 1330 + ULONG LastReportedAbnormalShutdownBootId; // RtlBsdItemReportedAbnormalShutdownBootId 1331 + RTL_BSD_DATA_ERROR_INFO ErrorInfo; // RtlBsdItemErrorInfo 1332 + RTL_BSD_POWER_BUTTON_PRESS_INFO PowerButtonPressInfo; // RtlBsdItemPowerButtonPressInfo 1333 + } RTL_BSD_DATA, *PRTL_BSD_DATA; 1240 1334 1241 1335 #ifdef NTOS_MODE_USER 1242 1336 //
+1
sdk/lib/rtl/CMakeLists.txt
··· 56 56 slist.c 57 57 sid.c 58 58 splaytree.c 59 + sysvol.c 59 60 thread.c 60 61 time.c 61 62 timezone.c
+115 -705
sdk/lib/rtl/bootdata.c
··· 1 1 /* 2 - * COPYRIGHT: See COPYING in the top level directory 3 - * PROJECT: ReactOS system libraries 4 - * PURPOSE: Boot Data implementation 2 + * PROJECT: ReactOS Runtime Library 3 + * LICENSE: See COPYING in the top level directory 5 4 * FILE: lib/rtl/bootdata.c 6 - * PROGRAMMERS: 5 + * PURPOSE: Boot Status Data Implementation 6 + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 + * Eric Kohl 7 8 */ 8 9 9 10 /* INCLUDES *****************************************************************/ 10 11 11 12 #include <rtl.h> 12 - 13 13 #define NDEBUG 14 14 #include <debug.h> 15 15 16 - typedef struct _RTL_BSD_ITEM 16 + typedef struct _RTL_BSD_ITEM_TABLE_ENTRY 17 17 { 18 - ULONG Offset; 19 - ULONG Size; 20 - } RTL_BSD_ITEM, *PRTL_BSD_ITEM; 18 + UCHAR Offset; 19 + UCHAR Size; 20 + } RTL_BSD_ITEM_TABLE_ENTRY; 21 21 22 22 /* FUNCTIONS *****************************************************************/ 23 23 24 - static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = {SECURITY_NT_AUTHORITY}; 25 - 26 - static RTL_BSD_ITEM BsdItemTable[6] = {{0, 4}, {4, 4,}, {8, 1}, {9, 1}, {10, 1}, {11, 1}}; 27 - 28 - static NTSTATUS 29 - RtlpSysVolCreateSecurityDescriptor(OUT PISECURITY_DESCRIPTOR *SecurityDescriptor, 30 - OUT PSID *SystemSid) 24 + PRTL_BSD_DATA DummyBsd; 25 + RTL_BSD_ITEM_TABLE_ENTRY BsdItemTable[RtlBsdItemMax] = 31 26 { 32 - PSECURITY_DESCRIPTOR AbsSD = NULL; 33 - PSID LocalSystemSid = NULL; 34 - PACL Dacl = NULL; 35 - ULONG DaclSize; 36 - NTSTATUS Status; 37 - 38 - /* create the local SYSTEM SID */ 39 - Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 40 - 1, 41 - SECURITY_LOCAL_SYSTEM_RID, 42 - 0, 43 - 0, 44 - 0, 45 - 0, 46 - 0, 47 - 0, 48 - 0, 49 - &LocalSystemSid); 50 - if (!NT_SUCCESS(Status)) 51 - { 52 - return Status; 53 - } 54 - 55 - /* allocate and initialize the security descriptor */ 56 - AbsSD = RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR), 57 - 'dSeS'); 58 - if (AbsSD == NULL) 59 - { 60 - Status = STATUS_NO_MEMORY; 61 - goto Cleanup; 62 - } 63 - 64 - Status = RtlCreateSecurityDescriptor(AbsSD, 65 - SECURITY_DESCRIPTOR_REVISION); 66 - if (!NT_SUCCESS(Status)) 67 - { 68 - goto Cleanup; 69 - } 70 - 71 - /* allocate and create the DACL */ 72 - DaclSize = sizeof(ACL) + sizeof(ACE) + 73 - RtlLengthSid(LocalSystemSid); 74 - Dacl = RtlpAllocateMemory(DaclSize, 75 - 'cAeS'); 76 - if (Dacl == NULL) 77 - { 78 - Status = STATUS_NO_MEMORY; 79 - goto Cleanup; 80 - } 81 - 82 - Status = RtlCreateAcl(Dacl, 83 - DaclSize, 84 - ACL_REVISION); 85 - if (!NT_SUCCESS(Status)) 86 - { 87 - goto Cleanup; 88 - } 89 - 90 - Status = RtlAddAccessAllowedAceEx(Dacl, 91 - ACL_REVISION, 92 - OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, 93 - STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, 94 - LocalSystemSid); 95 - if (!NT_SUCCESS(Status)) 96 - { 97 - goto Cleanup; 98 - } 99 - 100 - /* set the DACL in the security descriptor */ 101 - Status = RtlSetDaclSecurityDescriptor(AbsSD, 102 - TRUE, 103 - Dacl, 104 - FALSE); 105 - 106 - /* all done */ 107 - if (NT_SUCCESS(Status)) 108 - { 109 - *SecurityDescriptor = AbsSD; 110 - *SystemSid = LocalSystemSid; 111 - } 112 - else 113 - { 114 - Cleanup: 115 - if (LocalSystemSid != NULL) 116 - { 117 - RtlFreeSid(LocalSystemSid); 118 - } 119 - 120 - if (Dacl != NULL) 121 - { 122 - RtlpFreeMemory(Dacl, 123 - 'cAeS'); 124 - } 125 - 126 - if (AbsSD != NULL) 127 - { 128 - RtlpFreeMemory(AbsSD, 129 - 'dSeS'); 130 - } 131 - } 132 - 133 - return Status; 134 - } 135 - 136 - static NTSTATUS 137 - RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle, 138 - IN PISECURITY_DESCRIPTOR SecurityDescriptor) 139 - { 140 - PSECURITY_DESCRIPTOR RelSD = NULL; 141 - PSECURITY_DESCRIPTOR NewRelSD = NULL; 142 - PSECURITY_DESCRIPTOR AbsSD = NULL; 143 - #ifdef _WIN64 144 - BOOLEAN AbsSDAllocated = FALSE; 145 - #endif 146 - PSID AdminSid = NULL; 147 - PSID LocalSystemSid = NULL; 148 - ULONG DescriptorSize; 149 - ULONG AbsSDSize, RelSDSize = 0; 150 - PACL Dacl; 151 - BOOLEAN DaclPresent, DaclDefaulted; 152 - PSID OwnerSid; 153 - BOOLEAN OwnerDefaulted; 154 - ULONG AceIndex; 155 - PACE Ace = NULL; 156 - NTSTATUS Status; 157 - 158 - /* find out how much memory we need to allocate for the self-relative 159 - descriptor we're querying */ 160 - Status = ZwQuerySecurityObject(DirectoryHandle, 161 - OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 162 - NULL, 163 - 0, 164 - &DescriptorSize); 165 - if (Status != STATUS_BUFFER_TOO_SMALL) 166 - { 167 - /* looks like the FS doesn't support security... return success */ 168 - Status = STATUS_SUCCESS; 169 - goto Cleanup; 170 - } 171 - 172 - /* allocate enough memory for the security descriptor */ 173 - RelSD = RtlpAllocateMemory(DescriptorSize, 174 - 'dSeS'); 175 - if (RelSD == NULL) 176 - { 177 - Status = STATUS_NO_MEMORY; 178 - goto Cleanup; 179 - } 180 - 181 - /* query the self-relative security descriptor */ 182 - Status = ZwQuerySecurityObject(DirectoryHandle, 183 - OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 184 - RelSD, 185 - DescriptorSize, 186 - &DescriptorSize); 187 - if (!NT_SUCCESS(Status)) 188 - { 189 - /* FIXME - handle the case where someone else modified the owner and/or 190 - DACL while we allocated memory. But that should be *very* 191 - unlikely.... */ 192 - goto Cleanup; 193 - } 194 - 195 - /* query the owner and DACL from the descriptor */ 196 - Status = RtlGetOwnerSecurityDescriptor(RelSD, 197 - &OwnerSid, 198 - &OwnerDefaulted); 199 - if (!NT_SUCCESS(Status)) 200 - { 201 - goto Cleanup; 202 - } 203 - 204 - Status = RtlGetDaclSecurityDescriptor(RelSD, 205 - &DaclPresent, 206 - &Dacl, 207 - &DaclDefaulted); 208 - if (!NT_SUCCESS(Status)) 209 - { 210 - goto Cleanup; 211 - } 212 - 213 - /* create the Administrators SID */ 214 - Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 215 - 2, 216 - SECURITY_BUILTIN_DOMAIN_RID, 217 - DOMAIN_ALIAS_RID_ADMINS, 218 - 0, 219 - 0, 220 - 0, 221 - 0, 222 - 0, 223 - 0, 224 - &AdminSid); 225 - if (!NT_SUCCESS(Status)) 226 - { 227 - goto Cleanup; 228 - } 229 - 230 - /* create the local SYSTEM SID */ 231 - Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 232 - 1, 233 - SECURITY_LOCAL_SYSTEM_RID, 234 - 0, 235 - 0, 236 - 0, 237 - 0, 238 - 0, 239 - 0, 240 - 0, 241 - &LocalSystemSid); 242 - if (!NT_SUCCESS(Status)) 243 - { 244 - goto Cleanup; 245 - } 246 - 247 - /* check if the Administrators are the owner and at least a not-NULL DACL 248 - is present */ 249 - if (OwnerSid != NULL && 250 - RtlEqualSid(OwnerSid, 251 - AdminSid) && 252 - DaclPresent && Dacl != NULL) 253 - { 254 - /* check the DACL for an Allowed ACE for the SYSTEM account */ 255 - AceIndex = 0; 256 - do 257 - { 258 - Status = RtlGetAce(Dacl, 259 - AceIndex++, 260 - (PVOID*)&Ace); 261 - if (!NT_SUCCESS(Status)) 262 - { 263 - Ace = NULL; 264 - } 265 - else if (Ace != NULL && Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) 266 - { 267 - /* check if the the ACE is a set of allowed permissions for the 268 - local SYSTEM account */ 269 - if (RtlEqualSid((PSID)(Ace + 1), 270 - LocalSystemSid)) 271 - { 272 - /* check if the ACE is inherited by noncontainer and 273 - container objects, if not attempt to change that */ 274 - if (!(Ace->Header.AceFlags & OBJECT_INHERIT_ACE) || 275 - !(Ace->Header.AceFlags & CONTAINER_INHERIT_ACE)) 276 - { 277 - Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; 278 - Status = ZwSetSecurityObject(DirectoryHandle, 279 - DACL_SECURITY_INFORMATION, 280 - RelSD); 281 - } 282 - else 283 - { 284 - /* all done, we have access */ 285 - Status = STATUS_SUCCESS; 286 - } 287 - 288 - goto Cleanup; 289 - } 290 - } 291 - } while (Ace != NULL); 292 - } 293 - 294 - AbsSDSize = DescriptorSize; 295 - 296 - /* because we need to change any existing data we need to convert it to 297 - an absolute security descriptor first */ 298 - Status = RtlSelfRelativeToAbsoluteSD2(RelSD, 299 - &AbsSDSize); 300 - #ifdef _WIN64 301 - if (Status == STATUS_BUFFER_TOO_SMALL) 302 - { 303 - /* this error code can only be returned on 64 bit builds because 304 - the size of an absolute security descriptor is greater than the 305 - size of a self-relative security descriptor */ 306 - ASSERT(AbsSDSize > DescriptorSize); 307 - 308 - AbsSD = RtlpAllocateMemory(DescriptorSize, 309 - 'dSeS'); 310 - if (AbsSD == NULL) 311 - { 312 - Status = STATUS_NO_MEMORY; 313 - goto Cleanup; 314 - } 315 - 316 - AbsSDAllocated = TRUE; 317 - 318 - /* make a raw copy of the self-relative descriptor */ 319 - RtlCopyMemory(AbsSD, 320 - RelSD, 321 - DescriptorSize); 322 - 323 - /* finally convert it */ 324 - Status = RtlSelfRelativeToAbsoluteSD2(AbsSD, 325 - &AbsSDSize); 326 - } 327 - else 328 - #endif 329 - { 330 - AbsSD = RelSD; 331 - } 332 - 333 - if (!NT_SUCCESS(Status)) 334 - { 335 - goto Cleanup; 336 - } 337 - 338 - /* set the owner SID */ 339 - Status = RtlSetOwnerSecurityDescriptor(AbsSD, 340 - AdminSid, 341 - FALSE); 342 - if (!NT_SUCCESS(Status)) 343 - { 344 - goto Cleanup; 345 - } 346 - 347 - /* set the DACL in the security descriptor */ 348 - Status = RtlSetDaclSecurityDescriptor(AbsSD, 349 - TRUE, 350 - SecurityDescriptor->Dacl, 351 - FALSE); 352 - if (!NT_SUCCESS(Status)) 353 - { 354 - goto Cleanup; 355 - } 356 - 357 - /* convert it back to a self-relative descriptor, find out how much 358 - memory we need */ 359 - Status = RtlAbsoluteToSelfRelativeSD(AbsSD, 360 - NULL, 361 - &RelSDSize); 362 - if (Status != STATUS_BUFFER_TOO_SMALL) 363 - { 364 - goto Cleanup; 365 - } 366 - 367 - /* allocate enough memory for the new self-relative descriptor */ 368 - NewRelSD = RtlpAllocateMemory(RelSDSize, 369 - 'dSeS'); 370 - if (NewRelSD == NULL) 371 - { 372 - Status = STATUS_NO_MEMORY; 373 - goto Cleanup; 374 - } 375 - 376 - /* convert the security descriptor to self-relative format */ 377 - Status = RtlAbsoluteToSelfRelativeSD(AbsSD, 378 - NewRelSD, 379 - &RelSDSize); 380 - if (Status == STATUS_BUFFER_TOO_SMALL) 381 - { 382 - goto Cleanup; 383 - } 384 - 385 - /* finally attempt to change the security information */ 386 - Status = ZwSetSecurityObject(DirectoryHandle, 387 - OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 388 - NewRelSD); 389 - 390 - Cleanup: 391 - if (AdminSid != NULL) 392 - { 393 - RtlFreeSid(AdminSid); 394 - } 395 - 396 - if (LocalSystemSid != NULL) 397 - { 398 - RtlFreeSid(LocalSystemSid); 399 - } 400 - 401 - if (RelSD != NULL) 402 - { 403 - RtlpFreeMemory(RelSD, 404 - 'dSeS'); 405 - } 406 - 407 - if (NewRelSD != NULL) 408 - { 409 - RtlpFreeMemory(NewRelSD, 410 - 'dSeS'); 411 - } 412 - 413 - #ifdef _WIN64 414 - if (AbsSDAllocated) 415 27 { 416 - RtlpFreeMemory(AbsSD, 417 - 'dSeS'); 418 - } 419 - #endif 420 - 421 - return Status; 422 - } 423 - 424 - static NTSTATUS 425 - RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath, 426 - IN PSECURITY_DESCRIPTOR SecurityDescriptor) 427 - { 428 - TOKEN_PRIVILEGES TokenPrivileges; 429 - OBJECT_ATTRIBUTES ObjectAttributes; 430 - SECURITY_DESCRIPTOR AbsSD; 431 - PSID AdminSid = NULL; 432 - IO_STATUS_BLOCK IoStatusBlock; 433 - BOOLEAN TokenEnabled = FALSE; 434 - HANDLE hToken = NULL; 435 - HANDLE hDirectory = NULL; 436 - NTSTATUS Status; 437 - ULONG ReturnLength; 438 - 439 - Status = ZwOpenProcessToken(NtCurrentProcess(), 440 - TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, 441 - &hToken); 442 - if (!NT_SUCCESS(Status)) 28 + FIELD_OFFSET(RTL_BSD_DATA, Version), 29 + sizeof(&DummyBsd->Version) 30 + }, // RtlBsdItemVersionNumber 443 31 { 444 - goto Cleanup; 445 - } 446 - 447 - /* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */ 448 - TokenPrivileges.PrivilegeCount = 1; 449 - TokenPrivileges.Privileges[0].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; 450 - TokenPrivileges.Privileges[0].Luid.HighPart = 0; 451 - TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 452 - Status = ZwAdjustPrivilegesToken(hToken, 453 - FALSE, 454 - &TokenPrivileges, 455 - sizeof(TokenPrivileges), 456 - &TokenPrivileges, 457 - &ReturnLength); 458 - if (!NT_SUCCESS(Status)) 32 + FIELD_OFFSET(RTL_BSD_DATA, ProductType), 33 + sizeof(&DummyBsd->ProductType) 34 + }, // RtlBsdItemProductType 459 35 { 460 - goto Cleanup; 461 - } 462 - TokenEnabled = (TokenPrivileges.PrivilegeCount != 0); 463 - 464 - /* open the directory */ 465 - InitializeObjectAttributes(&ObjectAttributes, 466 - DirectoryPath, 467 - 0, 468 - NULL, 469 - SecurityDescriptor); 470 - 471 - Status = ZwOpenFile(&hDirectory, 472 - SYNCHRONIZE | WRITE_OWNER, 473 - &ObjectAttributes, 474 - &IoStatusBlock, 475 - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 476 - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 477 - if (!NT_SUCCESS(Status)) 36 + FIELD_OFFSET(RTL_BSD_DATA, AabEnabled), 37 + sizeof(&DummyBsd->AabEnabled) 38 + }, // RtlBsdItemAabEnabled 478 39 { 479 - goto Cleanup; 480 - } 481 - 482 - /* create the Administrators SID */ 483 - Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 484 - 2, 485 - SECURITY_BUILTIN_DOMAIN_RID, 486 - DOMAIN_ALIAS_RID_ADMINS, 487 - 0, 488 - 0, 489 - 0, 490 - 0, 491 - 0, 492 - 0, 493 - &AdminSid); 494 - if (!NT_SUCCESS(Status)) 40 + FIELD_OFFSET(RTL_BSD_DATA, AabTimeout), 41 + sizeof(&DummyBsd->AabTimeout) 42 + }, // RtlBsdItemAabTimeout 495 43 { 496 - goto Cleanup; 497 - } 498 - 499 - /* create the security descriptor */ 500 - Status = RtlCreateSecurityDescriptor(&AbsSD, 501 - SECURITY_DESCRIPTOR_REVISION); 502 - if (!NT_SUCCESS(Status)) 44 + FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded), 45 + sizeof(&DummyBsd->LastBootSucceeded) 46 + }, // RtlBsdItemBootGood 503 47 { 504 - goto Cleanup; 505 - } 506 - 507 - Status = RtlSetOwnerSecurityDescriptor(&AbsSD, 508 - AdminSid, 509 - FALSE); 510 - if (!NT_SUCCESS(Status)) 48 + FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown), 49 + sizeof(&DummyBsd->LastBootShutdown) 50 + }, // RtlBsdItemBootShutdown 511 51 { 512 - goto Cleanup; 513 - } 514 - 515 - /* attempt to take ownership */ 516 - Status = ZwSetSecurityObject(hDirectory, 517 - OWNER_SECURITY_INFORMATION, 518 - &AbsSD); 519 - 520 - Cleanup: 521 - if (TokenEnabled) 52 + FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress), 53 + sizeof(&DummyBsd->SleepInProgress) 54 + }, // RtlBsdSleepInProgress 522 55 { 523 - ZwAdjustPrivilegesToken(hToken, 524 - FALSE, 525 - &TokenPrivileges, 526 - 0, 527 - NULL, 528 - NULL); 529 - } 530 - 531 - if (AdminSid != NULL) 56 + FIELD_OFFSET(RTL_BSD_DATA, PowerTransition), 57 + sizeof(&DummyBsd->PowerTransition) 58 + }, // RtlBsdPowerTransition 532 59 { 533 - RtlFreeSid(AdminSid); 534 - } 535 - 536 - if (hDirectory != NULL) 60 + FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount), 61 + sizeof(&DummyBsd->BootAttemptCount) 62 + }, // RtlBsdItemBootAttemptCount 537 63 { 538 - ZwClose(hDirectory); 539 - } 540 - 541 - if (hToken != NULL) 64 + FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint), 65 + sizeof(&DummyBsd->LastBootCheckpoint) 66 + }, // RtlBsdItemBootCheckpoint 542 67 { 543 - ZwClose(hToken); 544 - } 545 - 546 - return Status; 547 - } 548 - 549 - /* 550 - * @implemented 551 - */ 552 - NTSTATUS 553 - NTAPI 554 - RtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath) 555 - { 556 - OBJECT_ATTRIBUTES ObjectAttributes; 557 - IO_STATUS_BLOCK IoStatusBlock; 558 - HANDLE hDirectory; 559 - UNICODE_STRING DirectoryName, NewPath; 560 - ULONG PathLen; 561 - PISECURITY_DESCRIPTOR SecurityDescriptor = NULL; 562 - PSID SystemSid = NULL; 563 - BOOLEAN AddSep = FALSE; 564 - NTSTATUS Status; 565 - 566 - PAGED_CODE_RTL(); 567 - 568 - RtlInitUnicodeString(&DirectoryName, 569 - L"System Volume Information"); 570 - 571 - PathLen = VolumeRootPath->Length + DirectoryName.Length; 572 - 573 - /* make sure we don't overflow while appending the strings */ 574 - if (PathLen > 0xFFFC) 68 + FIELD_OFFSET(RTL_BSD_DATA, LastBootId), 69 + sizeof(&DummyBsd->LastBootId) 70 + }, // RtlBsdItemBootId 575 71 { 576 - return STATUS_INVALID_PARAMETER; 577 - } 578 - 579 - if (VolumeRootPath->Buffer[(VolumeRootPath->Length / sizeof(WCHAR)) - 1] != L'\\') 72 + FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId), 73 + sizeof(&DummyBsd->LastSuccessfulShutdownBootId) 74 + }, // RtlBsdItemShutdownBootId 580 75 { 581 - AddSep = TRUE; 582 - PathLen += sizeof(WCHAR); 583 - } 584 - 585 - /* allocate the new string */ 586 - NewPath.MaximumLength = (USHORT)PathLen + sizeof(WCHAR); 587 - NewPath.Buffer = RtlpAllocateStringMemory(NewPath.MaximumLength, 588 - TAG_USTR); 589 - if (NewPath.Buffer == NULL) 76 + FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId), 77 + sizeof(&DummyBsd->LastReportedAbnormalShutdownBootId) 78 + }, // RtlBsdItemReportedAbnormalShutdownBootId 590 79 { 591 - return STATUS_INSUFFICIENT_RESOURCES; 592 - } 593 - 594 - /* create the new path string */ 595 - NewPath.Length = VolumeRootPath->Length; 596 - RtlCopyMemory(NewPath.Buffer, 597 - VolumeRootPath->Buffer, 598 - NewPath.Length); 599 - if (AddSep) 80 + FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo), 81 + sizeof(&DummyBsd->ErrorInfo) 82 + }, // RtlBsdItemErrorInfo 600 83 { 601 - NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\\'; 602 - NewPath.Length += sizeof(WCHAR); 603 - } 604 - RtlCopyMemory(NewPath.Buffer + (NewPath.Length / sizeof(WCHAR)), 605 - DirectoryName.Buffer, 606 - DirectoryName.Length); 607 - NewPath.Length += DirectoryName.Length; 608 - NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\0'; 609 - 610 - ASSERT(NewPath.Length == PathLen); 611 - ASSERT(NewPath.Length == NewPath.MaximumLength - sizeof(WCHAR)); 612 - 613 - /* create the security descriptor for the new directory */ 614 - Status = RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor, 615 - &SystemSid); 616 - if (NT_SUCCESS(Status)) 84 + FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo), 85 + sizeof(&DummyBsd->PowerButtonPressInfo) 86 + }, // RtlBsdItemPowerButtonPressInfo 617 87 { 618 - /* create or open the directory */ 619 - InitializeObjectAttributes(&ObjectAttributes, 620 - &NewPath, 621 - 0, 622 - NULL, 623 - SecurityDescriptor); 624 - 625 - Status = ZwCreateFile(&hDirectory, 626 - SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL, 627 - &ObjectAttributes, 628 - &IoStatusBlock, 629 - NULL, 630 - FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 631 - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 632 - FILE_OPEN_IF, 633 - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 634 - NULL, 635 - 0); 636 - if (!NT_SUCCESS(Status)) 637 - { 638 - Status = RtlpSysVolTakeOwnership(&NewPath, 639 - SecurityDescriptor); 640 - 641 - if (NT_SUCCESS(Status)) 642 - { 643 - /* successfully took ownership, attempt to open it */ 644 - Status = ZwCreateFile(&hDirectory, 645 - SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL, 646 - &ObjectAttributes, 647 - &IoStatusBlock, 648 - NULL, 649 - FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 650 - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 651 - FILE_OPEN_IF, 652 - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 653 - NULL, 654 - 0); 655 - } 656 - } 657 - 658 - if (NT_SUCCESS(Status)) 659 - { 660 - /* check security now and adjust it if neccessary */ 661 - Status = RtlpSysVolCheckOwnerAndSecurity(hDirectory, 662 - SecurityDescriptor); 663 - ZwClose(hDirectory); 664 - } 665 - 666 - /* free allocated memory */ 667 - ASSERT(SecurityDescriptor != NULL); 668 - ASSERT(SecurityDescriptor->Dacl != NULL); 669 - 670 - RtlpFreeMemory(SecurityDescriptor->Dacl, 671 - 'cAeS'); 672 - RtlpFreeMemory(SecurityDescriptor, 673 - 'dSeS'); 674 - 675 - RtlFreeSid(SystemSid); 676 - } 677 - 678 - RtlpFreeStringMemory(NewPath.Buffer, 679 - TAG_USTR); 680 - return Status; 681 - } 88 + FIELD_OFFSET(RTL_BSD_DATA, Checksum), 89 + sizeof(&DummyBsd->Checksum) 90 + }, // RtlBsdItemChecksum 91 + }; 682 92 683 93 /* 684 - * @implemented 685 - */ 94 + * @implemented 95 + */ 686 96 NTSTATUS 687 97 NTAPI 688 - RtlCreateBootStatusDataFile(VOID) 98 + RtlCreateBootStatusDataFile ( 99 + VOID 100 + ) 689 101 { 690 - OBJECT_ATTRIBUTES ObjectAttributes; 691 102 IO_STATUS_BLOCK IoStatusBlock; 692 103 LARGE_INTEGER AllocationSize; 693 104 LARGE_INTEGER ByteOffset; 694 - UNICODE_STRING FileName; 105 + UNICODE_STRING FileName = 106 + RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat"); 107 + OBJECT_ATTRIBUTES ObjectAttributes = 108 + RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE); 695 109 HANDLE FileHandle; 696 110 NTSTATUS Status; 697 - 698 - /* Initialize the file name */ 699 - RtlInitUnicodeString(&FileName, 700 - L"\\SystemRoot\\bootstat.dat"); 701 - 702 - /* Initialize the object attributes */ 703 - InitializeObjectAttributes(&ObjectAttributes, 704 - &FileName, 705 - OBJ_CASE_INSENSITIVE, 706 - NULL, 707 - NULL); 111 + RTL_BSD_DATA InitialBsd; 708 112 113 + /* Create the boot status data file */ 709 114 AllocationSize.QuadPart = 0x800; 710 115 DBG_UNREFERENCED_LOCAL_VARIABLE(AllocationSize); 711 - 712 - /* Create the boot status data file */ 713 116 Status = ZwCreateFile(&FileHandle, 714 117 FILE_GENERIC_READ | FILE_GENERIC_WRITE, 715 118 &ObjectAttributes, ··· 723 126 0); 724 127 if (NT_SUCCESS(Status)) 725 128 { 726 - // FIXME: Initialize the buffer in a better way. 727 - UCHAR Buffer[12] = {0xC,0,0,0, 1,0,0,0, 1, 0x1e, 1, 0}; 129 + /* Setup a sane looking initial BSD */ 130 + RtlZeroMemory(&InitialBsd, sizeof(InitialBsd)); 131 + InitialBsd.Version = sizeof(InitialBsd); 132 + InitialBsd.ProductType = NtProductWinNt; 133 + InitialBsd.AabEnabled = 1; 134 + InitialBsd.AabTimeout = 30; 135 + InitialBsd.LastBootSucceeded = TRUE; 728 136 137 + /* Write it to disk */ 729 138 ByteOffset.QuadPart = 0; 730 139 Status = ZwWriteFile(FileHandle, 731 140 NULL, 732 141 NULL, 733 142 NULL, 734 143 &IoStatusBlock, 735 - &Buffer, 736 - 12, //BufferSize, 144 + &InitialBsd, 145 + sizeof(InitialBsd), 737 146 &ByteOffset, 738 147 NULL); 739 148 } ··· 745 154 } 746 155 747 156 /* 748 - * @implemented 749 - */ 157 + * @implemented 158 + */ 750 159 NTSTATUS 751 160 NTAPI 752 - RtlGetSetBootStatusData(IN HANDLE FileHandle, 753 - IN BOOLEAN WriteMode, 754 - IN RTL_BSD_ITEM_TYPE DataClass, 755 - IN PVOID Buffer, 756 - IN ULONG BufferSize, 757 - OUT PULONG ReturnLength) 161 + RtlGetSetBootStatusData ( 162 + _In_ HANDLE FileHandle, 163 + _In_ BOOLEAN Read, 164 + _In_ RTL_BSD_ITEM_TYPE DataClass, 165 + _In_ PVOID Buffer, 166 + _In_ ULONG BufferSize, 167 + _Out_opt_ PULONG ReturnLength 168 + ) 758 169 { 759 170 IO_STATUS_BLOCK IoStatusBlock; 760 171 LARGE_INTEGER ByteOffset; 761 172 NTSTATUS Status; 762 173 763 174 DPRINT("RtlGetSetBootStatusData (%p %u %d %p %lu %p)\n", 764 - FileHandle, WriteMode, DataClass, Buffer, BufferSize, ReturnLength); 175 + FileHandle, Read, DataClass, Buffer, BufferSize, ReturnLength); 765 176 766 177 if (DataClass >= RtlBsdItemMax) 178 + { 767 179 return STATUS_INVALID_PARAMETER; 180 + } 768 181 769 182 if (BufferSize > BsdItemTable[DataClass].Size) 183 + { 770 184 return STATUS_BUFFER_TOO_SMALL; 185 + } 771 186 772 187 ByteOffset.HighPart = 0; 773 188 ByteOffset.LowPart = BsdItemTable[DataClass].Offset; 774 189 775 - if (WriteMode) 190 + if (Read) 776 191 { 777 192 Status = ZwReadFile(FileHandle, 778 193 NULL, ··· 800 215 if (NT_SUCCESS(Status)) 801 216 { 802 217 if (ReturnLength) 218 + { 803 219 *ReturnLength = BsdItemTable[DataClass].Size; 220 + } 804 221 } 805 222 806 223 return Status; 807 224 } 808 225 809 226 /* 810 - * @implemented 811 - */ 227 + * @implemented 228 + */ 812 229 NTSTATUS 813 230 NTAPI 814 - RtlLockBootStatusData(OUT PHANDLE FileHandle) 231 + RtlLockBootStatusData ( 232 + _Out_ PHANDLE FileHandle 233 + ) 815 234 { 816 - OBJECT_ATTRIBUTES ObjectAttributes; 817 - IO_STATUS_BLOCK IoStatusBlock; 818 - UNICODE_STRING FileName; 235 + UNICODE_STRING FileName = 236 + RTL_CONSTANT_STRING(L"\\SystemRoot\\bootstat.dat"); 237 + OBJECT_ATTRIBUTES ObjectAttributes = 238 + RTL_CONSTANT_OBJECT_ATTRIBUTES(&FileName, OBJ_CASE_INSENSITIVE); 819 239 HANDLE LocalFileHandle; 820 240 NTSTATUS Status; 241 + IO_STATUS_BLOCK IoStatusBlock; 821 242 822 243 /* Intialize the file handle */ 823 244 *FileHandle = NULL; 824 - 825 - /* Initialize the file name */ 826 - RtlInitUnicodeString(&FileName, 827 - L"\\SystemRoot\\bootstat.dat"); 828 - 829 - /* Initialize the object attributes */ 830 - InitializeObjectAttributes(&ObjectAttributes, 831 - &FileName, 832 - 0, 833 - NULL, 834 - NULL); 835 245 836 246 /* Open the boot status data file */ 837 247 Status = ZwOpenFile(&LocalFileHandle, ··· 850 260 } 851 261 852 262 /* 853 - * @implemented 854 - */ 263 + * @implemented 264 + */ 855 265 NTSTATUS 856 266 NTAPI 857 - RtlUnlockBootStatusData(IN HANDLE FileHandle) 267 + RtlUnlockBootStatusData ( 268 + _In_ HANDLE FileHandle 269 + ) 858 270 { 859 271 IO_STATUS_BLOCK IoStatusBlock; 860 272 861 273 /* Flush the file and close it */ 862 - ZwFlushBuffersFile(FileHandle, 863 - &IoStatusBlock); 864 - 274 + ZwFlushBuffersFile(FileHandle, &IoStatusBlock); 865 275 return ZwClose(FileHandle); 866 276 } 867 277
+674
sdk/lib/rtl/sysvol.c
··· 1 + /* 2 + * COPYRIGHT: See COPYING in the top level directory 3 + * PROJECT: ReactOS system libraries 4 + * PURPOSE: Boot Data implementation 5 + * FILE: lib/rtl/bootdata.c 6 + * PROGRAMMERS: 7 + */ 8 + 9 + /* INCLUDES *****************************************************************/ 10 + 11 + #include <rtl.h> 12 + #define NDEBUG 13 + #include <debug.h> 14 + 15 + /* FUNCTIONS *****************************************************************/ 16 + 17 + static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority = {SECURITY_NT_AUTHORITY}; 18 + 19 + static NTSTATUS 20 + RtlpSysVolCreateSecurityDescriptor(OUT PISECURITY_DESCRIPTOR *SecurityDescriptor, 21 + OUT PSID *SystemSid) 22 + { 23 + PSECURITY_DESCRIPTOR AbsSD = NULL; 24 + PSID LocalSystemSid = NULL; 25 + PACL Dacl = NULL; 26 + ULONG DaclSize; 27 + NTSTATUS Status; 28 + 29 + /* create the local SYSTEM SID */ 30 + Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 31 + 1, 32 + SECURITY_LOCAL_SYSTEM_RID, 33 + 0, 34 + 0, 35 + 0, 36 + 0, 37 + 0, 38 + 0, 39 + 0, 40 + &LocalSystemSid); 41 + if (!NT_SUCCESS(Status)) 42 + { 43 + return Status; 44 + } 45 + 46 + /* allocate and initialize the security descriptor */ 47 + AbsSD = RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR), 48 + 'dSeS'); 49 + if (AbsSD == NULL) 50 + { 51 + Status = STATUS_NO_MEMORY; 52 + goto Cleanup; 53 + } 54 + 55 + Status = RtlCreateSecurityDescriptor(AbsSD, 56 + SECURITY_DESCRIPTOR_REVISION); 57 + if (!NT_SUCCESS(Status)) 58 + { 59 + goto Cleanup; 60 + } 61 + 62 + /* allocate and create the DACL */ 63 + DaclSize = sizeof(ACL) + sizeof(ACE) + 64 + RtlLengthSid(LocalSystemSid); 65 + Dacl = RtlpAllocateMemory(DaclSize, 66 + 'cAeS'); 67 + if (Dacl == NULL) 68 + { 69 + Status = STATUS_NO_MEMORY; 70 + goto Cleanup; 71 + } 72 + 73 + Status = RtlCreateAcl(Dacl, 74 + DaclSize, 75 + ACL_REVISION); 76 + if (!NT_SUCCESS(Status)) 77 + { 78 + goto Cleanup; 79 + } 80 + 81 + Status = RtlAddAccessAllowedAceEx(Dacl, 82 + ACL_REVISION, 83 + OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, 84 + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, 85 + LocalSystemSid); 86 + if (!NT_SUCCESS(Status)) 87 + { 88 + goto Cleanup; 89 + } 90 + 91 + /* set the DACL in the security descriptor */ 92 + Status = RtlSetDaclSecurityDescriptor(AbsSD, 93 + TRUE, 94 + Dacl, 95 + FALSE); 96 + 97 + /* all done */ 98 + if (NT_SUCCESS(Status)) 99 + { 100 + *SecurityDescriptor = AbsSD; 101 + *SystemSid = LocalSystemSid; 102 + } 103 + else 104 + { 105 + Cleanup: 106 + if (LocalSystemSid != NULL) 107 + { 108 + RtlFreeSid(LocalSystemSid); 109 + } 110 + 111 + if (Dacl != NULL) 112 + { 113 + RtlpFreeMemory(Dacl, 114 + 'cAeS'); 115 + } 116 + 117 + if (AbsSD != NULL) 118 + { 119 + RtlpFreeMemory(AbsSD, 120 + 'dSeS'); 121 + } 122 + } 123 + 124 + return Status; 125 + } 126 + 127 + static NTSTATUS 128 + RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle, 129 + IN PISECURITY_DESCRIPTOR SecurityDescriptor) 130 + { 131 + PSECURITY_DESCRIPTOR RelSD = NULL; 132 + PSECURITY_DESCRIPTOR NewRelSD = NULL; 133 + PSECURITY_DESCRIPTOR AbsSD = NULL; 134 + #ifdef _WIN64 135 + BOOLEAN AbsSDAllocated = FALSE; 136 + #endif 137 + PSID AdminSid = NULL; 138 + PSID LocalSystemSid = NULL; 139 + ULONG DescriptorSize; 140 + ULONG AbsSDSize, RelSDSize = 0; 141 + PACL Dacl; 142 + BOOLEAN DaclPresent, DaclDefaulted; 143 + PSID OwnerSid; 144 + BOOLEAN OwnerDefaulted; 145 + ULONG AceIndex; 146 + PACE Ace = NULL; 147 + NTSTATUS Status; 148 + 149 + /* find out how much memory we need to allocate for the self-relative 150 + descriptor we're querying */ 151 + Status = ZwQuerySecurityObject(DirectoryHandle, 152 + OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 153 + NULL, 154 + 0, 155 + &DescriptorSize); 156 + if (Status != STATUS_BUFFER_TOO_SMALL) 157 + { 158 + /* looks like the FS doesn't support security... return success */ 159 + Status = STATUS_SUCCESS; 160 + goto Cleanup; 161 + } 162 + 163 + /* allocate enough memory for the security descriptor */ 164 + RelSD = RtlpAllocateMemory(DescriptorSize, 165 + 'dSeS'); 166 + if (RelSD == NULL) 167 + { 168 + Status = STATUS_NO_MEMORY; 169 + goto Cleanup; 170 + } 171 + 172 + /* query the self-relative security descriptor */ 173 + Status = ZwQuerySecurityObject(DirectoryHandle, 174 + OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 175 + RelSD, 176 + DescriptorSize, 177 + &DescriptorSize); 178 + if (!NT_SUCCESS(Status)) 179 + { 180 + /* FIXME - handle the case where someone else modified the owner and/or 181 + DACL while we allocated memory. But that should be *very* 182 + unlikely.... */ 183 + goto Cleanup; 184 + } 185 + 186 + /* query the owner and DACL from the descriptor */ 187 + Status = RtlGetOwnerSecurityDescriptor(RelSD, 188 + &OwnerSid, 189 + &OwnerDefaulted); 190 + if (!NT_SUCCESS(Status)) 191 + { 192 + goto Cleanup; 193 + } 194 + 195 + Status = RtlGetDaclSecurityDescriptor(RelSD, 196 + &DaclPresent, 197 + &Dacl, 198 + &DaclDefaulted); 199 + if (!NT_SUCCESS(Status)) 200 + { 201 + goto Cleanup; 202 + } 203 + 204 + /* create the Administrators SID */ 205 + Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 206 + 2, 207 + SECURITY_BUILTIN_DOMAIN_RID, 208 + DOMAIN_ALIAS_RID_ADMINS, 209 + 0, 210 + 0, 211 + 0, 212 + 0, 213 + 0, 214 + 0, 215 + &AdminSid); 216 + if (!NT_SUCCESS(Status)) 217 + { 218 + goto Cleanup; 219 + } 220 + 221 + /* create the local SYSTEM SID */ 222 + Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 223 + 1, 224 + SECURITY_LOCAL_SYSTEM_RID, 225 + 0, 226 + 0, 227 + 0, 228 + 0, 229 + 0, 230 + 0, 231 + 0, 232 + &LocalSystemSid); 233 + if (!NT_SUCCESS(Status)) 234 + { 235 + goto Cleanup; 236 + } 237 + 238 + /* check if the Administrators are the owner and at least a not-NULL DACL 239 + is present */ 240 + if (OwnerSid != NULL && 241 + RtlEqualSid(OwnerSid, 242 + AdminSid) && 243 + DaclPresent && Dacl != NULL) 244 + { 245 + /* check the DACL for an Allowed ACE for the SYSTEM account */ 246 + AceIndex = 0; 247 + do 248 + { 249 + Status = RtlGetAce(Dacl, 250 + AceIndex++, 251 + (PVOID*)&Ace); 252 + if (!NT_SUCCESS(Status)) 253 + { 254 + Ace = NULL; 255 + } 256 + else if (Ace != NULL && Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) 257 + { 258 + /* check if the the ACE is a set of allowed permissions for the 259 + local SYSTEM account */ 260 + if (RtlEqualSid((PSID)(Ace + 1), 261 + LocalSystemSid)) 262 + { 263 + /* check if the ACE is inherited by noncontainer and 264 + container objects, if not attempt to change that */ 265 + if (!(Ace->Header.AceFlags & OBJECT_INHERIT_ACE) || 266 + !(Ace->Header.AceFlags & CONTAINER_INHERIT_ACE)) 267 + { 268 + Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; 269 + Status = ZwSetSecurityObject(DirectoryHandle, 270 + DACL_SECURITY_INFORMATION, 271 + RelSD); 272 + } 273 + else 274 + { 275 + /* all done, we have access */ 276 + Status = STATUS_SUCCESS; 277 + } 278 + 279 + goto Cleanup; 280 + } 281 + } 282 + } while (Ace != NULL); 283 + } 284 + 285 + AbsSDSize = DescriptorSize; 286 + 287 + /* because we need to change any existing data we need to convert it to 288 + an absolute security descriptor first */ 289 + Status = RtlSelfRelativeToAbsoluteSD2(RelSD, 290 + &AbsSDSize); 291 + #ifdef _WIN64 292 + if (Status == STATUS_BUFFER_TOO_SMALL) 293 + { 294 + /* this error code can only be returned on 64 bit builds because 295 + the size of an absolute security descriptor is greater than the 296 + size of a self-relative security descriptor */ 297 + ASSERT(AbsSDSize > DescriptorSize); 298 + 299 + AbsSD = RtlpAllocateMemory(DescriptorSize, 300 + 'dSeS'); 301 + if (AbsSD == NULL) 302 + { 303 + Status = STATUS_NO_MEMORY; 304 + goto Cleanup; 305 + } 306 + 307 + AbsSDAllocated = TRUE; 308 + 309 + /* make a raw copy of the self-relative descriptor */ 310 + RtlCopyMemory(AbsSD, 311 + RelSD, 312 + DescriptorSize); 313 + 314 + /* finally convert it */ 315 + Status = RtlSelfRelativeToAbsoluteSD2(AbsSD, 316 + &AbsSDSize); 317 + } 318 + else 319 + #endif 320 + { 321 + AbsSD = RelSD; 322 + } 323 + 324 + if (!NT_SUCCESS(Status)) 325 + { 326 + goto Cleanup; 327 + } 328 + 329 + /* set the owner SID */ 330 + Status = RtlSetOwnerSecurityDescriptor(AbsSD, 331 + AdminSid, 332 + FALSE); 333 + if (!NT_SUCCESS(Status)) 334 + { 335 + goto Cleanup; 336 + } 337 + 338 + /* set the DACL in the security descriptor */ 339 + Status = RtlSetDaclSecurityDescriptor(AbsSD, 340 + TRUE, 341 + SecurityDescriptor->Dacl, 342 + FALSE); 343 + if (!NT_SUCCESS(Status)) 344 + { 345 + goto Cleanup; 346 + } 347 + 348 + /* convert it back to a self-relative descriptor, find out how much 349 + memory we need */ 350 + Status = RtlAbsoluteToSelfRelativeSD(AbsSD, 351 + NULL, 352 + &RelSDSize); 353 + if (Status != STATUS_BUFFER_TOO_SMALL) 354 + { 355 + goto Cleanup; 356 + } 357 + 358 + /* allocate enough memory for the new self-relative descriptor */ 359 + NewRelSD = RtlpAllocateMemory(RelSDSize, 360 + 'dSeS'); 361 + if (NewRelSD == NULL) 362 + { 363 + Status = STATUS_NO_MEMORY; 364 + goto Cleanup; 365 + } 366 + 367 + /* convert the security descriptor to self-relative format */ 368 + Status = RtlAbsoluteToSelfRelativeSD(AbsSD, 369 + NewRelSD, 370 + &RelSDSize); 371 + if (Status == STATUS_BUFFER_TOO_SMALL) 372 + { 373 + goto Cleanup; 374 + } 375 + 376 + /* finally attempt to change the security information */ 377 + Status = ZwSetSecurityObject(DirectoryHandle, 378 + OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 379 + NewRelSD); 380 + 381 + Cleanup: 382 + if (AdminSid != NULL) 383 + { 384 + RtlFreeSid(AdminSid); 385 + } 386 + 387 + if (LocalSystemSid != NULL) 388 + { 389 + RtlFreeSid(LocalSystemSid); 390 + } 391 + 392 + if (RelSD != NULL) 393 + { 394 + RtlpFreeMemory(RelSD, 395 + 'dSeS'); 396 + } 397 + 398 + if (NewRelSD != NULL) 399 + { 400 + RtlpFreeMemory(NewRelSD, 401 + 'dSeS'); 402 + } 403 + 404 + #ifdef _WIN64 405 + if (AbsSDAllocated) 406 + { 407 + RtlpFreeMemory(AbsSD, 408 + 'dSeS'); 409 + } 410 + #endif 411 + 412 + return Status; 413 + } 414 + 415 + static NTSTATUS 416 + RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath, 417 + IN PSECURITY_DESCRIPTOR SecurityDescriptor) 418 + { 419 + TOKEN_PRIVILEGES TokenPrivileges; 420 + OBJECT_ATTRIBUTES ObjectAttributes; 421 + SECURITY_DESCRIPTOR AbsSD; 422 + PSID AdminSid = NULL; 423 + IO_STATUS_BLOCK IoStatusBlock; 424 + BOOLEAN TokenEnabled = FALSE; 425 + HANDLE hToken = NULL; 426 + HANDLE hDirectory = NULL; 427 + NTSTATUS Status; 428 + ULONG ReturnLength; 429 + 430 + Status = ZwOpenProcessToken(NtCurrentProcess(), 431 + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, 432 + &hToken); 433 + if (!NT_SUCCESS(Status)) 434 + { 435 + goto Cleanup; 436 + } 437 + 438 + /* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */ 439 + TokenPrivileges.PrivilegeCount = 1; 440 + TokenPrivileges.Privileges[0].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; 441 + TokenPrivileges.Privileges[0].Luid.HighPart = 0; 442 + TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 443 + Status = ZwAdjustPrivilegesToken(hToken, 444 + FALSE, 445 + &TokenPrivileges, 446 + sizeof(TokenPrivileges), 447 + &TokenPrivileges, 448 + &ReturnLength); 449 + if (!NT_SUCCESS(Status)) 450 + { 451 + goto Cleanup; 452 + } 453 + TokenEnabled = (TokenPrivileges.PrivilegeCount != 0); 454 + 455 + /* open the directory */ 456 + InitializeObjectAttributes(&ObjectAttributes, 457 + DirectoryPath, 458 + 0, 459 + NULL, 460 + SecurityDescriptor); 461 + 462 + Status = ZwOpenFile(&hDirectory, 463 + SYNCHRONIZE | WRITE_OWNER, 464 + &ObjectAttributes, 465 + &IoStatusBlock, 466 + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 467 + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 468 + if (!NT_SUCCESS(Status)) 469 + { 470 + goto Cleanup; 471 + } 472 + 473 + /* create the Administrators SID */ 474 + Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 475 + 2, 476 + SECURITY_BUILTIN_DOMAIN_RID, 477 + DOMAIN_ALIAS_RID_ADMINS, 478 + 0, 479 + 0, 480 + 0, 481 + 0, 482 + 0, 483 + 0, 484 + &AdminSid); 485 + if (!NT_SUCCESS(Status)) 486 + { 487 + goto Cleanup; 488 + } 489 + 490 + /* create the security descriptor */ 491 + Status = RtlCreateSecurityDescriptor(&AbsSD, 492 + SECURITY_DESCRIPTOR_REVISION); 493 + if (!NT_SUCCESS(Status)) 494 + { 495 + goto Cleanup; 496 + } 497 + 498 + Status = RtlSetOwnerSecurityDescriptor(&AbsSD, 499 + AdminSid, 500 + FALSE); 501 + if (!NT_SUCCESS(Status)) 502 + { 503 + goto Cleanup; 504 + } 505 + 506 + /* attempt to take ownership */ 507 + Status = ZwSetSecurityObject(hDirectory, 508 + OWNER_SECURITY_INFORMATION, 509 + &AbsSD); 510 + 511 + Cleanup: 512 + if (TokenEnabled) 513 + { 514 + ZwAdjustPrivilegesToken(hToken, 515 + FALSE, 516 + &TokenPrivileges, 517 + 0, 518 + NULL, 519 + NULL); 520 + } 521 + 522 + if (AdminSid != NULL) 523 + { 524 + RtlFreeSid(AdminSid); 525 + } 526 + 527 + if (hDirectory != NULL) 528 + { 529 + ZwClose(hDirectory); 530 + } 531 + 532 + if (hToken != NULL) 533 + { 534 + ZwClose(hToken); 535 + } 536 + 537 + return Status; 538 + } 539 + 540 + /* 541 + * @implemented 542 + */ 543 + NTSTATUS 544 + NTAPI 545 + RtlCreateSystemVolumeInformationFolder(IN PUNICODE_STRING VolumeRootPath) 546 + { 547 + OBJECT_ATTRIBUTES ObjectAttributes; 548 + IO_STATUS_BLOCK IoStatusBlock; 549 + HANDLE hDirectory; 550 + UNICODE_STRING DirectoryName, NewPath; 551 + ULONG PathLen; 552 + PISECURITY_DESCRIPTOR SecurityDescriptor = NULL; 553 + PSID SystemSid = NULL; 554 + BOOLEAN AddSep = FALSE; 555 + NTSTATUS Status; 556 + 557 + PAGED_CODE_RTL(); 558 + 559 + RtlInitUnicodeString(&DirectoryName, 560 + L"System Volume Information"); 561 + 562 + PathLen = VolumeRootPath->Length + DirectoryName.Length; 563 + 564 + /* make sure we don't overflow while appending the strings */ 565 + if (PathLen > 0xFFFC) 566 + { 567 + return STATUS_INVALID_PARAMETER; 568 + } 569 + 570 + if (VolumeRootPath->Buffer[(VolumeRootPath->Length / sizeof(WCHAR)) - 1] != L'\\') 571 + { 572 + AddSep = TRUE; 573 + PathLen += sizeof(WCHAR); 574 + } 575 + 576 + /* allocate the new string */ 577 + NewPath.MaximumLength = (USHORT)PathLen + sizeof(WCHAR); 578 + NewPath.Buffer = RtlpAllocateStringMemory(NewPath.MaximumLength, 579 + TAG_USTR); 580 + if (NewPath.Buffer == NULL) 581 + { 582 + return STATUS_INSUFFICIENT_RESOURCES; 583 + } 584 + 585 + /* create the new path string */ 586 + NewPath.Length = VolumeRootPath->Length; 587 + RtlCopyMemory(NewPath.Buffer, 588 + VolumeRootPath->Buffer, 589 + NewPath.Length); 590 + if (AddSep) 591 + { 592 + NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\\'; 593 + NewPath.Length += sizeof(WCHAR); 594 + } 595 + RtlCopyMemory(NewPath.Buffer + (NewPath.Length / sizeof(WCHAR)), 596 + DirectoryName.Buffer, 597 + DirectoryName.Length); 598 + NewPath.Length += DirectoryName.Length; 599 + NewPath.Buffer[NewPath.Length / sizeof(WCHAR)] = L'\0'; 600 + 601 + ASSERT(NewPath.Length == PathLen); 602 + ASSERT(NewPath.Length == NewPath.MaximumLength - sizeof(WCHAR)); 603 + 604 + /* create the security descriptor for the new directory */ 605 + Status = RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor, 606 + &SystemSid); 607 + if (NT_SUCCESS(Status)) 608 + { 609 + /* create or open the directory */ 610 + InitializeObjectAttributes(&ObjectAttributes, 611 + &NewPath, 612 + 0, 613 + NULL, 614 + SecurityDescriptor); 615 + 616 + Status = ZwCreateFile(&hDirectory, 617 + SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL, 618 + &ObjectAttributes, 619 + &IoStatusBlock, 620 + NULL, 621 + FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 622 + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 623 + FILE_OPEN_IF, 624 + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 625 + NULL, 626 + 0); 627 + if (!NT_SUCCESS(Status)) 628 + { 629 + Status = RtlpSysVolTakeOwnership(&NewPath, 630 + SecurityDescriptor); 631 + 632 + if (NT_SUCCESS(Status)) 633 + { 634 + /* successfully took ownership, attempt to open it */ 635 + Status = ZwCreateFile(&hDirectory, 636 + SYNCHRONIZE | WRITE_OWNER | WRITE_DAC | READ_CONTROL, 637 + &ObjectAttributes, 638 + &IoStatusBlock, 639 + NULL, 640 + FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, 641 + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 642 + FILE_OPEN_IF, 643 + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, 644 + NULL, 645 + 0); 646 + } 647 + } 648 + 649 + if (NT_SUCCESS(Status)) 650 + { 651 + /* check security now and adjust it if neccessary */ 652 + Status = RtlpSysVolCheckOwnerAndSecurity(hDirectory, 653 + SecurityDescriptor); 654 + ZwClose(hDirectory); 655 + } 656 + 657 + /* free allocated memory */ 658 + ASSERT(SecurityDescriptor != NULL); 659 + ASSERT(SecurityDescriptor->Dacl != NULL); 660 + 661 + RtlpFreeMemory(SecurityDescriptor->Dacl, 662 + 'cAeS'); 663 + RtlpFreeMemory(SecurityDescriptor, 664 + 'dSeS'); 665 + 666 + RtlFreeSid(SystemSid); 667 + } 668 + 669 + RtlpFreeStringMemory(NewPath.Buffer, 670 + TAG_USTR); 671 + return Status; 672 + } 673 + 674 + /* EOF */