DiskArbitration and APFS container - xcode

DADiskCopyDescription() give basic information for disk and partition but not how these info elements are linked together.
By example how to get the volume parent container ?
How to decode de CFSTR given by DADiskCopyDescription() ?
When does DAMediaContent hold "GUID_partition_scheme" or "FDisk_partition_scheme" ?
For volume DAMediaContent is something like "C12A7328-F81F-11D2-BA4B-00A0C93EC93B" (with volume name in DAMediaName).
But DAMediaContent with such numeric value is not always volume (DAMediaName and DAVolumeKind are then empty).
And sometime DAMediaContent is empty.
Where can I found information about the way DADiskCopyDescription() information are linked together ?

Related

How to determine what bloks are allocated for the disk device?

A lot of modern storage types use Thin provisioning to allocate blocks. I need to get Block allocation map for the disk device. There is FSCTL_GET_VOLUME_BITMAP to get volume bitmap, but it is file-system specific and I need an approach that is not FS specific.
Starting in Windows 8 Windows is sending "TRIM and Unmap" hints to storage media to track allocated blocks.
UNMAP is the SCSI command by which an application or the system can
communicate to the storage stack and the disk that a certain sector or
range of sectors are currently not in use, including sectors that were
previously in use by files that were later deleted.
So this should be possible. Unfortunately, I was unable to find Disk Management Control Code or Disk Management Function to get it. Maybe someone know know the way to get it?
Like gubblebozer made a hint - GET LBA STATUS command introduced in SBC-3 is the way to retrieve the low-level mappings from the device itself. From Thin Provisioning
The application can call the IOCTL DSM allocation routine to send the SCSI
command and retrieve the mapped or unmapped state of each slab in a particular
range. If the LBA provisioning status returned does not describe the entire
allocation range, the application sends another SCSI command to retrieve the
provisioning status of the remaining LBA range.
Looks like this can be done with the help of IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES
then DEVICE_DATA_SET_LB_PROVISIONING_STATE structure will contain a bitmap of
slab allocations.

Get Volume GUID from Partition number in windows

I am looking for some kind help regarding below query.
I am trying to write (using WriteFile()) to a windows disk partition within a Windows PE environment by opening a disk handle and seeking to the partition starting offset.
WriteFile() is returning error code 5 (ACCESS DENIED).
I believe it is because the application has not locked the volume before writing to the volume.
My application has only the partition number as input. The ioctl FSCTL_LOCK_VOLUME needs a volume handle which is returned by CreateFile() and this needs a volume GUID as parameter.
So how do I get the volume GUID via the partition number?
Regards.

ext4 pointers from in-memory inode

I'm trying to retrieve in a kernel module the direct/indirect etc addresses in an ext4 file system inode. I understand that I need to look into ext_inode_info struct (I do this via container_of using the relevant vfs_inode).
But to which field am I supposed to look into?
Where can I find for example the first direct pointer? I thought it was stored in i_data array (it is in ext3_inode_info).
But for an ext4 inode when I examine the first entry in i_data, I get a sector address that is not remotely similar to the real sector holding the address of the first data block.
Any help will be appreciated.
==EDIT==
ok, so I seemed to have understood the basic problem. I have an extent-based ext4 file system. Wasn't aware of this change, and that this is enabled by default. So is there a simple way to extract the physical addresses of blocks by offset? I'm trying again as verification to look at the first physical block (logical 0), by looking at the first extent, but I get some gibberish numbers (though consistent and unique for every inode/file, so some progress was made).

determine if drive is removable (flash or HDD) knowing only the drive letter

I am trying to determine if a file is on a local drive. I found GetDriveType() WINAPI which retrieves the drive type. However reading the description of the return values it seems, and thats how I understand it, that it retrieves a flash drive as FIXED which is not what I want.
Its working fine on local drives:
bool IsDriveRemovableOrRemote(CString driveRoot)
{
UINT driveType = GetDriveType(driveRoot);
return (DRIVE_REMOVABLE == driveType || DRIVE_CDROM == driveType || DRIVE_NO_ROOT_DIR == driveType || DRIVE_REMOTE == driveType);
}
I don't have a flash/external drive to test ATM but I would like if someone can tell me if my interpretation is correct? and if so, what better alternative should I use?
Please bear in mind that I only have the path of the file.
You should read the doco more closely. While a Flash drive is considered a fixed device, there's a note in that linked page:
To determine whether a drive is a USB-type drive, call SetupDiGetDeviceRegistryProperty and specify the SPDRP_REMOVAL_POLICY property.
The process seems a little messy if all you start with is the path but you can start reading the doco here. It looks like you may need to enumerate the devices until you find one matching your drive.
To avoid doing this to all your requests, I would do a two-stage check. If your current method says it's not fixed, treat it as non-local.
If it says it is fixed, then you can enumerate the devices using my suggested method to be certain.
Alternatively, you can enumerate all fixed non-USB drives the first time you need to, and then just cache the information. I'm pretty certain that the list of these drives won't change while the system is running - drives that get added and deleted are, by definition, removable.
You can try using DeviceIoControl and query for the BusType = BusTypeUsb by passing IOCTL_STORAGE_QUERY_PROPERTY as its second parameter. Read Determining USB by Thomas Lee at the bottom of page.

The Uniqueness of IOCTL_MOUNTDEV_QUERY_UNIQUE_ID

The documentation on IOCTL_MOUNTDEV_QUERY_UNIQUE_ID is a bit confusing... exactly what kind of ID should be returned in the MOUNTDEV_UNIQUE_ID structure?
The documentation for
typedef struct _MOUNTDEV_UNIQUE_ID {
USHORT UniqueIdLength;
UCHAR UniqueId[1];
} MOUNTDEV_UNIQUE_ID, *PMOUNTDEV_UNIQUE_ID;
says:
UniqueIdLength
Contains the length of unique volume ID.
UniqueId
Contains the unique volume ID. The format for unique volume names is "\??\Volume{GUID}\", where GUID is a globally unique identifier that identifies the volume.
However, there's something weird here: What should be the exact format of UniqueId? If it's meant to be in the \??\Volume{GUID}\ format, then what's the point of the UniqueIdLength field -- aren't they all the same size? Otherwise, what format does the device ID need to be in?
Furthermore, is this a device ID or a volume ID? In other words, is this supposed to be unique per medium (e.g. CD) or per device (CD drive)?
This kind of struct is pretty common in MS APIs - the UniqueID[1] variable is just a placeholder, in reality it's used as a UniqueId[UniqueIdLength] variable.
The ID is unique both per medium and per device - it depends on whether you're talking to a volume driver or a device class driver. The ID is intended to identify "something that can be mounted" - so e.g. a CD-ROM device, a fixed disk partition or an unpartitioned removable disk. The mount manager uses the ID a.o. to lookup where this particular volume was mounted before, and remount it at the same point.
From MSDN
Maybe there is misunderstanding about this structure.
I called DeviceIoControl(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) and got a string as the similar format to Device Interface Path, but it is just different of the prefix 4 characters, and then it saved in registry \HKLM\SYSTEM\MountedDevices.
MOUNTDEV_UNIQUE_ID is acquired upon a volume arrival notification where mountmgr!MountMgrMountedDeviceArrival invokes mountmgr!QueryDeviceInformation, which sends a IOCTL_MOUNTDEV_QUERY_UNIQUE_ID IRP to the volume PDO stack, which volmgr picks up, and I'm not sure what routine it is but in XP's ftdisk it was ftdisk!FtpQueryUniqueIdBuffer that determined whether to set the UniqueID member to a GPT partition GUID, a MBR signature + offset, or the symbolic link like STORAGE#RemovableMedia.... The symbolic link is based on the name of devnode that the volume PDO is part of, and the symbolic link was generated by IoRegisterDeviceInterface, which was then stored in the volume extension before alerting mountmgr of the volume arrival in the first place (alerting is done by IoSetDeviceInterfaceState Enable). On Windows 7 the volume PDO devnode name is STORAGE\Volume\_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_B lade&Rev_1.27#4C530399920812105355&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}, the symbolic link is STORAGE#Volume#_??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.27#4C530399920812105355&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b} but the MountedDevices data is _??_USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Blade&Rev_1.27#4C530399920812105355&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}. The symbolic link that is created is always to the volume PDO name, because the volume PDO is supplied to the call, which is \Device\HarddiskVolumeX.
FtpQueryUniqueIdBuffer uses the MBR signature and partition offset if it's an MBR disk, and uses the GPT partition GUID if it's a GPT disk, and uses the symbolic link if it's neither, which tends to be a regular USB drive mass storage volume that doesn't have a boot sector, and ftdisk considers a disk without a boot sector to be a 'superfloppy', so it looks for that flag on the volume extension. So that's how unique it is, MBR signature and GPT GUID uniqueness speak for themselves, but the symlink doesn't so I'll elaborate: it contains the DIID of the USBSTOR device, which includes the USB serial number, or if it doesn't have one, a system wide unique number determine according to the following scheme.
Mountmgr creates further symbolic links between the drive letter and volume device name, and the volume GUID and the volume device name, and then puts them in the MountedDevices database but uses the unique ID instead of the volume device name. The volume GUID \??\Volume{GUID}\ it generates using ExUuidCreate. IOCTL_MOUNTMGR_QUERY_POINTS shows each symbolic link for a mounted device, so it will show \DosDevices\C: -> \Device\HarddiskVolumeX and \??\Volume{GUID}\ -> \Device\HarddiskVolumeX and the unique ID of the mounted device and the name of the mounted device. It does not however show the symbolic link to \Device\HarddiskVolumeX created by IoRegisterDeviceInterface because the symbolic link wasn't created by mount manager, so it doesn't know about it.

Resources