nsresult sbWinCreateAncestorDeviceFile(HANDLE* aDevFile, DEVINST aDevInst, const GUID* aGUID, DWORD aDesiredAccess, DWORD aShareMode, LPSECURITY_ATTRIBUTES aSecurityAttributes, DWORD aCreationDisposition, DWORD aFlagsAndAttributes, HANDLE aTemplateFile) { // Validate arguments. NS_ENSURE_ARG_POINTER(aDevFile); // Function variables. CONFIGRET cfgRet; nsresult rv; // Search for an ancestor device that has the specified interface. DEVINST ancestorDevInst; DEVINST devInst = aDevInst; while (1) { // Get the next ancestor. cfgRet = CM_Get_Parent(&ancestorDevInst, devInst, 0); if (cfgRet != CR_SUCCESS) return NS_ERROR_NOT_AVAILABLE; // Check if the ancestor has the interface. bool hasInterface; rv = sbWinDeviceHasInterface(ancestorDevInst, aGUID, &hasInterface); NS_ENSURE_SUCCESS(rv, rv); if (hasInterface) break; // Check the next ancestor. devInst = ancestorDevInst; } /* Create a device file for the ancestor. */ return sbWinCreateDeviceFile(aDevFile, ancestorDevInst, aGUID, aDesiredAccess, aShareMode, aSecurityAttributes, aCreationDisposition, aFlagsAndAttributes, aTemplateFile); }
nsresult sbWinRegisterDeviceHandleNotification(HDEVNOTIFY* aDeviceNotification, HWND aEventWindow, DEVINST aDevInst, const GUID& aGUID) { // Validate arguments. NS_ENSURE_ARG_POINTER(aDeviceNotification); // Function variables. nsresult rv; // Create a device file for notifications. sbAutoHANDLE deviceHandle; rv = sbWinCreateDeviceFile(deviceHandle.StartAssignment(), aDevInst, &aGUID, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); NS_ENSURE_SUCCESS(rv, rv); // Register for device handle notifications. The handle may be closed after // registration without affecting the registration. Doing so avoids having // extra device file handles open. HDEVNOTIFY deviceNotification; DEV_BROADCAST_HANDLE devBroadcast = {0}; devBroadcast.dbch_size = sizeof(devBroadcast); devBroadcast.dbch_devicetype = DBT_DEVTYP_HANDLE; devBroadcast.dbch_handle = deviceHandle; deviceNotification = RegisterDeviceNotification(aEventWindow, &devBroadcast, 0); NS_ENSURE_TRUE(deviceNotification, NS_ERROR_FAILURE); // Return results. *aDeviceNotification = deviceNotification; return NS_OK; }
nsresult sbWinGetSCSIProductInfo(DEVINST aDevInst, nsAString& aVendorID, nsAString& aProductID) { DWORD byteCount; BOOL success; errno_t errno; nsresult rv; // Create a disk interface device file. sbAutoHANDLE diskHandle; GUID guid = GUID_DEVINTERFACE_DISK; rv = sbWinCreateDeviceFile(diskHandle.StartAssignment(), aDevInst, &guid, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); NS_ENSURE_SUCCESS(rv, rv); // Set up a storage property query to get the storage device descriptor. STORAGE_PROPERTY_QUERY storagePropertyQuery; memset(&storagePropertyQuery, 0, sizeof(storagePropertyQuery)); storagePropertyQuery.PropertyId = StorageDeviceProperty; storagePropertyQuery.QueryType = PropertyStandardQuery; // Determine how many bytes are required to hold the full storage device // descriptor. STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader; success = DeviceIoControl(diskHandle, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(storagePropertyQuery), &storageDescriptorHeader, sizeof(storageDescriptorHeader), &byteCount, NULL); NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); NS_ENSURE_TRUE(byteCount == sizeof(storageDescriptorHeader), NS_ERROR_FAILURE); // Allocate the storage device descriptor. sbAutoMemPtr<STORAGE_DEVICE_DESCRIPTOR> storageDeviceDescriptor = static_cast<PSTORAGE_DEVICE_DESCRIPTOR> (malloc(storageDescriptorHeader.Size)); NS_ENSURE_TRUE(storageDeviceDescriptor, NS_ERROR_OUT_OF_MEMORY); // Get the storage device descriptor. success = DeviceIoControl(diskHandle, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(storagePropertyQuery), storageDeviceDescriptor, storageDescriptorHeader.Size, &byteCount, NULL); NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); NS_ENSURE_TRUE(byteCount == storageDescriptorHeader.Size, NS_ERROR_FAILURE); // Return results with trailing spaces trimmed. SCSI inquiry vendor and // product IDs have trailing spaces as filler. aVendorID.AssignLiteral (reinterpret_cast<char*>(storageDeviceDescriptor.get()) + storageDeviceDescriptor->VendorIdOffset); aVendorID.Trim(" ", PR_FALSE, PR_TRUE); aProductID.AssignLiteral (reinterpret_cast<char*>(storageDeviceDescriptor.get()) + storageDeviceDescriptor->ProductIdOffset); aProductID.Trim(" ", PR_FALSE, PR_TRUE); return NS_OK; }