ReactOS 0.4.16-dev-109-gf4cb10f
bcd.c File Reference
#include "bl.h"
#include <bcd.h>
Include dependency graph for bcd.c:

Go to the source code of this file.

Functions

VOID BiNotifyEnumerationError (_In_ HANDLE ObjectHandle, _In_ PWCHAR ElementName, _In_ NTSTATUS Status)
 
ULONG BiConvertElementFormatToValueType (_In_ ULONG Format)
 
NTSTATUS BiConvertRegistryDataToElement (_In_ HANDLE ObjectHandle, _In_ PVOID Data, _In_ ULONG DataLength, _In_ BcdElementType ElementType, _Out_ PVOID Element, _Out_ PULONG ElementSize)
 
NTSTATUS BiConvertBcdElements (_In_ PBCD_PACKED_ELEMENT Elements, _Out_opt_ PBCD_ELEMENT Buffer, _Inout_ PULONG BufferSize, _Inout_ PULONG ElementCount)
 
NTSTATUS BcdOpenObject (_In_ HANDLE BcdHandle, _In_ PGUID ObjectId, _Out_ PHANDLE ObjectHandle)
 
NTSTATUS BcdDeleteElement (_In_ HANDLE ObjectHandle, _In_ ULONG Type)
 
NTSTATUS BiEnumerateSubElements (_In_ HANDLE BcdHandle, _In_ PVOID Object, _In_ ULONG ElementType, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT *Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
 
NTSTATUS BiEnumerateSubObjectElements (_In_ HANDLE BcdHandle, _Out_ PGUID SubObjectList, _In_ ULONG SubObjectCount, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
 
NTSTATUS BiEnumerateElements (_In_ HANDLE BcdHandle, _In_ HANDLE ObjectHandle, _In_ ULONG RootElementType, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
 
NTSTATUS BiAddStoreFromFile (_In_ PBL_FILE_PATH_DESCRIPTOR FilePath, _Out_ PHANDLE StoreHandle)
 
NTSTATUS BiGetObjectDescription (_In_ HANDLE ObjectHandle, _Out_ PBCD_OBJECT_DESCRIPTION Description)
 
NTSTATUS BcdEnumerateAndUnpackElements (_In_ HANDLE BcdHandle, _In_ HANDLE ObjectHandle, _Out_opt_ PBCD_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
 
NTSTATUS BcdOpenStoreFromFile (_In_ PUNICODE_STRING FileName, _In_ PHANDLE BcdHandle)
 

Function Documentation

◆ BcdDeleteElement()

NTSTATUS BcdDeleteElement ( _In_ HANDLE  ObjectHandle,
_In_ ULONG  Type 
)

Definition at line 560 of file bcd.c.

564{
566 HANDLE ElementsHandle, ElementHandle;
567 WCHAR TypeString[22];
568
569 /* Open the elements key */
570 Status = BiOpenKey(ObjectHandle, L"Elements", &ElementsHandle);
571 if (NT_SUCCESS(Status))
572 {
573 /* Convert the element ID into a string */
574 if (!_ultow(Type, TypeString, 16))
575 {
576 /* Failed to do so */
578 }
579 else
580 {
581 /* Open the element specifically */
582 Status = BiOpenKey(ElementsHandle, TypeString, &ElementHandle);
583 if (NT_SUCCESS(Status))
584 {
585 /* Delete it */
586 Status = BiDeleteKey(ElementHandle);
587 if (NT_SUCCESS(Status))
588 {
589 /* No point in closing the handle anymore */
590 ElementHandle = NULL;
591 }
592 }
593 else
594 {
595 /* The element doesn't exist */
597 }
598
599 /* Check if we should close the key */
600 if (ElementHandle)
601 {
602 /* Do it */
603 BiCloseKey(ElementHandle);
604 }
605 }
606 }
607
608 /* Check if we should close the elements handle */
609 if (ElementsHandle)
610 {
611 /* Do it */
612 BiCloseKey(ElementsHandle);
613 }
614
615 /* Return whatever the result was */
616 return Status;
617}
Type
Definition: Type.h:7
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS BiOpenKey(_In_ HANDLE ParentHandle, _In_ PWCHAR KeyName, _Out_ PHANDLE Handle)
Definition: bootreg.c:186
VOID BiCloseKey(_In_ HANDLE KeyHandle)
Definition: bootreg.c:141
NTSTATUS BiDeleteKey(_In_ HANDLE KeyHandle)
Definition: bootreg.c:892
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
_CRTIMP wchar_t *__cdecl _ultow(_In_ unsigned long _Value, _Pre_notnull_ _Post_z_ wchar_t *_Dest, _In_ int _Radix)
#define L(x)
Definition: ntvdm.h:50
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by BmPurgeOption().

◆ BcdEnumerateAndUnpackElements()

NTSTATUS BcdEnumerateAndUnpackElements ( _In_ HANDLE  BcdHandle,
_In_ HANDLE  ObjectHandle,
_Out_opt_ PBCD_ELEMENT  Elements,
_Inout_ PULONG  ElementSize,
_Out_ PULONG  ElementCount 
)

Definition at line 1241 of file bcd.c.

1248{
1249 PVOID LocalElements;
1251 ULONG LocalElementCount, LocalElementSize;
1252
1253 /* Make sure required parameters are there */
1254 if (!(ElementSize) || !(ElementCount) || ((Elements) && (!*ElementSize)))
1255 {
1257 }
1258
1259 /* Set initial count to zero */
1260 *ElementCount = 0;
1261
1262 /* Do the initial enumeration to figure out the size required */
1263 LocalElementSize = 0;
1264 LocalElementCount = 0;
1265 Status = BiEnumerateElements(BcdHandle,
1266 ObjectHandle,
1267 0,
1271 NULL,
1272 &LocalElementSize,
1273 &LocalElementCount);
1275 {
1276 return Status;
1277 }
1278
1279 /* Now allocate a buffer large enough to hold them */
1280 LocalElements = BlMmAllocateHeap(LocalElementSize);
1281 if (!LocalElements)
1282 {
1284 }
1285
1286 /* Zero out the array and do the real enumeration this time around */
1287 RtlZeroMemory(LocalElements, LocalElementSize);
1288 Status = BiEnumerateElements(BcdHandle,
1289 ObjectHandle,
1290 0,
1294 LocalElements,
1295 &LocalElementSize,
1296 &LocalElementCount);
1297 if (!NT_SUCCESS(Status))
1298 {
1299 return Status;
1300 }
1301
1302 /* Now we know the real count */
1303 *ElementCount = LocalElementCount;
1304
1305 /* Now unpack the data */
1306 Status = BiConvertBcdElements(LocalElements,
1307 Elements,
1308 ElementSize,
1309 &LocalElementCount);
1310 if (NT_SUCCESS(Status))
1311 {
1312 /* Not all elements may have been converted */
1313 *ElementCount = LocalElementCount;
1314 }
1315
1316 /* Free the local (unpacked) buffer and return status */
1317 BlMmFreeHeap(LocalElements);
1318 return Status;
1319}
NTSTATUS BiEnumerateElements(_In_ HANDLE BcdHandle, _In_ HANDLE ObjectHandle, _In_ ULONG RootElementType, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
Definition: bcd.c:804
NTSTATUS BiConvertBcdElements(_In_ PBCD_PACKED_ELEMENT Elements, _Out_opt_ PBCD_ELEMENT Buffer, _Inout_ PULONG BufferSize, _Inout_ PULONG ElementCount)
Definition: bcd.c:350
#define BCD_ENUMERATE_FLAG_DEEP
Definition: bcd.h:315
#define BCD_ENUMERATE_FLAG_DEVICES
Definition: bcd.h:316
#define BCD_ENUMERATE_FLAG_IN_ORDER
Definition: bcd.h:317
PVOID BlMmAllocateHeap(_In_ SIZE_T Size)
Definition: heapalloc.c:569
NTSTATUS BlMmFreeHeap(_In_ PVOID Buffer)
Definition: heapalloc.c:663
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by BmGetOptionList().

◆ BcdOpenObject()

NTSTATUS BcdOpenObject ( _In_ HANDLE  BcdHandle,
_In_ PGUID  ObjectId,
_Out_ PHANDLE  ObjectHandle 
)

Definition at line 506 of file bcd.c.

511{
513 GUID LocalGuid;
515 HANDLE RootObjectHandle;
516
517 /* Assume failure */
518 *ObjectHandle = NULL;
519
520 /* Initialize GUID string */
521 GuidString.Buffer = NULL;
522
523 /* Open the root "Objects" handle */
524 RootObjectHandle = NULL;
525 Status = BiOpenKey(BcdHandle, L"Objects", &RootObjectHandle);
526 if (!NT_SUCCESS(Status))
527 {
528 goto Quickie;
529 }
530
531 /* Capture the object ID and convert it into a string */
532 LocalGuid = *ObjectId;
533 Status = RtlStringFromGUID(&LocalGuid, &GuidString);
534 if (!NT_SUCCESS(Status))
535 {
536 goto Quickie;
537 }
538
539 /* Now open the key containing this object ID */
540 Status = BiOpenKey(RootObjectHandle, GuidString.Buffer, ObjectHandle);
541
542Quickie:
543 /* Free the GUID string if we had one allocated */
544 if (GuidString.Buffer)
545 {
547 }
548
549 /* Close the root handle if it was open */
550 if (RootObjectHandle)
551 {
552 BiCloseKey(RootObjectHandle);
553 }
554
555 /* Return the final status */
556 return Status;
557}
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
static PWSTR GuidString
Definition: apphelp.c:93
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)

Referenced by BiEnumerateSubElements(), BmGetEntryDescription(), BmGetOptionList(), and BmPurgeOption().

◆ BcdOpenStoreFromFile()

NTSTATUS BcdOpenStoreFromFile ( _In_ PUNICODE_STRING  FileName,
_In_ PHANDLE  BcdHandle 
)

Definition at line 1322 of file bcd.c.

1326{
1327 ULONG Length;
1331
1332 /* Assume failure */
1333 LocalHandle = NULL;
1334
1335 /* Allocate a path descriptor */
1336 Length = FileName->Length + sizeof(*FilePath);
1338 if (!FilePath)
1339 {
1340 return STATUS_NO_MEMORY;
1341 }
1342
1343 /* Initialize it */
1344 FilePath->Version = 1;
1345 FilePath->PathType = InternalPath;
1346 FilePath->Length = Length;
1347
1348 /* Copy the name and NULL-terminate it */
1349 RtlCopyMemory(FilePath->Path, FileName->Buffer, Length);
1350 FilePath->Path[Length / sizeof(WCHAR)] = UNICODE_NULL;
1351
1352 /* Open the BCD */
1354 if (NT_SUCCESS(Status))
1355 {
1356 /* Return the handle on success */
1357 *BcdHandle = LocalHandle;
1358 }
1359
1360 /* Free the descriptor and return the status */
1362 return Status;
1363}
PCWSTR FilePath
NTSTATUS BiAddStoreFromFile(_In_ PBL_FILE_PATH_DESCRIPTOR FilePath, _Out_ PHANDLE StoreHandle)
Definition: bcd.c:1143
@ InternalPath
Definition: bl.h:284
HLOCAL NTAPI LocalHandle(LPCVOID pMem)
Definition: heapmem.c:1605
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263

Referenced by BmOpenDataStore().

◆ BiAddStoreFromFile()

NTSTATUS BiAddStoreFromFile ( _In_ PBL_FILE_PATH_DESCRIPTOR  FilePath,
_Out_ PHANDLE  StoreHandle 
)

Definition at line 1143 of file bcd.c.

1147{
1149 HANDLE HiveHandle, KeyHandle;
1150
1151 /* Load the specified hive */
1152 Status = BiLoadHive(FilePath, &HiveHandle);
1153 if (!NT_SUCCESS(Status))
1154 {
1155 return Status;
1156 }
1157
1158 /* Open the description key to make sure this is really a BCD */
1159 Status = BiOpenKey(HiveHandle, L"Description", &KeyHandle);
1160 if (NT_SUCCESS(Status))
1161 {
1162 /* It is -- close the key as we don't need it */
1164 *StoreHandle = HiveHandle;
1165 }
1166 else
1167 {
1168 /* Failure, drop a reference on the hive and close the key */
1169 BiDereferenceHive(HiveHandle);
1170 BiCloseKey(HiveHandle);
1171 }
1172
1173 /* Return the status */
1174 return Status;
1175}
VOID BiDereferenceHive(_In_ HANDLE KeyHandle)
Definition: bootreg.c:117
NTSTATUS BiLoadHive(_In_ PBL_FILE_PATH_DESCRIPTOR FilePath, _Out_ PHANDLE HiveHandle)
Definition: bootreg.c:369
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715

Referenced by BcdOpenStoreFromFile().

◆ BiConvertBcdElements()

NTSTATUS BiConvertBcdElements ( _In_ PBCD_PACKED_ELEMENT  Elements,
_Out_opt_ PBCD_ELEMENT  Buffer,
_Inout_ PULONG  BufferSize,
_Inout_ PULONG  ElementCount 
)

Definition at line 350 of file bcd.c.

356{
358 ULONG ElementSize, AlignedElementSize, AlignedDataSize;
360 PVOID Data;
361 BOOLEAN Exists;
362 ULONG i, j, Count;
363
364 /* Local variable to keep track of objects */
365 Count = 0;
366
367 /* Safely compute the element bytes needed */
368 Status = RtlULongMult(*ElementCount, sizeof(BCD_ELEMENT), &ElementSize);
369 if (!NT_SUCCESS(Status))
370 {
371 return Status;
372 }
373
374 /* Safely align the element size */
375 Status = RtlULongAdd(ElementSize,
376 sizeof(ULONG) - 1,
377 &AlignedElementSize);
378 if (!NT_SUCCESS(Status))
379 {
380 return Status;
381 }
382 AlignedElementSize = ALIGN_DOWN(AlignedElementSize, ULONG);
383
384 /* Do a safe version of Add2Ptr to figure out where the headers will start */
385 Status = RtlULongPtrAdd((ULONG_PTR)Buffer,
386 AlignedElementSize,
388 if (!NT_SUCCESS(Status))
389 {
390 return Status;
391 }
392
393 /* Safely compute the header bytes needed */
394 Status = RtlULongMult(*ElementCount,
395 sizeof(BCD_ELEMENT_HEADER),
396 &ElementSize);
397 if (!NT_SUCCESS(Status))
398 {
399 return Status;
400 }
401
402 /* Safely align the header size */
403 Status = RtlULongAdd(ElementSize,
404 AlignedElementSize + sizeof(ULONG) - 1,
405 &AlignedElementSize);
406 if (!NT_SUCCESS(Status))
407 {
408 return Status;
409 }
410 AlignedElementSize = ALIGN_DOWN(AlignedElementSize, ULONG);
411
412 /* Do a safe version of Add2Ptr */
413 Status = RtlULongPtrAdd((ULONG_PTR)Buffer,
414 AlignedElementSize,
415 (PULONG_PTR)&Data);
416 if (!NT_SUCCESS(Status))
417 {
418 return Status;
419 }
420
421 /* Iterate over every element */
422 for (i = 0; i < *ElementCount; i++)
423 {
424 /* Safely align the element size */
425 Status = RtlULongAdd(Elements->Size,
426 sizeof(ULONG) - 1,
427 &AlignedDataSize);
428 if (!NT_SUCCESS(Status))
429 {
430 break;
431 }
432 AlignedDataSize = ALIGN_DOWN(AlignedDataSize, ULONG);
433
434 /* Safely add the size of this data element */
435 Status = RtlULongAdd(AlignedElementSize,
436 AlignedDataSize,
437 &AlignedElementSize);
438 if (!NT_SUCCESS(Status))
439 {
440 break;
441 }
442
443 /* Do we have enough space left? */
444 if (*BufferSize >= AlignedElementSize)
445 {
446 /* Check if our root is an inherited object */
447 Exists = FALSE;
448 if (Elements->RootType.PackedValue == BcdLibraryObjectList_InheritedObjects)
449 {
450 /* Yes, scan for us in the current buffer */
451 for (j = 0; j < Count; j++)
452 {
453 /* Do we already exist? */
454 while (Buffer[j].Header->Type == Elements->RootType.PackedValue)
455 {
456 /* Yep */
457 Exists = TRUE;
458 break;
459 }
460 }
461 }
462
463 /* Have we already found ourselves? */
464 if (!Exists)
465 {
466 /* Nope, one more entry */
467 ++Count;
468
469 /* Write out the unpacked object */
470 Buffer->Body = Data;
471 Buffer->Header = Header;
472
473 /* Fill out its header */
474 Header->Size = Elements->Size;
475 Header->Type = Elements->Type;
476 Header->Version = Elements->Version;
477
478 /* And copy the data */
479 RtlCopyMemory(Data, Elements->Data, Header->Size);
480
481 /* Move to the next unpacked object and header */
482 ++Buffer;
483 ++Header;
484
485 /* Move to the next data entry */
486 Data = (PVOID)((ULONG_PTR)Data + AlignedDataSize);
487 }
488 }
489 else
490 {
491 /* Nope, set failure code, but keep going so we can return count */
493 }
494
495 /* Move to the next element entry */
496 Elements = Elements->NextEntry;
497 }
498
499 /* Return the new final buffer size and count */
500 *BufferSize = AlignedElementSize;
501 *ElementCount = Count;
502 return Status;
503}
unsigned char BOOLEAN
@ BcdLibraryObjectList_InheritedObjects
Definition: bcd.h:54
Definition: bufpool.h:45
Definition: Header.h:9
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
int Count
Definition: noreturn.cpp:7
Data(int index, int value)
Definition: sort_test.cpp:78
uint32_t * PULONG_PTR
Definition: typedefs.h:65
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define ALIGN_DOWN(size, type)
Definition: umtypes.h:88
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254

Referenced by BcdEnumerateAndUnpackElements().

◆ BiConvertElementFormatToValueType()

ULONG BiConvertElementFormatToValueType ( _In_ ULONG  Format)

Definition at line 31 of file bcd.c.

34{
35 /* Strings and objects are strings */
37 {
38 return REG_SZ;
39 }
40
41 /* Object lists are arrays of strings */
43 {
44 return REG_MULTI_SZ;
45 }
46
47 /* Everything else is binary */
48 return REG_BINARY;
49}
#define BCD_TYPE_OBJECT_LIST
Definition: bcd.h:24
#define BCD_TYPE_STRING
Definition: bcd.h:22
#define BCD_TYPE_OBJECT
Definition: bcd.h:23
#define REG_SZ
Definition: layer.c:22
#define REG_BINARY
Definition: nt_native.h:1496
#define REG_MULTI_SZ
Definition: nt_native.h:1501

Referenced by BiEnumerateElements().

◆ BiConvertRegistryDataToElement()

NTSTATUS BiConvertRegistryDataToElement ( _In_ HANDLE  ObjectHandle,
_In_ PVOID  Data,
_In_ ULONG  DataLength,
_In_ BcdElementType  ElementType,
_Out_ PVOID  Element,
_Out_ PULONG  ElementSize 
)

Definition at line 52 of file bcd.c.

60{
64 BOOLEAN NullTerminate;
65 PBCD_DEVICE_OPTION BcdDevice, ElementDevice;
66 PWCHAR BcdString, ElementString;
67 PGUID ElementGuid; UNICODE_STRING GuidString;
68 PULONGLONG ElementInteger;
69 PUSHORT ElementWord; PBOOLEAN BcdBoolean;
70
71 /* Assume failure */
73
74 /* Check what type of format we are dealing with */
75 switch (ElementType.Format)
76 {
77 /* Devices -- they are in a binary format */
78 case BCD_TYPE_DEVICE:
79
80 /* First, make sure it's at least big enough for an empty descriptor */
82 DeviceDescriptor.Unknown))
83 {
85 }
86
87 /* Both the registry and BCD format are the same */
88 BcdDevice = (PBCD_DEVICE_OPTION)Data;
89 ElementDevice = (PBCD_DEVICE_OPTION)Element;
90
91 /* Make sure the device fits in the registry data */
92 Device = &BcdDevice->DeviceDescriptor;
93 Size = Device->Size;
94 if ((Size + sizeof(BcdDevice->AssociatedEntry)) != DataLength)
95 {
97 }
98
99 /* Check if this is a locate device */
100 if (Device->DeviceType == LocateDevice)
101 {
102 EfiPrintf(L"Locates not yet supported\r\n");
104 }
105
106 /* Make sure the caller's buffer can fit the device */
107 ReturnedLength = Size + sizeof(BcdDevice->AssociatedEntry);
108 if (ReturnedLength > *ElementSize)
109 {
111 break;
112 }
113
114 /* It'll fit -- copy it in */
115 RtlCopyMemory(&ElementDevice->DeviceDescriptor, Device, Size);
116 ElementDevice->AssociatedEntry = BcdDevice->AssociatedEntry;
118 break;
119
120 /* Strings -- they are stored as is */
121 case BCD_TYPE_STRING:
122
123 /* Make sure the string isn't empty or misaligned */
124 if (!(DataLength) || (DataLength & 1))
125 {
127 }
128
129 /* Both the registry and BCD format are the same */
130 BcdString = (PWCHAR)Data;
131 ElementString = (PWCHAR)Element;
132
133 /* We'll need as much data as the string has to offer */
135
136 /* If the string isn't NULL-terminated, do it now */
137 NullTerminate = FALSE;
138 if (BcdString[(DataLength / sizeof(WCHAR)) - 1] != UNICODE_NULL)
139 {
140 ReturnedLength += sizeof(UNICODE_NULL);
141 NullTerminate = TRUE;
142 }
143
144 /* Will we fit in the caller's buffer? */
145 if (ReturnedLength > *ElementSize)
146 {
148 break;
149 }
150
151 /* Yep -- copy it in, and NULL-terminate if needed */
152 RtlCopyMemory(Element, Data, DataLength);
153 if (NullTerminate)
154 {
155 ElementString[DataLength / sizeof(WCHAR)] = UNICODE_NULL;
156 }
157
159 break;
160
161 /* Objects -- they are stored as GUID Strings */
162 case BCD_TYPE_OBJECT:
163
164 /* Registry data is a string, BCD data is a GUID */
165 BcdString = (PWCHAR)Data;
166 ElementGuid = (PGUID)Element;
167
168 /* We need a GUID-sized buffer, does the caller have one? */
169 ReturnedLength = sizeof(*ElementGuid);
170 if (*ElementSize < ReturnedLength)
171 {
173 break;
174 }
175
176 /* Yep, copy the GUID */
177 RtlInitUnicodeString(&GuidString, BcdString);
178 Status = RtlGUIDFromString(&GuidString, ElementGuid);
179 break;
180
181 /* Object Lists -- they are stored as arrays of GUID strings */
183
184 /* Assume an empty list*/
185 ReturnedLength = 0;
186 Length = 0;
188
189 /* Registry data is an array of strings, BCD data is array of GUIDs */
190 BcdString = (PWCHAR)Data;
191 ElementGuid = (PGUID)Element;
192
193 /* Loop as long as the array still has strings */
194 while (*BcdString)
195 {
196 /* Don't read beyond the registry data */
197 if (Length >= DataLength)
198 {
199 break;
200 }
201
202 /* One more GUID -- does the caller have space? */
203 ReturnedLength += sizeof(GUID);
204 if (ReturnedLength <= *ElementSize)
205 {
206 /* Convert and add it in */
207 RtlInitUnicodeString(&GuidString, BcdString);
208 Status = RtlGUIDFromString(&GuidString, ElementGuid);
209 if (!NT_SUCCESS(Status))
210 {
211 break;
212 }
213
214 /* Move to the next GUID in the caller's buffer */
215 ElementGuid++;
216 }
217
218 /* Move to the next string in the registry array */
219 Size = (wcslen(BcdString) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
220 Length += Size;
221 BcdString = (PWCHAR)((ULONG_PTR)BcdString + Length);
222 }
223
224 /* Check if we failed anywhere */
225 if (!NT_SUCCESS(Status))
226 {
227 break;
228 }
229
230 /* Check if we consumed more space than we have */
231 if (ReturnedLength > *ElementSize)
232 {
234 }
235
236 /* All good here */
237 break;
238
239 /* Integer -- stored as binary */
240 case BCD_TYPE_INTEGER:
241
242 /* BCD data is a ULONGLONG, registry data is 8 bytes binary */
243 ElementInteger = (PULONGLONG)Element;
244 ReturnedLength = sizeof(*ElementInteger);
245
246 /* Make sure the registry data makes sense */
248 {
250 }
251
252 /* Make sure the caller has space */
253 if (*ElementSize < ReturnedLength)
254 {
256 break;
257 }
258
259 /* Write the integer result */
260 *ElementInteger = 0;
261 RtlCopyMemory(ElementInteger, Data, DataLength);
263 break;
264
265 /* Boolean -- stored as binary */
266 case BCD_TYPE_BOOLEAN:
267
268 /* BCD data is a BOOLEAN, registry data is 2 bytes binary */
269 ElementWord = (PUSHORT)Element;
270 BcdBoolean = (PBOOLEAN)Data;
271 ReturnedLength = sizeof(ElementWord);
272
273 /* Make sure the registry data makes sense */
274 if (DataLength != sizeof(*BcdBoolean))
275 {
277 }
278
279 /* Make sure the caller has space */
280 if (*ElementSize < ReturnedLength)
281 {
283 break;
284 }
285
286 /* Write the boolean result */
287 *ElementWord = 0;
288 *ElementWord = *BcdBoolean != 0;
290 break;
291
292 /* Integer list --stored as binary */
294
295 /* BCD Data is n ULONGLONGs, registry data is n*8 bytes binary */
297 if (!(DataLength) || (DataLength & 7))
298 {
300 }
301
302 /* Make sure the caller has space */
303 if (*ElementSize < ReturnedLength)
304 {
306 break;
307 }
308
309 /* Write the integer list result */
310 RtlCopyMemory(Element, Data, DataLength);
312 break;
313
314 /* Arbitrary data */
315 default:
316
317 /* Registry data is copied binary as-is */
319
320 /* Make sure it's not empty */
321 if (!DataLength)
322 {
324 }
325
326 /* Make sure the caller has space */
327 if (*ElementSize < ReturnedLength)
328 {
330 break;
331 }
332
333 /* Write the result */
334 RtlCopyMemory(Element, Data, DataLength);
336 break;
337 }
338
339 /* If we got here due to success or space issues, write the size */
341 {
342 *ElementSize = ReturnedLength;
343 }
344
345 /* All done, return our conversion result */
346 return Status;
347}
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:188
#define BCD_TYPE_INTEGER
Definition: bcd.h:25
struct _BCD_DEVICE_OPTION * PBCD_DEVICE_OPTION
#define BCD_TYPE_INTEGER_LIST
Definition: bcd.h:27
#define BCD_TYPE_BOOLEAN
Definition: bcd.h:26
#define BCD_TYPE_DEVICE
Definition: bcd.h:21
GUID * PGUID
Definition: bdasup.h:12
VOID EfiPrintf(_In_ PWCHAR Format,...)
Definition: firmware.c:126
@ LocateDevice
Definition: bl.h:253
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
#define STATUS_SUCCESS
Definition: shellext.h:65
const KSDEVICE_DESCRIPTOR DeviceDescriptor
Definition: splitter.c:257
BL_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: bcd.h:298
GUID AssociatedEntry
Definition: bcd.h:297
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint16_t * PUSHORT
Definition: typedefs.h:56
uint16_t * PWCHAR
Definition: typedefs.h:56
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by BiEnumerateElements().

◆ BiEnumerateElements()

NTSTATUS BiEnumerateElements ( _In_ HANDLE  BcdHandle,
_In_ HANDLE  ObjectHandle,
_In_ ULONG  RootElementType,
_In_ ULONG  Flags,
_Out_opt_ PBCD_PACKED_ELEMENT  Elements,
_Inout_ PULONG  ElementSize,
_Out_ PULONG  ElementCount 
)

Definition at line 804 of file bcd.c.

813{
814 HANDLE ElementsHandle, ElementHandle;
815 ULONG TotalLength, RegistryElementDataLength, RemainingLength;
817 ULONG i;
818 PVOID ElementData, SubObjectList, RegistryElementData;
819 BcdElementType ElementType;
820 PBCD_PACKED_ELEMENT PreviousElement, ElementsStart;
821 ULONG SubElementCount, SubKeyCount, SubObjectCount, ElementDataLength;
822 PWCHAR ElementName;
823 PWCHAR* SubKeys;
824
825 /* Assume failure */
826 *ElementCount = 0;
827
828 /* Initialize all locals that are checked at the end*/
829 SubKeys = NULL;
830 ElementsHandle = NULL;
831 ElementHandle = NULL;
832 ElementData = NULL;
833 RegistryElementData = NULL;
834 PreviousElement = NULL;
835 ElementName = NULL;
836 SubObjectList = NULL;
837 TotalLength = 0;
838 ElementDataLength = 0;
839 SubObjectCount = 0;
840 RemainingLength = 0;
841 ElementsStart = Elements;
842
843 /* Open the root object key's elements */
844 Status = BiOpenKey(ObjectHandle, L"Elements", &ElementsHandle);
845 if (!NT_SUCCESS(Status))
846 {
847 goto Quickie;
848 }
849
850 /* Enumerate all elements */
851 Status = BiEnumerateSubKeys(ElementsHandle, &SubKeys, &SubKeyCount);
852 if (!NT_SUCCESS(Status))
853 {
854 goto Quickie;
855 }
856
857 /* Iterate over each one */
858 for (i = 0; i < SubKeyCount; i++)
859 {
860 /* Open the element */
861 ElementName = SubKeys[i];
862 Status = BiOpenKey(ElementsHandle, ElementName, &ElementHandle);
863 if (!NT_SUCCESS(Status))
864 {
865 EfiPrintf(L"ELEMENT ERROR: %lx\r\n", Status);
866 EfiStall(100000);
867 break;
868 }
869
870 /* The name of the element is its data type */
871 ElementType.PackedValue = wcstoul(SubKeys[i], NULL, 16);
872 if (!(ElementType.PackedValue) || (ElementType.PackedValue == -1))
873 {
874 EfiPrintf(L"Value invalid\r\n");
875 BiCloseKey(ElementHandle);
876 ElementHandle = NULL;
877 continue;
878 }
879
880 /* Read the appropriate registry value type for this element */
881 Status = BiGetRegistryValue(ElementHandle,
882 L"Element",
884 ElementType.Format),
885 &RegistryElementData,
886 &RegistryElementDataLength);
887 if (!NT_SUCCESS(Status))
888 {
889 EfiPrintf(L"Element invalid\r\n");
890 break;
891 }
892
893 /* Now figure out how much space the converted element will need */
894 ElementDataLength = 0;
896 RegistryElementData,
897 RegistryElementDataLength,
898 ElementType,
899 NULL,
900 &ElementDataLength);
902 {
903 break;
904 }
905
906 /* Allocate a buffer big enough for the converted element */
907 ElementData = BlMmAllocateHeap(ElementDataLength);
908 if (!ElementData)
909 {
911 break;
912 }
913
914 /* And actually convert it this time around */
916 RegistryElementData,
917 RegistryElementDataLength,
918 ElementType,
919 ElementData,
920 &ElementDataLength);
921 if (!NT_SUCCESS(Status))
922 {
923 break;
924 }
925
926 /* Safely add space for the packed element header */
927 Status = RtlULongAdd(TotalLength,
929 &TotalLength);
930 if (!NT_SUCCESS(Status))
931 {
932 break;
933 }
934
935 /* Safely add space for the data of the element itself */
936 Status = RtlULongAdd(TotalLength, ElementDataLength, &TotalLength);
937 if (!NT_SUCCESS(Status))
938 {
939 break;
940 }
941
942 /* One more element */
943 ++*ElementCount;
944
945 /* See how much space we were given */
946 RemainingLength = *ElementSize;
947 if (RemainingLength >= TotalLength)
948 {
949 /* Set the next pointer */
950 Elements->NextEntry = (PBCD_PACKED_ELEMENT)((ULONG_PTR)ElementsStart + TotalLength);
951
952 /* Fill this one out */
953 Elements->RootType.PackedValue = RootElementType;
954 Elements->Version = 1;
955 Elements->Type = ElementType.PackedValue;
956 Elements->Size = ElementDataLength;
957
958 /* Add the data */
959 RtlCopyMemory(Elements->Data, ElementData, ElementDataLength);
960 RemainingLength -= TotalLength;
961
962 /* Move to the next element on the next pass */
963 PreviousElement = Elements;
964 Elements = Elements->NextEntry;
965 }
966 else
967 {
968 /* We're out of space */
969 RemainingLength = 0;
970 }
971
972 /* Are we enumerating devices, and is this a device? */
974 (ElementType.Format == BCD_TYPE_DEVICE))
975 {
976 /* Yep, so go inside to enumerate it */
977 Status = BiEnumerateSubElements(BcdHandle,
978 ElementData,
979 ElementType.PackedValue,
980 Flags,
981 &Elements,
982 &ElementDataLength,
983 &SubElementCount);
985 {
986 /* Safely add the length of the sub elements */
987 Status = RtlULongAdd(TotalLength,
988 ElementDataLength,
989 &TotalLength);
990 if (!NT_SUCCESS(Status))
991 {
992 break;
993 }
994
995 /* Add the sub elements to the total */
996 *ElementCount += SubElementCount;
997
998 /* See if we have enough space*/
999 if (*ElementSize >= TotalLength)
1000 {
1001 /* Were there any subelements? */
1002 if (SubElementCount)
1003 {
1004 /* Update to keep track of these new subelements */
1005 ElementDataLength = *ElementSize - TotalLength;
1006
1007 /* Link the subelements into the chain */
1008 PreviousElement = Elements;
1009 PreviousElement->NextEntry =
1010 (PBCD_PACKED_ELEMENT)((ULONG_PTR)ElementsStart +
1011 TotalLength);
1012 Elements = PreviousElement->NextEntry;
1013 }
1014 }
1015 else
1016 {
1017 /* We're out of space */
1018 ElementDataLength = 0;
1019 }
1020 }
1021 else if ((Status != STATUS_NOT_FOUND) &&
1023 {
1024 /* Fatal error trying to read the data, so fail */
1025 break;
1026 }
1027 }
1028 else if ((Flags & BCD_ENUMERATE_FLAG_DEEP) &&
1030 {
1031 /* Inherited objects are requested, so allocate a buffer for them */
1032 SubObjectList = BlMmAllocateHeap(ElementDataLength);
1033 if (!SubObjectList)
1034 {
1036 break;
1037 }
1038
1039 /* Copy the elements into the list. They are arrays of GUIDs */
1040 RtlCopyMemory(SubObjectList, ElementData, ElementDataLength);
1041 SubObjectCount = ElementDataLength / sizeof(GUID);
1042 }
1043
1044 /* Free our local buffers */
1045 BlMmFreeHeap(ElementData);
1046 BlMmFreeHeap(RegistryElementData);
1047 ElementData = NULL;
1048 RegistryElementData = NULL;
1049
1050 /* Close the key */
1051 BiCloseKey(ElementHandle);
1052 ElementHandle = NULL;
1053 ElementName = NULL;
1054 }
1055
1056 /* Did we end up here with a sub object list after successful loop parsing? */
1057 if ((i != 0) && (i == SubKeyCount) && (SubObjectList))
1058 {
1059 /* We will actually enumerate it now, at the end */
1061 SubObjectList,
1062 SubObjectCount,
1063 Flags,
1064 Elements,
1065 &RemainingLength,
1066 &SubElementCount);
1068 {
1069 /* Safely add the length of the sub elements */
1070 Status = RtlULongAdd(TotalLength, RemainingLength, &TotalLength);
1071 if ((NT_SUCCESS(Status)) && (SubElementCount))
1072 {
1073 /* Add the sub elements to the total */
1074 *ElementCount += SubElementCount;
1075
1076 /* Don't touch PreviousElement anymore */
1077 PreviousElement = NULL;
1078 }
1079 }
1080 }
1081
1082Quickie:
1083 /* Free the sub object list, if any */
1084 if (SubObjectList)
1085 {
1086 BlMmFreeHeap(SubObjectList);
1087 }
1088
1089 /* Free any local element data */
1090 if (ElementData)
1091 {
1092 BlMmFreeHeap(ElementData);
1093 }
1094
1095 /* Free any local registry data */
1096 if (RegistryElementData)
1097 {
1098 BlMmFreeHeap(RegistryElementData);
1099 }
1100
1101 /* Close the handle if still opened */
1102 if (ElementHandle)
1103 {
1104 BiCloseKey(ElementHandle);
1105 }
1106
1107 /* Terminate the last element, if any */
1108 if (PreviousElement)
1109 {
1110 PreviousElement->NextEntry = NULL;
1111 }
1112
1113 /* Close the root handle if still opened */
1114 if (ElementsHandle)
1115 {
1116 BiCloseKey(ElementsHandle);
1117 }
1118
1119 /* Set failure code if out of space */
1120 if (*ElementSize < TotalLength)
1121 {
1123 }
1124
1125 /* Other errors will send a notification error */
1127 {
1128 BiNotifyEnumerationError(ObjectHandle, ElementName, Status);
1129 }
1130
1131 /* Finally free the subkeys array */
1132 if (SubKeys)
1133 {
1134 BlMmFreeHeap(SubKeys);
1135 }
1136
1137 /* And return the required, final length and status */
1138 *ElementSize = TotalLength;
1139 return Status;
1140}
VOID BiNotifyEnumerationError(_In_ HANDLE ObjectHandle, _In_ PWCHAR ElementName, _In_ NTSTATUS Status)
Definition: bcd.c:17
ULONG BiConvertElementFormatToValueType(_In_ ULONG Format)
Definition: bcd.c:31
NTSTATUS BiEnumerateSubElements(_In_ HANDLE BcdHandle, _In_ PVOID Object, _In_ ULONG ElementType, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT *Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
Definition: bcd.c:620
NTSTATUS BiConvertRegistryDataToElement(_In_ HANDLE ObjectHandle, _In_ PVOID Data, _In_ ULONG DataLength, _In_ BcdElementType ElementType, _Out_ PVOID Element, _Out_ PULONG ElementSize)
Definition: bcd.c:52
NTSTATUS BiEnumerateSubObjectElements(_In_ HANDLE BcdHandle, _Out_ PGUID SubObjectList, _In_ ULONG SubObjectCount, _In_ ULONG Flags, _Out_opt_ PBCD_PACKED_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
Definition: bcd.c:688
struct _BCD_PACKED_ELEMENT * PBCD_PACKED_ELEMENT
NTSTATUS BiGetRegistryValue(_In_ HANDLE KeyHandle, _In_ PWCHAR ValueName, _In_ ULONG Type, _Out_ PVOID *Buffer, _Out_ PULONG ValueLength)
Definition: bootreg.c:657
NTSTATUS EfiStall(_In_ ULONG StallTime)
Definition: firmware.c:1003
NTSTATUS BiEnumerateSubKeys(_In_ HANDLE KeyHandle, _Out_ PWCHAR **SubKeyList, _Out_ PULONG SubKeyCount)
Definition: bootreg.c:723
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
ULONG PackedValue
Definition: bcd.h:234
ULONG Format
Definition: bcd.h:238
struct _BCD_PACKED_ELEMENT * NextEntry
Definition: bcd.h:283
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_In_ ULONG TotalLength
Definition: usbdlib.h:158
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by BcdEnumerateAndUnpackElements(), and BiEnumerateSubElements().

◆ BiEnumerateSubElements()

NTSTATUS BiEnumerateSubElements ( _In_ HANDLE  BcdHandle,
_In_ PVOID  Object,
_In_ ULONG  ElementType,
_In_ ULONG  Flags,
_Out_opt_ PBCD_PACKED_ELEMENT Elements,
_Inout_ PULONG  ElementSize,
_Out_ PULONG  ElementCount 
)

Definition at line 620 of file bcd.c.

629{
631 PBCD_PACKED_ELEMENT Element;
632 HANDLE ObjectHandle;
633 ULONG ParsedElements, RequiredSize;
634
635 /* Assume empty */
636 *ElementCount = 0;
637 RequiredSize = 0;
638 ParsedElements = 0;
639
640 /* Open the object */
641 Status = BcdOpenObject(BcdHandle, Object, &ObjectHandle);
642 if (!NT_SUCCESS(Status))
643 {
644 goto Quickie;
645 }
646
647 /* Read the first entry, and the size available */
648 Element = *Elements;
649 RequiredSize = *ElementSize;
650
651 /* Enumerate the object into the element array */
652 Status = BiEnumerateElements(BcdHandle,
653 ObjectHandle,
654 ElementType,
655 Flags,
656 Element,
658 &ParsedElements);
659
660 /* Close the handle and bail out if we couldn't enumerate */
661 BiCloseKey(ObjectHandle);
662 if (!NT_SUCCESS(Status))
663 {
664 goto Quickie;
665 }
666
667 /* Check if the and subelements were present */
668 if (ParsedElements)
669 {
670 /* Keep going until the last one */
671 while (Element->NextEntry)
672 {
673 Element = Element->NextEntry;
674 }
675
676 /* Set the new buffer location to the last element */
677 *Elements = Element;
678 }
679
680Quickie:
681 /* Return the number of sub-elements and their size */
682 *ElementCount = ParsedElements;
683 *ElementSize = RequiredSize;
684 return Status;
685}
NTSTATUS BcdOpenObject(_In_ HANDLE BcdHandle, _In_ PGUID ObjectId, _Out_ PHANDLE ObjectHandle)
Definition: bcd.c:506
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ ULONG _Out_ PVOID _Out_ PULONG RequiredSize
Definition: wdfdevice.h:4439

Referenced by BiEnumerateElements(), and BiEnumerateSubObjectElements().

◆ BiEnumerateSubObjectElements()

NTSTATUS BiEnumerateSubObjectElements ( _In_ HANDLE  BcdHandle,
_Out_ PGUID  SubObjectList,
_In_ ULONG  SubObjectCount,
_In_ ULONG  Flags,
_Out_opt_ PBCD_PACKED_ELEMENT  Elements,
_Inout_ PULONG  ElementSize,
_Out_ PULONG  ElementCount 
)

Definition at line 688 of file bcd.c.

697{
699 ULONG SubElementCount, TotalSize, RequiredSize, CurrentSize, i;
700 PBCD_PACKED_ELEMENT PreviousElement;
701
702 /* Assume empty list */
703 *ElementCount = 0;
705
706 /* Initialize variables */
707 TotalSize = 0;
708 PreviousElement = NULL;
709
710 /* Set the currently remaining size based on caller's input */
711 CurrentSize = *ElementSize;
712
713 /* Iterate over every subje object */
714 for (i = 0; i < SubObjectCount; i++)
715 {
716 /* Set the currently remaining buffer space */
717 RequiredSize = CurrentSize;
718
719 /* Enumerate the inherited sub elements */
720 Status = BiEnumerateSubElements(BcdHandle,
721 &SubObjectList[i],
723 Flags,
724 &Elements,
726 &SubElementCount);
728 {
729 /* Safely add the length of the sub elements */
730 Status = RtlULongAdd(TotalSize, RequiredSize, &TotalSize);
731 if (!NT_SUCCESS(Status))
732 {
733 break;
734 }
735
736 /* Add the sub elements to the total */
737 *ElementCount += SubElementCount;
738
739 /* See if we have enough space*/
740 if (*ElementSize >= TotalSize)
741 {
742 /* Were there any subelements? */
743 if (SubElementCount)
744 {
745 /* Update to keep track of these new subelements */
746 CurrentSize = *ElementSize - TotalSize;
747
748 /* Link the subelements into the chain */
749 PreviousElement = Elements;
750 PreviousElement->NextEntry =
751 (PBCD_PACKED_ELEMENT)((ULONG_PTR)Elements + TotalSize);
752 Elements = PreviousElement->NextEntry;
753 }
754 }
755 else
756 {
757 /* We're out of space */
758 CurrentSize = 0;
759 }
760 }
761 else if ((Status != STATUS_NOT_FOUND) &&
763 {
764 /* Some other fatal error, break out */
765 break;
766 }
767 else
768 {
769 /* The sub element was not found, print a warning but keep going */
770 BlStatusPrint(L"Ignoring missing BCD inherit object: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
771 (&SubObjectList[i])->Data1,
772 (&SubObjectList[i])->Data2,
773 (&SubObjectList[i])->Data3,
774 (&SubObjectList[i])->Data4[0],
775 (&SubObjectList[i])->Data4[1],
776 (&SubObjectList[i])->Data4[2],
777 (&SubObjectList[i])->Data4[3],
778 (&SubObjectList[i])->Data4[4],
779 (&SubObjectList[i])->Data4[5],
780 (&SubObjectList[i])->Data4[6],
781 (&SubObjectList[i])->Data4[7]);
783 }
784 }
785
786 /* Terminate the last element, if one was left */
787 if (PreviousElement)
788 {
789 PreviousElement->NextEntry = NULL;
790 }
791
792 /* Set failure code if we ran out of space */
793 if (*ElementSize < TotalSize)
794 {
796 }
797
798 /* Return final length and status */
799 *ElementSize = TotalSize;
800 return Status;
801}
VOID BlStatusPrint(_In_ PCWCH Format,...)
Definition: debug.c:75

Referenced by BiEnumerateElements().

◆ BiGetObjectDescription()

NTSTATUS BiGetObjectDescription ( _In_ HANDLE  ObjectHandle,
_Out_ PBCD_OBJECT_DESCRIPTION  Description 
)

Definition at line 1178 of file bcd.c.

1182{
1184 HANDLE DescriptionHandle;
1185 PULONG Data;
1186 ULONG Length;
1187
1188 /* Initialize locals */
1189 Data = NULL;
1190 DescriptionHandle = NULL;
1191
1192 /* Open the description key */
1193 Status = BiOpenKey(ObjectHandle, L"Description", &DescriptionHandle);
1194 if (NT_SUCCESS(Status))
1195 {
1196 /* It exists */
1197 Description->Valid = TRUE;
1198
1199 /* Read the type */
1200 Length = 0;
1201 Status = BiGetRegistryValue(DescriptionHandle,
1202 L"Type",
1203 REG_DWORD,
1204 (PVOID*)&Data,
1205 &Length);
1206 if (NT_SUCCESS(Status))
1207 {
1208 /* Make sure it's the length we expected it to be */
1209 if (Length == sizeof(Data))
1210 {
1211 /* Return the type that is stored there */
1212 Description->Type = *Data;
1213 }
1214 else
1215 {
1216 /* Invalid type value */
1218 }
1219 }
1220 }
1221
1222 /* Did we have a handle open? */
1223 if (DescriptionHandle)
1224 {
1225 /* Close it */
1226 BiCloseKey(DescriptionHandle);
1227 }
1228
1229 /* Did we have data allocated? */
1230 if (Data)
1231 {
1232 /* Free it */
1234 }
1235
1236 /* Return back to caller */
1237 return Status;
1238}
static const WCHAR Description[]
Definition: oid.c:1266
#define REG_DWORD
Definition: sdbapi.c:596
uint32_t * PULONG
Definition: typedefs.h:59

Referenced by BmGetEntryDescription().

◆ BiNotifyEnumerationError()

VOID BiNotifyEnumerationError ( _In_ HANDLE  ObjectHandle,
_In_ PWCHAR  ElementName,
_In_ NTSTATUS  Status 
)

Definition at line 17 of file bcd.c.

22{
23 /* Stub for now */
24 UNREFERENCED_PARAMETER(ObjectHandle);
25 UNREFERENCED_PARAMETER(ElementName);
27 EfiPrintf(L"Error in BiNotify: %lx for element %s\r\n", Status, ElementName);
28}
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317

Referenced by BiEnumerateElements().