[RTL] Revert b3b2a23 which introduced a regression.
[reactos.git] / sdk / lib / rtl / bootdata.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
13 #define NDEBUG
14 #include <debug.h>
15
16 typedef struct _RTL_BSD_ITEM
17 {
18 ULONG Offset;
19 ULONG Size;
20 } RTL_BSD_ITEM, *PRTL_BSD_ITEM;
21
22 /* FUNCTIONS *****************************************************************/
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)
31 {
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 {
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))
443 {
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))
459 {
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))
478 {
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))
495 {
496 goto Cleanup;
497 }
498
499 /* create the security descriptor */
500 Status = RtlCreateSecurityDescriptor(&AbsSD,
501 SECURITY_DESCRIPTOR_REVISION);
502 if (!NT_SUCCESS(Status))
503 {
504 goto Cleanup;
505 }
506
507 Status = RtlSetOwnerSecurityDescriptor(&AbsSD,
508 AdminSid,
509 FALSE);
510 if (!NT_SUCCESS(Status))
511 {
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)
522 {
523 ZwAdjustPrivilegesToken(hToken,
524 FALSE,
525 &TokenPrivileges,
526 0,
527 NULL,
528 NULL);
529 }
530
531 if (AdminSid != NULL)
532 {
533 RtlFreeSid(AdminSid);
534 }
535
536 if (hDirectory != NULL)
537 {
538 ZwClose(hDirectory);
539 }
540
541 if (hToken != NULL)
542 {
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)
575 {
576 return STATUS_INVALID_PARAMETER;
577 }
578
579 if (VolumeRootPath->Buffer[(VolumeRootPath->Length / sizeof(WCHAR)) - 1] != L'\\')
580 {
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)
590 {
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)
600 {
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))
617 {
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 }
682
683 /*
684 * @implemented
685 */
686 NTSTATUS
687 NTAPI
688 RtlCreateBootStatusDataFile(VOID)
689 {
690 OBJECT_ATTRIBUTES ObjectAttributes;
691 IO_STATUS_BLOCK IoStatusBlock;
692 LARGE_INTEGER AllocationSize;
693 LARGE_INTEGER ByteOffset;
694 UNICODE_STRING FileName;
695 HANDLE FileHandle;
696 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);
708
709 AllocationSize.QuadPart = 0x800;
710 DBG_UNREFERENCED_LOCAL_VARIABLE(AllocationSize);
711
712 /* Create the boot status data file */
713 Status = ZwCreateFile(&FileHandle,
714 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
715 &ObjectAttributes,
716 &IoStatusBlock,
717 NULL, //&AllocationSize,
718 FILE_ATTRIBUTE_SYSTEM,
719 0,
720 FILE_CREATE,
721 FILE_SYNCHRONOUS_IO_NONALERT,
722 NULL,
723 0);
724 if (NT_SUCCESS(Status))
725 {
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};
728
729 ByteOffset.QuadPart = 0;
730 Status = ZwWriteFile(FileHandle,
731 NULL,
732 NULL,
733 NULL,
734 &IoStatusBlock,
735 &Buffer,
736 12, //BufferSize,
737 &ByteOffset,
738 NULL);
739 }
740
741 /* Close the file */
742 ZwClose(FileHandle);
743
744 return Status;
745 }
746
747 /*
748 * @implemented
749 */
750 NTSTATUS
751 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)
758 {
759 IO_STATUS_BLOCK IoStatusBlock;
760 LARGE_INTEGER ByteOffset;
761 NTSTATUS Status;
762
763 DPRINT("RtlGetSetBootStatusData (%p %u %d %p %lu %p)\n",
764 FileHandle, WriteMode, DataClass, Buffer, BufferSize, ReturnLength);
765
766 if (DataClass >= RtlBsdItemMax)
767 return STATUS_INVALID_PARAMETER;
768
769 if (BufferSize > BsdItemTable[DataClass].Size)
770 return STATUS_BUFFER_TOO_SMALL;
771
772 ByteOffset.HighPart = 0;
773 ByteOffset.LowPart = BsdItemTable[DataClass].Offset;
774
775 if (WriteMode)
776 {
777 Status = ZwReadFile(FileHandle,
778 NULL,
779 NULL,
780 NULL,
781 &IoStatusBlock,
782 Buffer,
783 BufferSize,
784 &ByteOffset,
785 NULL);
786 }
787 else
788 {
789 Status = ZwWriteFile(FileHandle,
790 NULL,
791 NULL,
792 NULL,
793 &IoStatusBlock,
794 Buffer,
795 BufferSize,
796 &ByteOffset,
797 NULL);
798 }
799
800 if (NT_SUCCESS(Status))
801 {
802 if (ReturnLength)
803 *ReturnLength = BsdItemTable[DataClass].Size;
804 }
805
806 return Status;
807 }
808
809 /*
810 * @implemented
811 */
812 NTSTATUS
813 NTAPI
814 RtlLockBootStatusData(OUT PHANDLE FileHandle)
815 {
816 OBJECT_ATTRIBUTES ObjectAttributes;
817 IO_STATUS_BLOCK IoStatusBlock;
818 UNICODE_STRING FileName;
819 HANDLE LocalFileHandle;
820 NTSTATUS Status;
821
822 /* Intialize the file handle */
823 *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
836 /* Open the boot status data file */
837 Status = ZwOpenFile(&LocalFileHandle,
838 FILE_ALL_ACCESS,
839 &ObjectAttributes,
840 &IoStatusBlock,
841 0,
842 FILE_SYNCHRONOUS_IO_NONALERT);
843 if (NT_SUCCESS(Status))
844 {
845 /* Return the file handle */
846 *FileHandle = LocalFileHandle;
847 }
848
849 return Status;
850 }
851
852 /*
853 * @implemented
854 */
855 NTSTATUS
856 NTAPI
857 RtlUnlockBootStatusData(IN HANDLE FileHandle)
858 {
859 IO_STATUS_BLOCK IoStatusBlock;
860
861 /* Flush the file and close it */
862 ZwFlushBuffersFile(FileHandle,
863 &IoStatusBlock);
864
865 return ZwClose(FileHandle);
866 }
867
868 /* EOF */