This source file includes following definitions.
- AddDeviceInfo
- PopulateList
- GetAllDevices
#include <windows.h>
#include <setupapi.h>
#include <winioctl.h>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_handle.h"
#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
namespace extensions {
namespace {
bool AddDeviceInfo(HANDLE interface_enumerator,
SP_DEVICE_INTERFACE_DATA* interface_data,
StorageDeviceList* device_list) {
DWORD interface_detail_data_size;
BOOL status = SetupDiGetDeviceInterfaceDetail(
interface_enumerator,
interface_data,
NULL,
0,
&interface_detail_data_size,
NULL);
if (status == FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail failed";
return false;
}
scoped_ptr<char[]> interface_detail_data_buffer(
new char[interface_detail_data_size]);
SP_DEVICE_INTERFACE_DETAIL_DATA* interface_detail_data =
reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(
interface_detail_data_buffer.get());
interface_detail_data->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
status = SetupDiGetDeviceInterfaceDetail(
interface_enumerator,
interface_data,
interface_detail_data,
interface_detail_data_size,
NULL,
NULL);
if (status == FALSE) {
PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail failed";
return false;
}
base::win::ScopedHandle device_handle(CreateFile(
interface_detail_data->DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL));
if (!device_handle) {
PLOG(ERROR) << "Opening device handle failed.";
return false;
}
DISK_GEOMETRY geometry;
DWORD bytes_returned;
status = DeviceIoControl(
device_handle,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&geometry,
sizeof(DISK_GEOMETRY),
&bytes_returned,
NULL);
if (status == FALSE) {
PLOG(ERROR) << "DeviceIoControl";
return false;
}
ULONGLONG disk_capacity = geometry.Cylinders.QuadPart *
geometry.TracksPerCylinder *
geometry.SectorsPerTrack *
geometry.BytesPerSector;
STORAGE_PROPERTY_QUERY query = STORAGE_PROPERTY_QUERY();
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
scoped_ptr<char[]> output_buf(new char[1024]);
status = DeviceIoControl(
device_handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&query,
sizeof(STORAGE_PROPERTY_QUERY),
output_buf.get(),
1024,
&bytes_returned,
NULL);
if (status == FALSE) {
PLOG(ERROR) << "Storage property query failed.";
return false;
}
STORAGE_DEVICE_DESCRIPTOR* device_descriptor =
reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(output_buf.get());
if (!device_descriptor->RemovableMedia) {
return true;
}
linked_ptr<api::image_writer_private::RemovableStorageDevice> device(
new api::image_writer_private::RemovableStorageDevice());
device->capacity = disk_capacity;
base::string16 device_path_16(interface_detail_data->DevicePath);
device->storage_unit_id = base::UTF16ToUTF8(device_path_16);
if (device_descriptor->VendorIdOffset &&
output_buf[device_descriptor->VendorIdOffset]) {
device->vendor.assign(output_buf.get() + device_descriptor->VendorIdOffset);
}
std::string product_id;
if (device_descriptor->ProductIdOffset &&
output_buf[device_descriptor->ProductIdOffset]) {
device->model.assign(output_buf.get() + device_descriptor->ProductIdOffset);
}
device_list->data.push_back(device);
return true;
}
bool PopulateList(StorageDeviceList* device_list) {
HDEVINFO interface_enumerator = SetupDiGetClassDevs(
&DiskClassGuid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_INTERFACEDEVICE));
if (interface_enumerator == INVALID_HANDLE_VALUE) {
DPLOG(ERROR) << "SetupDiGetClassDevs failed.";
return false;
}
DWORD index = 0;
SP_DEVICE_INTERFACE_DATA interface_data;
interface_data.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
while (SetupDiEnumDeviceInterfaces(
interface_enumerator,
NULL,
&GUID_DEVINTERFACE_DISK,
index,
&interface_data)) {
AddDeviceInfo(interface_enumerator, &interface_data, device_list);
index++;
}
DWORD error_code = GetLastError();
if (error_code != ERROR_NO_MORE_ITEMS) {
PLOG(ERROR) << "SetupDiEnumDeviceInterfaces failed";
SetupDiDestroyDeviceInfoList(interface_enumerator);
return false;
}
SetupDiDestroyDeviceInfoList(interface_enumerator);
return true;
}
}
void RemovableStorageProvider::GetAllDevices(DeviceListReadyCallback callback) {
scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList());
if (PopulateList(device_list.get())) {
callback.Run(device_list, true);
} else {
callback.Run(device_list, false);
}
}
}