DefineDosDevice GetVolumeNameForVolumeMountPoint - winapi

MSDN has a nice example of changing drive letters at:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364014(v=vs.85).aspx
Only problem is that it doesn't work on my Windows 7 system.
Am invoking the EXE from a DOS window with admin privileges.
I start with a thumb drive on E:
I can use the MSDN example to remove E:
But when I then use the MSDN example to assign F: to the same thumb drive, the initial DefineDosDevice for F: succeeds, but the subsequent GetVolumeNameForVolumeMountPoint fails thus SetVolumeMountPoint fails.
I understand that the function of the initial DefineDosDevice is to create the drive letter so there's something for GetVolumeNameForVolumeMountPoint to connect to and thus return the volume name, but GetVolumeNameForVolumeMountPoint is behaving as if the intial DefineDosDevice has failed.
Whassup?

The problem was the second argument to ChangeLetter.exe when defining a new drive. You must include the partition number. Assume USB drive is set for E: and you want to move it to F:. You must do the following:
ChangeLetter -r E:
ChangeLetter F: \device\harddisk1\partition1
Harddisk counts from zero. Partition counts from one.

Related

Assign the same Drive Letter Every Time to USB Drive with USBDLM

I try to use USBDLM to connect separately a USB sticks and a USB drive to appear always as drive T.
On every USB stich/drive I put a USBDLM.ini with:
[DriveLetters]
Letters=%drive%\usbdlm.ini
and for every drive its own configuration as:
[DriveLetters10]
; Aldistick
DeviceID1=USB 2.0 Flash Disk USB Device
Letter1=T
; many other options are documented in the Help files
[DriveLetters20]
VolumeSerial=16ED-33C5
Letter=T
But I find out that this is not working unless I put the same usbdlm.ini file for every stick/drive into the folder where USBDLM.exe is placed.
Do I something wrong?
Thanks.
On the drive you need an USBDLM.INI which contains a simple [DriveLetters] section with the desired letters:
[DriveLetters]
Letters=T
In the main USBDLM.INI you let is read the letter from the INI on the drive:
[DriveLetters]
Letters=%drive%\usbdlm.ini
Maybe it is more handy to let USBDLM extract the desired drive letter from the volume label, e.g. label it "Drive T" and write in the main USBDLM.INI:
[DriveLetters]
Letters=%LetterFromLabel%
http://www.uwe-sieber.de/usbdlm_help_e.html#by_label
Uwe Sieber

NodeJS: Unable to write to Windows 8 block device

I'm looking forward to write directly to a raw windows block device.
I can successfully do so with dd for windows:
> dd.exe if=myData.dat of=\\.\PhysicalDrive1
However I'm unable to do so using NodeJS. I'm using node-blockdevice in the following manner:
var device = new BlockDevice({
path: '\\\\.\\PhysicalDrive1',
mode: 'w+',
size: 512
});
device.write(0, myBuffer, callback);
device.write correctly returns the amount of bytes written, however it's not actually writing anything to the device.
Notice that the exact code works successfully in Mac OS X (substituting \\\\.\\PhysicalDrive1 with /dev/diskN of course): it writes my data and I can view it without any problem in Windows 8.
What am I doing wrong?
I also tried:
Not escaping the backslashes (\\.\PhysicalDrive1) but that results in a EINV error.
Using the logical name: \\\\.\\E:.
Unmounting the volume with mountvol X: /D before attempting to read/write.
I can correctly confirm the id of the device I want to write to with:
wmic diskdrive list brief
I've also tried setting the mode to rs+. The read operation seemed to work, however the saved data contained the following failure-related data:
�X�MSDOS5.0�
�?����:�)?�xNO NAME FAT32 3ɎѼ�{��ٽ|�V#�N�V#�A��U�r��U�u
��t�F�-�V#�s�����f��#f������Af��f��f�F�~u9�~*w3f�Ff��
����,���}��|���t<�t ������}��}��ߘ��f`�~� fjfPSfh�B�V#���fXfXfXfX�3f;F�r��*f3�f�Nf����f��f���v�֊V#����
̸�fa�t���f#Iu��BOOTMGR
Disk error�
Press any key to restart
��U�%
EDIT: A github issue thread describing more things I've tried: https://github.com/jhermsmeier/node-blockdevice/issues/1.
EDIT: All approaches mentioned were tested with admin privileges.
EDIT: I'm using device.close(callback), but omitted in the example for simplicity.

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.

How to WriteFile to a PhysicalDrive (Windows 7) without getting ERROR_ACCESS_DENIED?

I'm trying to write a test pattern to every sector of a formatted USB drive. There is one logical drive (e.g. h:). This volume is FAT-formatted and contains data to be overwritten. Also, I want to overwrite the whole physical drive. The program is running with elevated user rights.
First I did the following:
// from the drive letter "h:" I get the physical disk number using
// IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS => "\\.\PhysicalDrive2"
hDevice = ::CreateFile( "\\.\PhysicalDrive2", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
// get the number of available sectors with IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
// => ulNumberOfSectors
// now I try to write some sectors, e.g. 2 (I want to use a higher value):
WriteFile( hDevice, abBuffer, 2*512, &byteswritten, NULL );
The call to WriteFile fails with ERROR_ACCESS_DENIED.
If I write one sector, it works.
When I overwrite the first sector and plug the device out and in again, Windows wants to format it. In this situation my code with 2048 sectors at once works without ERROR_ACCESS_DENIED.
I also unmounted the volume as described in CodeProject: WriteFile on Physical Drives with Windows 7 but this didn't change anything. Obviously the volume is unmounted because it's no longer visible in Windows Explorer.
I want to write more than a single sector due to perfomance reasons. I'm also afraid that other problems in the field might occur because I don't fully understand ths problem.
Any suggestions?
I didn't have problems with different WriteFile() sizes, but I did solve the
WriteFile(): Access is denied <ERROR_ACCESS_DENIED/5> to
'\.\physicaldriveX
devices (usually USB HDD/SSD) in Windows 7 running as Administrator (elevated rights) as follows:
Computer Management -> Disk Management:
Volume (H: in your case) -> right-click -> Delete Volume
Disk (Disk 2 in your case) -> right-click -> Off-line
Disk (Disk 2 in your case) -> right-click -> On-line
After that, I'm able to write to '\.\physicaldriveX' with no problem.
I think the Win7 locks (unlike previous Windows releases) the physical device as long as there is any file system on the device to avoid consistency problems.
You cannot directly access sectors of a drive which are owned by a mounted filesystem.
See Changes to the file system and to the storage stack to restrict direct disk access and direct volume access
The documentation for FSCTL_DISMOUNT_VOLUME describes the following sequence for overwriting a filesystem:
Open a volume.
Lock the volume.
Format the volume.
Dismount the volume.
Unlock the volume.
Close the volume handle.
Your pattern-writing operation would be in step 3 instead of formatting.
Another method is to use clean to delete all the partitions (and ALL DATA) on the disk:
C:\> diskpart
Diskpart> list disk
Diskpart> select disk N (where N is your disk number)
Diskpart> clean
Diskpart> exit

Maximum number of drives in windows?

I'm trying to figure out the available disk space programmatically in windows. For this, I need to first get a list of the available drives, then check which of those are local drives and then query the available bytes on each local drive.
I'm a bit stuck on the first part, where the API presents two functions:
GetLogicalDrives (http://msdn.microsoft.com/en-us/library/aa364972(VS.85).aspx) which gives you a DWORD with the bits set (bit 0 if drive A is present, bit 1 if drive B etc)
GetLogicalDriveStrings (http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx) which gives you the actual strings.
Now, although I'll be using strings later on, I'd prefer using the first option for querying. However, on my system a DWORD is typedef-ed to "unsigned long", which is 4 bytes, whereas drive letters only range A-Z (26 - i think - characters). Obviously, one can define more than 26 drives on their system (however unlikely they are to do so) - so I was wondering if there was any convention for those drives. Can someone point me to a resource on this?
Thanks.
DWORD is always 4 bytes, regardless of the system (it's a Win32 type).
The maximum for drive letters in Windows is 26. Because English alphabet has only 26 letters :). However, Windows allows two ways to mount a volume:
to a drive letter
to a directory (on an NTFS volume).
You can mount one volume to multiple locations (but no more than one drive letter, IIRC). A GUI for this task is presented by Control Panel -> Administrative Tools -> Computer Management -> Disk Management.
If you want to have more than 26 drives with the additional drives being redirects to already active drives and are okay with them not working properly in most programs, then you can assign more with the following method (be warned they won't even show up in the file explorer):
subst ♪: C:\Temp\
cd /D ♪:\
and to delete them (also they aren't preserved through restarts):
subst /D ♪:
You can enumerate all volumes and their mount points as described in this article.
You could use WMI. The following WMI query should list all drives:
SELECT * FROM Win32_DiskDrive
It it not sufficient to enumerate MS-DOS drives (there can be at most 26 of them, by the way, although each can be bound twice, once globally and once locally in your session), a volume can, for example, be mounted to a directory. What you want is probably to enumerate all volumes in the system, using FindFirstVolume et al. Take a look at the associated MSDN example.

Resources