NTSTATUS BlGetBootOptionString ( _In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PWCHAR* Value ) { NTSTATUS Status; PBL_BCD_OPTION Option; PWCHAR String, StringCopy; ULONG StringLength; BcdElementType ElementType; //PGUID AppIdentifier; /* Make sure this is a BCD_STRING */ ElementType.PackedValue = Type; if (ElementType.Format != BCD_TYPE_STRING) { return STATUS_INVALID_PARAMETER; } /* Return the data */ Option = MiscGetBootOption(List, Type); if (Option) { /* Extract the string */ String = (PWCHAR)((ULONG_PTR)Option + Option->DataOffset); Status = STATUS_SUCCESS; } else { /* No string is present */ String = NULL; Status = STATUS_NOT_FOUND; } /* Compute the data size */ StringLength = Option->DataSize / sizeof(WCHAR); #ifdef _SECURE_BOOT_ /* Filter out SecureBoot Options */ AppIdentifier = BlGetApplicationIdentifier(); Status = BlpBootOptionCallbackString(AppIdentifier, Type, String, StringLength, &String, &StringLength); #else #endif /* Make sure we have a valid, non-filtered string */ if (NT_SUCCESS(Status)) { /* Check if we have space for one more character */ Status = RtlULongAdd(StringLength, 1, &StringLength); if (NT_SUCCESS(Status)) { /* Check if it's safe to multiply by two */ Status = RtlULongMult(StringLength, sizeof(WCHAR), &StringLength); if (NT_SUCCESS(Status)) { /* Allocate a copy for the string */ StringCopy = BlMmAllocateHeap(StringLength); if (StringCopy) { /* NULL-terminate it */ RtlCopyMemory(StringCopy, String, StringLength - sizeof(UNICODE_NULL)); StringCopy[StringLength] = UNICODE_NULL; *Value = StringCopy; Status = STATUS_SUCCESS; } else { /* No memory, fail */ Status = STATUS_NO_MEMORY; } } } } /* All done */ return Status; }
PDRIVE_LAYOUT_INFORMATION DiskConvertExtendedToLayout( IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx ) { ULONG i; ULONG LayoutSize; PDRIVE_LAYOUT_INFORMATION Layout; PPARTITION_INFORMATION Partition; PPARTITION_INFORMATION_EX PartitionEx; NTSTATUS status; PAGED_CODE (); ASSERT ( LayoutEx ); // // The only valid conversion is from an MBR extended layout structure to // the old structure. // if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR) { ASSERT ( FALSE ); return NULL; } // // Use safe interger function // status = RtlULongMult(LayoutEx->PartitionCount, sizeof(PARTITION_INFORMATION), &LayoutSize); if (!NT_SUCCESS(status)) { return NULL; } status = RtlULongAdd(LayoutSize, FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]), &LayoutSize); if (!NT_SUCCESS(status)) { return NULL; } Layout = ExAllocatePoolWithTag ( NonPagedPool, LayoutSize, DISK_TAG_PART_LIST ); if ( Layout == NULL ) { return NULL; } Layout->Signature = LayoutEx->Mbr.Signature; Layout->PartitionCount = LayoutEx->PartitionCount; for (i = 0; i < LayoutEx->PartitionCount; i++) { Partition = &Layout->PartitionEntry[i]; PartitionEx = &LayoutEx->PartitionEntry[i]; Partition->StartingOffset = PartitionEx->StartingOffset; Partition->PartitionLength = PartitionEx->PartitionLength; Partition->RewritePartition = PartitionEx->RewritePartition; Partition->PartitionNumber = PartitionEx->PartitionNumber; Partition->PartitionType = PartitionEx->Mbr.PartitionType; Partition->BootIndicator = PartitionEx->Mbr.BootIndicator; Partition->RecognizedPartition = PartitionEx->Mbr.RecognizedPartition; Partition->HiddenSectors = PartitionEx->Mbr.HiddenSectors; } return Layout; }
NTSTATUS BiConvertBcdElements ( _In_ PBCD_PACKED_ELEMENT Elements, _Out_opt_ PBCD_ELEMENT Buffer, _Inout_ PULONG BufferSize, _Inout_ PULONG ElementCount ) { NTSTATUS Status; ULONG ElementSize, AlignedElementSize, AlignedDataSize; PBCD_ELEMENT_HEADER Header; PVOID Data; BOOLEAN Exists; ULONG i, j, Count; /* Local variable to keep track of objects */ Count = 0; /* Safely compute the element bytes needed */ Status = RtlULongMult(*ElementCount, sizeof(BCD_ELEMENT), &ElementSize); if (!NT_SUCCESS(Status)) { return Status; } /* Safely align the element size */ Status = RtlULongAdd(ElementSize, sizeof(ULONG) - 1, &AlignedElementSize); if (!NT_SUCCESS(Status)) { return Status; } AlignedElementSize = ALIGN_DOWN(AlignedElementSize, ULONG); /* Do a safe version of Add2Ptr to figure out where the headers will start */ Status = RtlULongPtrAdd((ULONG_PTR)Buffer, AlignedElementSize, (PULONG_PTR)&Header); if (!NT_SUCCESS(Status)) { return Status; } /* Safely compute the header bytes needed */ Status = RtlULongMult(*ElementCount, sizeof(BCD_ELEMENT_HEADER), &ElementSize); if (!NT_SUCCESS(Status)) { return Status; } /* Safely align the header size */ Status = RtlULongAdd(ElementSize, AlignedElementSize + sizeof(ULONG) - 1, &AlignedElementSize); if (!NT_SUCCESS(Status)) { return Status; } AlignedElementSize = ALIGN_DOWN(AlignedElementSize, ULONG); /* Do a safe version of Add2Ptr */ Status = RtlULongPtrAdd((ULONG_PTR)Buffer, AlignedElementSize, (PULONG_PTR)&Data); if (!NT_SUCCESS(Status)) { return Status; } /* Iterate over every element */ for (i = 0; i < *ElementCount; i++) { /* Safely align the element size */ Status = RtlULongAdd(Elements->Size, sizeof(ULONG) - 1, &AlignedDataSize); if (!NT_SUCCESS(Status)) { break; } AlignedDataSize = ALIGN_DOWN(AlignedDataSize, ULONG); /* Safely add the size of this data element */ Status = RtlULongAdd(AlignedElementSize, AlignedDataSize, &AlignedElementSize); if (!NT_SUCCESS(Status)) { break; } /* Do we have enough space left? */ if (*BufferSize >= AlignedElementSize) { /* Check if our root is an inherited object */ Exists = FALSE; if (Elements->RootType.PackedValue == BcdLibraryObjectList_InheritedObjects) { /* Yes, scan for us in the current buffer */ for (j = 0; j < Count; j++) { /* Do we already exist? */ while (Buffer[j].Header->Type == Elements->RootType.PackedValue) { /* Yep */ Exists = TRUE; break; } } } /* Have we already found ourselves? */ if (!Exists) { /* Nope, one more entry */ ++Count; /* Write out the unpacked object */ Buffer->Body = Data; Buffer->Header = Header; /* Fill out its header */ Header->Size = Elements->Size; Header->Type = Elements->Type; Header->Version = Elements->Version; /* And copy the data */ RtlCopyMemory(Data, Elements->Data, Header->Size); /* Move to the next unpacked object and header */ ++Buffer; ++Header; /* Move to the next data entry */ Data = (PVOID)((ULONG_PTR)Data + AlignedDataSize); } } else { /* Nope, set failure code, but keep going so we can return count */ Status = STATUS_BUFFER_TOO_SMALL; } /* Move to the next element entry */ Elements = Elements->NextEntry; } /* Return the new final buffer size and count */ *BufferSize = AlignedElementSize; *ElementCount = Count; return Status; }
PDRIVE_LAYOUT_INFORMATION_EX DiskConvertLayoutToExtended( IN CONST PDRIVE_LAYOUT_INFORMATION Layout ) /*++ Routine Description: Convert a DRIVE_LAYOUT_INFORMATION structure into a DRIVE_LAYOUT_INFORMATION_EX structure. Arguments: Layout - The source DRIVE_LAYOUT_INFORMATION structure. Return Values: The resultant DRIVE_LAYOUT_INFORMATION_EX structure. This buffer must be freed by the callee using ExFreePool. --*/ { ULONG i; ULONG size; PDRIVE_LAYOUT_INFORMATION_EX layoutEx; NTSTATUS status; PAGED_CODE (); ASSERT ( Layout != NULL ); // // Allocate enough space for a DRIVE_LAYOUT_INFORMATION_EX structure // plus as many PARTITION_INFORMATION_EX structures as are in the // source array. // // // Use safe interger function // status = RtlULongMult(Layout->PartitionCount, sizeof(PARTITION_INFORMATION_EX), &size); if (!NT_SUCCESS(status)) { return NULL; } status = RtlULongAdd(size, FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]), &size); if (!NT_SUCCESS(status)) { return NULL; } layoutEx = ExAllocatePoolWithTag( NonPagedPool, size, DISK_TAG_PART_LIST ); if ( layoutEx == NULL ) { return NULL; } // // Convert the disk information. // layoutEx->PartitionStyle = PARTITION_STYLE_MBR; layoutEx->PartitionCount = Layout->PartitionCount; layoutEx->Mbr.Signature = Layout->Signature; for (i = 0; i < Layout->PartitionCount; i++) { // // Convert each entry. // DiskConvertPartitionToExtended ( &Layout->PartitionEntry[i], &layoutEx->PartitionEntry[i] ); } return layoutEx; }
PSURFACE NTAPI SURFACE_AllocSurface( _In_ USHORT iType, _In_ ULONG cx, _In_ ULONG cy, _In_ ULONG iFormat, _In_ ULONG fjBitmap, _In_opt_ ULONG cjWidth, _In_opt_ ULONG cjBufSize, _In_opt_ PVOID pvBits) { ULONG cBitsPixel, cjBits, cjObject; PSURFACE psurf; SURFOBJ *pso; PVOID pvSection; NT_ASSERT(!pvBits || (iType == STYPE_BITMAP)); NT_ASSERT((iFormat <= BMF_32BPP) || (cjBufSize != 0)); NT_ASSERT((LONG)cy > 0); /* Verify format */ if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG)) { DPRINT1("Invalid bitmap format: %lu\n", iFormat); return NULL; } /* Get bits per pixel from the format */ cBitsPixel = gajBitsPerFormat[iFormat]; /* Are bits and a width in bytes given? */ if (pvBits && cjWidth) { /* Align the width (Windows compatibility, drivers expect that) */ cjWidth = WIDTH_BYTES_ALIGN32((cjWidth << 3) / cBitsPixel, cBitsPixel); } else { /* Calculate width from the bitmap width in pixels */ cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel); } /* Is this an uncompressed format? */ if (iFormat <= BMF_32BPP) { /* Calculate the correct bitmap size in bytes */ if (!NT_SUCCESS(RtlULongMult(cjWidth, cy, &cjBits))) { DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n", cjWidth, cy); return NULL; } /* Did we get a buffer and size? */ if ((pvBits != NULL) && (cjBufSize != 0)) { /* Make sure the buffer is large enough */ if (cjBufSize < cjBits) { DPRINT1("Buffer is too small, required: %lu, got %lu\n", cjBits, cjBufSize); return NULL; } } } else { /* Compressed format, use the provided size */ NT_ASSERT(cjBufSize != 0); cjBits = cjBufSize; } /* Check if we need an extra large object */ if ((iType == STYPE_BITMAP) && (pvBits == NULL) && !(fjBitmap & BMF_USERMEM) && !(fjBitmap & BMF_KMSECTION)) { /* Allocate an object large enough to hold the bits */ cjObject = sizeof(SURFACE) + cjBits; } else { /* Otherwise just allocate the SURFACE structure */ cjObject = sizeof(SURFACE); } /* Check for arithmetic overflow */ if (cjObject < sizeof(SURFACE)) { /* Fail! */ DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits); return NULL; } /* Allocate a SURFACE object */ psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP, cjObject); if (!psurf) { return NULL; } /* Initialize the basic fields */ pso = &psurf->SurfObj; pso->hsurf = psurf->BaseObject.hHmgr; pso->sizlBitmap.cx = cx; pso->sizlBitmap.cy = cy; pso->iBitmapFormat = iFormat; pso->iType = iType; pso->fjBitmap = (USHORT)fjBitmap; pso->iUniq = InterlockedIncrement(&giUniqueSurface); pso->cjBits = cjBits; /* Check if we need a bitmap buffer */ if (iType == STYPE_BITMAP) { /* Check if we got one or if we need to allocate one */ if (pvBits != NULL) { /* Use the caller provided buffer */ pso->pvBits = pvBits; } else if (fjBitmap & BMF_USERMEM) { /* User mode memory was requested */ pso->pvBits = EngAllocUserMem(cjBits, 0); /* Check for failure */ if (!pso->pvBits) { GDIOBJ_vDeleteObject(&psurf->BaseObject); return NULL; } } else if (fjBitmap & BMF_KMSECTION) { /* Use a kernel mode section */ pso->pvBits = EngAllocSectionMem(&pvSection, (fjBitmap & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY, cjBits, TAG_DIB); /* Check for failure */ if (!pso->pvBits) { GDIOBJ_vDeleteObject(&psurf->BaseObject); return NULL; } /* Free the section already, but keep the mapping */ EngFreeSectionMem(pvSection, NULL); } else { /* Buffer is after the object */ pso->pvBits = psurf + 1; /* Zero the buffer, except requested otherwise */ if (!(fjBitmap & BMF_NOZEROINIT)) { RtlZeroMemory(pso->pvBits, cjBits); } } /* Set pvScan0 and lDelta */ if (fjBitmap & BMF_TOPDOWN) { /* Topdown is the normal way */ pso->pvScan0 = pso->pvBits; pso->lDelta = cjWidth; } else { /* Inversed bitmap (bottom up) */ pso->pvScan0 = ((PCHAR)pso->pvBits + pso->cjBits - cjWidth); pso->lDelta = -(LONG)cjWidth; } } else { /* There are no bitmap bits */ pso->pvScan0 = pso->pvBits = NULL; pso->lDelta = 0; } /* Assign a default palette and increment its reference count */ SURFACE_vSetPalette(psurf, appalSurfaceDefault[iFormat]); return psurf; }