Skip to content

Commit

Permalink
Auto-merge for PR #249 via VersionBot
Browse files Browse the repository at this point in the history
fix(windows): Fix segfault on Windows 7
  • Loading branch information
resin-io-modules-versionbot[bot] authored Jan 18, 2018
2 parents ce762ba + 8441de2 commit dc35503
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 27 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).

## v6.0.3 - 2018-01-18

* Fix crash on Windows 7 #249 [Jonas Hermsmeier]

## v6.0.2 - 2018-01-14

* Fix(darwin): Use proper flag to enable extended regexes in `sed` Fixes #247 #248 [Andrew Scheller]
Expand Down
15 changes: 14 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@
"src/drivelist.cpp",
"src/device-descriptor.cpp",
],
"msvs_settings": {
"VCLinkerTool": {
"SetChecksum": "true"
},
"VCCLCompilerTool": {
"ExceptionHandling": 1,
"AdditionalOptions": [
"/EHsc"
]
}
},
"conditions": [
[ 'OS=="mac"', {
"sources": [
Expand All @@ -24,7 +35,9 @@
"src/windows/list.cpp"
],
"libraries": [
"-lsetupapi.lib"
"-lKernel32.lib",
"-lShell32.lib",
"-lSetupAPI.lib"
]
}],
[ 'OS=="linux"', {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "drivelist",
"version": "6.0.2",
"version": "6.0.3",
"description": "List all connected drives in your computer, in all major operating systems",
"main": "lib/drivelist.js",
"homepage": "https://github.com/resin-io-modules/drivelist",
Expand Down
99 changes: 74 additions & 25 deletions src/windows/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ int32_t GetDeviceNumber(HANDLE hDevice) {

if (result && diskExtents.NumberOfDiskExtents > 0) {
// printf("[INFO] DiskNumber: %i\n", diskExtents.Extents[0].DiskNumber);

// NOTE: Always ignore RAIDs
// TODO(jhermsmeier): Handle RAIDs properly
if (diskExtents.NumberOfDiskExtents >= 2) {
Expand All @@ -226,11 +227,11 @@ int32_t GetDeviceNumber(HANDLE hDevice) {
if (result) {
// printf("[INFO] DeviceNumber: %i\n", deviceNumber.DeviceNumber);
diskNumber = deviceNumber.DeviceNumber;
} else {
errorCode = GetLastError();
// printf("[INFO] STORAGE_GET_DEVICE_NUMBER: Error 0x%08lX\n", errorCode);
}

// errorCode = GetLastError();
// printf("[INFO] STORAGE_GET_DEVICE_NUMBER: Error 0x%08lX\n", errorCode);

return diskNumber;
}

Expand All @@ -245,6 +246,7 @@ void GetMountpoints(int32_t deviceNumber,
for (std::string volumeName : logicalVolumes) {
if (hLogical != INVALID_HANDLE_VALUE) {
CloseHandle(hLogical);
hLogical = INVALID_HANDLE_VALUE;
}

// NOTE: Ignore everything that's not a fixed or removable drive,
Expand All @@ -253,7 +255,11 @@ void GetMountpoints(int32_t deviceNumber,
// attributed to blockdevices
driveType = GetDriveTypeA((volumeName + ":\\").c_str());

// printf("[INFO] Checking %s:/\n", volumeName.c_str());

if ((driveType != DRIVE_FIXED) && (driveType != DRIVE_REMOVABLE)) {
// printf("[INFO] Ignoring volume %s:/ - Not FIXED | REMOVABLE\n",
// volumeName.c_str());
continue;
}

Expand All @@ -277,12 +283,15 @@ void GetMountpoints(int32_t deviceNumber,
}

if (logicalVolumeDeviceNumber == deviceNumber) {
// printf("[INFO] Device number for logical volume %s is %i\n",
// volumeName.c_str(), logicalVolumeDeviceNumber);
mountpoints->push_back(volumeName + ":\\");
}
}

if (hLogical != INVALID_HANDLE_VALUE) {
CloseHandle(hLogical);
hLogical = INVALID_HANDLE_VALUE;
}
}

Expand Down Expand Up @@ -311,6 +320,7 @@ std::string GetBusType(STORAGE_ADAPTER_DESCRIPTOR *adapterDescriptor) {
bool GetAdapterInfo(HANDLE hPhysical, DeviceDescriptor *device) {
STORAGE_PROPERTY_QUERY query;
STORAGE_ADAPTER_DESCRIPTOR adapterDescriptor;
DWORD size = 0;

ZeroMemory(&query, sizeof(query));

Expand All @@ -320,7 +330,7 @@ bool GetAdapterInfo(HANDLE hPhysical, DeviceDescriptor *device) {
BOOL hasAdapterInfo = DeviceIoControl(
hPhysical, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
&adapterDescriptor, sizeof(STORAGE_ADAPTER_DESCRIPTOR), NULL, NULL);
&adapterDescriptor, sizeof(STORAGE_ADAPTER_DESCRIPTOR), &size, NULL);

if (hasAdapterInfo) {
device->busType = GetBusType(&adapterDescriptor);
Expand All @@ -335,6 +345,7 @@ bool GetAdapterInfo(HANDLE hPhysical, DeviceDescriptor *device) {
bool GetDeviceBlockSize(HANDLE hPhysical, DeviceDescriptor *device) {
STORAGE_PROPERTY_QUERY query;
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDescriptor;
DWORD size = 0;

ZeroMemory(&query, sizeof(query));

Expand All @@ -345,7 +356,7 @@ bool GetDeviceBlockSize(HANDLE hPhysical, DeviceDescriptor *device) {
hPhysical, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
&alignmentDescriptor, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
NULL, NULL);
&size, NULL);

if (hasAlignmentDescriptor) {
device->blockSize = alignmentDescriptor.BytesPerPhysicalSector;
Expand All @@ -359,9 +370,16 @@ bool GetDeviceBlockSize(HANDLE hPhysical, DeviceDescriptor *device) {
bool GetDeviceSize(HANDLE hPhysical, DeviceDescriptor *device) {
DISK_GEOMETRY_EX diskGeometry;

BOOL hasDiskGeometry = DeviceIoControl(
// printf("[INFO] hasDiskGeometry\n");

BOOL hasDiskGeometry = false;
DWORD size = 0;

hasDiskGeometry = DeviceIoControl(
hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0,
&diskGeometry, sizeof(DISK_GEOMETRY_EX), NULL, NULL);
&diskGeometry, sizeof(DISK_GEOMETRY_EX), &size, NULL);

// printf("[INFO] hasDiskGeometry %i\n", hasDiskGeometry);

// NOTE: Another way to get the block size would be
// `IOCTL_STORAGE_QUERY_PROPERTY` with `STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR`,
Expand All @@ -382,28 +400,26 @@ bool GetDetailData(DeviceDescriptor* device,
DWORD errorCode = 0;
bool result = true;

// Passing zero to `CreateFile()` doesn't require permissions to
// open the device handle, but only lets you acquire device metadata,
// which is all we want
DWORD handleOpenFlags = 0;

HANDLE hDevice = INVALID_HANDLE_VALUE;
HANDLE hPhysical = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA_W deviceDetailData;
PSP_DEVICE_INTERFACE_DETAIL_DATA_W deviceDetailData(NULL);

for (index = 0; ; index++) {
if (hDevice != INVALID_HANDLE_VALUE) {
CloseHandle(hDevice);
hDevice = INVALID_HANDLE_VALUE;
}

if (hPhysical != INVALID_HANDLE_VALUE) {
CloseHandle(hPhysical);
hPhysical = INVALID_HANDLE_VALUE;
}

deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

// printf("[INFO] (%i) SetupDiEnumDeviceInterfaces\n", index);
// printf("[INFO] (%i) SetupDiEnumDeviceInterfaces - isDisk\n", index);

BOOL isDisk = SetupDiEnumDeviceInterfaces(
hDeviceInfo, &deviceInfoData, &GUID_DEVICE_INTERFACE_DISK,
index, &deviceInterfaceData);
Expand All @@ -412,7 +428,7 @@ bool GetDetailData(DeviceDescriptor* device,
errorCode = GetLastError();
if (errorCode == ERROR_NO_MORE_ITEMS) {
// printf("[INFO] (%i) EnumDeviceInterfaces: No more items 0x%08lX\n",
// index, errorCode);
// index, errorCode);
result = index != 0;
break;
} else {
Expand All @@ -429,23 +445,29 @@ bool GetDetailData(DeviceDescriptor* device,
if (!hasDeviceInterfaceData) {
errorCode = GetLastError();
if (errorCode == ERROR_INSUFFICIENT_BUFFER) {
deviceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W) calloc(1, size);
deviceDetailData = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>
(malloc(size));
if (deviceDetailData == NULL) {
device->error = "GetDeviceInterfaceDetailW: "
"Unable to allocate SP_DEVICE_INTERFACE_DETAIL_DATA; "
device->error = "SetupDiGetDeviceInterfaceDetailW: "
"Unable to allocate SP_DEVICE_INTERFACE_DETAIL_DATA_W"
"(" + std::to_string(size) + "); "
"Error " + std::to_string(errorCode);
result = false;
break;
}
deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// printf("Allocated SP_DEVICE_INTERFACE_DETAIL_DATA_W\n");
} else {
device->error = "GetDeviceInterfaceDetailW: "
device->error = "SetupDiGetDeviceInterfaceDetailW: "
"Couldn't get detail data; Error " + std::to_string(errorCode);
result = false;
break;
}
}

// printf("[INFO] (%i) Getting SP_DEVICE_INTERFACE_DETAIL_DATA_W\n", index);

deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);

BOOL hasDeviceDetail = SetupDiGetDeviceInterfaceDetailW(
hDeviceInfo, &deviceInterfaceData, deviceDetailData, size, &size, NULL);

Expand All @@ -458,17 +480,21 @@ bool GetDetailData(DeviceDescriptor* device,
}

// printf("[INFO] (%i) SetupDiGetDeviceInterfaceDetailW:\n %s\n",
// index, WCharToUtf8(deviceDetailData->DevicePath));
// index, WCharToUtf8(deviceDetailData->DevicePath));

// Passing zero to `CreateFile()` doesn't require permissions to
// open the device handle, but only lets you acquire device metadata,
// which is all we want
hDevice = CreateFileW(
deviceDetailData->DevicePath, handleOpenFlags,
deviceDetailData->DevicePath, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (hDevice == INVALID_HANDLE_VALUE) {
errorCode = GetLastError();
// printf("[ERROR] Couldn't open handle to device: Error %i", errorCode);
device->error = "Couldn't open handle to device: Error " +
std::to_string(errorCode);
std::to_string(errorCode);
result = false;
break;
}
Expand All @@ -486,55 +512,76 @@ bool GetDetailData(DeviceDescriptor* device,

GetMountpoints(deviceNumber, &device->mountpoints);

// printf("[INFO] Opening handle to %s\n", device->raw.c_str());

hPhysical = CreateFileA(
device->raw.c_str(), handleOpenFlags,
device->raw.c_str(), 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

// printf("[INFO] Opened handle to %s\n", device->raw.c_str());
// printf("[INFO] Handle %i (INVALID %i)\n",
// hPhysical, INVALID_HANDLE_VALUE);

if (hPhysical == INVALID_HANDLE_VALUE) {
errorCode = GetLastError();
// printf("[INFO] Couldn't open handle to %s: Error %i\n",
// device->raw.c_str(), errorCode);
device->error = "Couldn't open handle to physical device: Error " +
std::to_string(errorCode);
result = false;
break;
}

// printf("[INFO] GetDeviceSize( %s )\n", device->raw.c_str());

if (!GetDeviceSize(hPhysical, device)) {
errorCode = GetLastError();
// printf("[ERROR] Couldn't get disk geometry: Error %i\n", errorCode);
device->error = "Couldn't get disk geometry: Error " +
std::to_string(errorCode);
result = false;
break;
}

// printf("[INFO] GetAdapterInfo( %s )\n", device->raw.c_str());

if (!GetAdapterInfo(hPhysical, device)) {
errorCode = GetLastError();
// printf("[ERROR] Couldn't get device adapter descriptor: Error %i\n",
// errorCode);
device->error = "Couldn't get device adapter descriptor: Error " +
std::to_string(errorCode);
result = false;
break;
}

// printf("[INFO] GetDeviceBlockSize( %s )\n", device->raw.c_str());

// NOTE: No need to fail over this one,
// as we can safely default to a 512B block size
if (!GetDeviceBlockSize(hPhysical, device)) {
errorCode = GetLastError();
// printf("[INFO] Couldn't get block size: Error %u\n", errorCode);
}

// printf("[INFO] isWritable( %s )\n", device->raw.c_str());

BOOL isWritable = DeviceIoControl(
hPhysical, IOCTL_DISK_IS_WRITABLE, NULL, 0,
NULL, 0, &size, NULL);

device->isReadOnly = !isWritable;
}
} // end for (index = 0; ; index++)

if (hDevice != INVALID_HANDLE_VALUE) {
CloseHandle(hDevice);
hDevice = INVALID_HANDLE_VALUE;
}

if (hPhysical != INVALID_HANDLE_VALUE) {
CloseHandle(hPhysical);
hPhysical = INVALID_HANDLE_VALUE;
}

free(deviceDetailData);
Expand Down Expand Up @@ -565,6 +612,8 @@ std::vector<DeviceDescriptor> ListStorageDevices() {
for (i = 0; SetupDiEnumDeviceInfo(hDeviceInfo, i, &deviceInfoData); i++) {
enumeratorName = GetEnumeratorName(hDeviceInfo, deviceInfoData);

// printf("[INFO] Enumerating %s\n", enumeratorName);

// If it failed to get the SPDRP_ENUMERATOR_NAME, skip it
if (enumeratorName == NULL) {
continue;
Expand Down

0 comments on commit dc35503

Please sign in to comment.