158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file. 458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// devguid requires Windows.h be imported first. 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <windows.h> 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <setupapi.h> 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <winioctl.h> 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_number_conversions.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_handle.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h" 1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace extensions { 1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AddDeviceInfo(HANDLE interface_enumerator, 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVICE_INTERFACE_DATA* interface_data, 22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<StorageDeviceList> device_list) { 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get the required buffer size by calling with a null output buffer. 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD interface_detail_data_size; 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BOOL status = SetupDiGetDeviceInterfaceDetail( 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_enumerator, 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_data, 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Output buffer. 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, // Output buffer size. 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &interface_detail_data_size, // Receives the buffer size. 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); // Optional DEVINFO_DATA. 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status == FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail failed"; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<char[]> interface_detail_data_buffer( 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new char[interface_detail_data_size]); 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVICE_INTERFACE_DETAIL_DATA* interface_detail_data = 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>( 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_detail_data_buffer.get()); 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_detail_data->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = SetupDiGetDeviceInterfaceDetail( 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_enumerator, 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_data, 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_detail_data, // Output struct. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_detail_data_size, // Output struct size. 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Receives required size, unneeded. 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); // Optional DEVINFO_Data. 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status == FALSE) { 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail failed"; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Open a handle to the device to send DeviceIoControl messages. 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::ScopedHandle device_handle(CreateFile( 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_detail_data->DevicePath, 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Desired access, which is none as we only need metadata. 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Required to be read + write for devices. 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FILE_SHARE_READ | FILE_SHARE_WRITE, 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Optional security attributes. 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OPEN_EXISTING, // Devices already exist. 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, // No optional flags. 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL)); // No template file. 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device_handle.IsValid()) { 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "Opening device handle failed."; 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISK_GEOMETRY geometry; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD bytes_returned; 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = DeviceIoControl( 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device_handle.Get(), // Device handle. 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IOCTL_DISK_GET_DRIVE_GEOMETRY, // Flag to request disk size. 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Optional additional parameters. 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, // Optional parameter size. 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &geometry, // output buffer. 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sizeof(DISK_GEOMETRY), // output size. 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &bytes_returned, // Must be non-null. If overlapped is null, 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // then value is meaningless. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); // Optional unused overlapped parameter. 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status == FALSE) { 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "DeviceIoControl"; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ULONGLONG disk_capacity = geometry.Cylinders.QuadPart * 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) geometry.TracksPerCylinder * 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) geometry.SectorsPerTrack * 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) geometry.BytesPerSector; 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) STORAGE_PROPERTY_QUERY query = STORAGE_PROPERTY_QUERY(); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) query.PropertyId = StorageDeviceProperty; 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) query.QueryType = PropertyStandardQuery; 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<char[]> output_buf(new char[1024]); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = DeviceIoControl( 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device_handle.Get(), // Device handle. 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IOCTL_STORAGE_QUERY_PROPERTY, // Flag to request device properties. 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &query, // Query parameters. 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sizeof(STORAGE_PROPERTY_QUERY), // query parameters size. 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output_buf.get(), // output buffer. 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1024, // Size of buffer. 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &bytes_returned, // Number of bytes returned. 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Must not be null. 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); // Optional unused overlapped perameter. 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status == FALSE) { 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "Storage property query failed."; 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) STORAGE_DEVICE_DESCRIPTOR* device_descriptor = 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(output_buf.get()); 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!device_descriptor->RemovableMedia && 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !(device_descriptor->BusType == BusTypeUsb)) { 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Reject non-removable and non-USB devices. 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Return true to indicate success but not add anything to the device list. 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Create a drive identifier from the drive number. 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch STORAGE_DEVICE_NUMBER device_number = {0}; 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch status = DeviceIoControl( 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device_handle.Get(), // Device handle. 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IOCTL_STORAGE_GET_DEVICE_NUMBER,// Flag to request device number. 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL, // Query parameters, should be NULL. 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 0, // Query parameters size, should be 0. 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &device_number, // output buffer. 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sizeof(device_number), // Size of buffer. 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &bytes_returned, // Number of bytes returned. 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL); // Optional unused overlapped perameter. 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (status == FALSE) { 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PLOG(ERROR) << "Storage device number query failed."; 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string drive_id = "\\\\.\\PhysicalDrive"; 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch drive_id.append(base::Uint64ToString(device_number.DeviceNumber)); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) linked_ptr<api::image_writer_private::RemovableStorageDevice> device( 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new api::image_writer_private::RemovableStorageDevice()); 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device->capacity = disk_capacity; 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch device->storage_unit_id = drive_id; 1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) device->removable = device_descriptor->RemovableMedia == TRUE; 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (device_descriptor->VendorIdOffset && 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output_buf[device_descriptor->VendorIdOffset]) { 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device->vendor.assign(output_buf.get() + device_descriptor->VendorIdOffset); 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string product_id; 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (device_descriptor->ProductIdOffset && 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output_buf[device_descriptor->ProductIdOffset]) { 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device->model.assign(output_buf.get() + device_descriptor->ProductIdOffset); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) device_list->data.push_back(device); 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RemovableStorageProvider::PopulateDeviceList( 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<StorageDeviceList> device_list) { 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HDEVINFO interface_enumerator = SetupDiGetClassDevs( 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &DiskClassGuid, 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Enumerator. 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Parent window. 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only devices present & interface class. 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (DIGCF_PRESENT | DIGCF_INTERFACEDEVICE)); 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (interface_enumerator == INVALID_HANDLE_VALUE) { 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DPLOG(ERROR) << "SetupDiGetClassDevs failed."; 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD index = 0; 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SP_DEVICE_INTERFACE_DATA interface_data; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_data.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) while (SetupDiEnumDeviceInterfaces( 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface_enumerator, 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // Device Info data. 1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &GUID_DEVINTERFACE_DISK, // Only disk devices. 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) index, 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &interface_data)) { 1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AddDeviceInfo(interface_enumerator, &interface_data, device_list); 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) index++; 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DWORD error_code = GetLastError(); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (error_code != ERROR_NO_MORE_ITEMS) { 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PLOG(ERROR) << "SetupDiEnumDeviceInterfaces failed"; 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetupDiDestroyDeviceInfoList(interface_enumerator); 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetupDiDestroyDeviceInfoList(interface_enumerator); 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace extensions 216