How can I get volume name for EFI system partition? - c++

I have a Windows machine with GPT drives.
I have a DOS device name of EFI system partition as output from bcdedit.
I want to open handle for this partition and get DOS name by QueryDosDevice() to compare with DOS name which I already have.
I tried to use FindFirstVolume/FindNextVolume to find volume name to get DOS name from QueryDosDevice, but I didn't find volume for EFI system partition. WMI also doesn't have volume for this partition.
How can I get volume name of EFI system partition from C++ code to use it in QueryDosDevice?

Try this. Download and install WinObj (from MS technet). Look through the \Device directory for the logical device name of the EFI system partition. Note that logical device names in the \Device directory are of the form \Device\Harddisk<N>\Partition<M> where N is the harddisk number and M is the partition number. Note M equal to zero means whole harddisk, and M > 0 refers to individual partitions. THe number N is the same number you will see in disk manager (diskmgmt.msc) and in diskpart.
Once you get the logical device name look in the \GLOBAL?? directory for an alias to that name. If you find an alias, then you're good to go. If you don't find an alias, then you'll need to use a Win32 API that can access \Device names. I think there is at least one such API, because I wrote a program many years ago that took \Device names as an argument.

Related

Querying table with >1000 columns fails

I can create and ingest data into a table with 1100 columns, but when I try to run any kind of query on it, like get all vals:
select * from iot_agg;
It looks like I cannot read it with the following error
io.questdb.cairo.CairoException: [24] Cannot open file: /root/.questdb/db/table/iot_agg.d
at io.questdb.std.ThreadLocal.initialValue(ThreadLocal.java:36)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
at java.lang.ThreadLocal.get(ThreadLocal.java:170)
at io.questdb.cairo.CairoException.instance(CairoException.java:38)
at io.questdb.cairo.ReadOnlyMemory.of(ReadOnlyMemory.java:135)
at io.questdb.cairo.ReadOnlyMemory.<init>(ReadOnlyMemory.java:44)
at io.questdb.cairo.TableReader.reloadColumnAt(TableReader.java:1031)
at io.questdb.cairo.TableReader.openPartitionColumns(TableReader.java:862)
at io.questdb.cairo.TableReader.openPartition0(TableReader.java:841)
at io.questdb.cairo.TableReader.openPartition(TableReader.java:806)
...
Ouroborus might be right in suggesting that the schema could be revisited, but regarding the actual error from Cairo:
24: OS error, too many open files
This is dependent on the OS that the instance is running on, and is tied to system-wide or user settings, which can be increased if necessary.
It is relatively common to hit limits like this for multiple different DB engines which handle large amounts of files. This is commonly configured with kernel variables to set the maximum number of open files. Checking the max limit for open files can be done on Linux and MacOS with
ulimit -n
You can also use ulimit to set this to a value you need. If you need to set it to 10,000, for example, you can do this with:
ulimit -n 10000
edit: There is official documentation for capacity planning when deploying QuestDB which takes several factors such as CPU, memory, network capacity, and a combination of these elements into consideration. For more information, see the capacity planning guide

WMI query to select disk containing system volume

I need to get some information (model and serial) of the disk that contains the system volume (usually C:). I'm using this query:
SELECT * FROM Win32_DiskDrive WHERE Index=0
My question is, is the disk with Index=0 always the disk containing the system volume?
Edit: I added an additional query to get the index of the disk containing the boot partition:
SELECT * FROM Win32_DiskPartition WHERE BootPartition=True
Then the original query changes to
SELECT * FROM Win32_DiskDrive WHERE Index={diskIndex}
I figured I'd be pretty safe this way. Suggestions for better solutions are always welcome :)
As stated, add an extra query to get the index of the disk containing the boot partition:
{diskIndex} = SELECT * FROM Win32_DiskPartition WHERE BootPartition=True
SELECT * FROM Win32_DiskDrive WHERE Index={diskIndex}
Unfortunatly WMI doesn't seem to support JOINs, which would have made the query a little more efficient.
My question is, is the disk with Index=0 always the disk containing the system volume?
In my case the answer is No. My system disk has index 1.
Also your assumption that the system disk is always bootable is incorrect.
$ wmic os get "SystemDrive"
SystemDrive
C:
$ wmic logicaldisk where 'DeviceID="C:"' assoc /resultclass:Win32_DiskPartition
...\\DZEN\ROOT\CIMV2:Win32_DiskPartition.DeviceID="Disk #1, Partition #0"...
wmic diskdrive where 'Index=1' get "Caption"
Caption
OCZ-VERTEX4 // Yes, this is my system disk.
Also your assumpion about BootPartition usage is incorrect for cases when bootmanager is on another disk, like in my case:
wmic partition where 'DeviceID like "Disk_#1%"' get DeviceID,BootPartition
BootPartition DeviceID
FALSE Disk #1, Partition #0
wmic partition where 'BootPartition="TRUE"' get DeviceID,BootPartition
BootPartition DeviceID
TRUE Disk #4, Partition #0
TRUE Disk #3, Partition #0
As you can see, nor the system disk neither one of bootable ones do not have Index=0 for my case. Actually I have Index=0 for the one of non system and non bootable disk.

How to associate volume drive letter with corresponding disk partitions?

My goal is to associate a pair of "drive and partition number" with a logical drive letter for that volume. For instance, in this configuration:
for a spanned volume F: I would assume to get:
Volume F:
PhysicalDrive1-Partition1
PhysicalDrive2-Partition1
So to obtain physical drive numbers that the volume spans I use IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS control code for the DeviceIoControl API as described here (they don't allocate memory correctly for DeviceIoControl API call, but that's outside of the scope of this question.)
So in my example for volume F: I get two DISK_EXTENT structures that I can use to get physical drive numbers from, using DiskNumber member.
My question is how do I get corresponding partition numbers?
PS. The reason I need those partition numbers is so that I can associate volume drive letters with disk partitions in a later call to IOCTL_DISK_GET_DRIVE_LAYOUT_EX using the drive handle that was opened as "\\?\PhysicalDriveX" where X stands for drive number.

Get the partition type of a specific partition in C++, on a GPT disk

I'm working on a project which requires me to operate at a low level on Windows drives, and am doing so primarily using Windows API calls. But before I can operate on the drive, I need to know the types of partitions present on it.
This is fairly simple on a disk formatted by MBR, because
DeviceIoControl(...,IOCTL_DISK_GET_DRIVE_LAYOUT_EX,...);
returns a structure in format DRIVE_LAYOUT_INFORMATION_EX, which contains an array of PARTITION_INFORMATION_EX. On an MBR disk, the PARTITION_INFORMATION_EX.Mbr.PartitionType element contains a unique identifier for the partition type, e.g. for NTFS it is 0x07, for Extended it is 0x05.
However, this isn't so simple on a GPT disk. I know that I can read the identifier off of the beginning of the partition, but I'd prefer to handle this with API calls, such as DeviceIoControl. When I run DeviceIoControl on a GPT disk, the PARTITION_INFORMATION_EX.Mbr.PartitionType contains completely different values than those which would be normally there.
Note that the GUID is useless to me because that only tells me the purpose of the partition, not what type of partition it is. I'm trying to figure out if the drive is NTFS, FAT, etc.
For GPT partition in your code when you call DeviceIoControl(), this call will return the Partition information in the object of PARTITION_INFORMATION_EX. If you see the PARTITION_INFORMATION_EX structure, there are two separate structure for MBR and GPT disk. So when you get the information in PARTITION_INFORMATION_EX object, you'll have to first confirm that whether the disk type is GPT or MBR, if GPT you can get the specific partition type by comparing it's GUID.
Look at Microsoft's PARTITION_INFORMATION_GPT struct for GPT partitions.
Instead of going through PARTITION_INFORMATION_EX, I found the best way to find the filesystem of a volume is to call GetVolumeInformation. On Vista+, this seems to be just a wrapper for GetVolumeInformationByHandleW. The later might be the best for you if you already have a volume handle.
Both work well with either MBR or GPT disks. The result is the filesystem name string instead of a type ID, but should be easy to adapt.

Keeping the physical address of the data which is in hard drive

Is it possible to keep a datas address which is placed in hard disk or solid state disk in a container in RAM?
For my application (C++/visual studio 2008) I'm going to create a repository(directory) on a SSD drive and in that repository there will be thousands (lets say 100000 files with size like 3 MB for each) of binary files (the names of the files are Unique Id's)
Some applications have to perform search operation on tihs directory with the names (Id's).
So I thought that, if I create a container like a map in RAM and set the key column ID (name of the file) and the value to the physical address of the file (which is in the SSD) and let the applications perform the search in this map (in RAM) and if the data found, retreive the data with the address(since we have the physical address) wouldn't be much more faster?
So is it possible to do something like that?
There are a few easy options: use a database, or memory map the bunch of files. In the latter case, you'll have to be aware that apparent memory operations are in fact disk I/O's, and much slower. But the result of memory mapping a file is still a fairly ordinary pointer to its contents. This is even easier than the "physical addresses" you're proposing.