LPTSTR pGetDiskForNdasScsiLocationEx( const NDAS_SCSI_LOCATION* NdasScsiLocation, BOOL SymbolicLinkOrDevInstId) { // Get the child device instances of the NDAS SCSI pdo XTL::AutoProcessHeapPtr<TCHAR> ChildDevInstIdList = pGetChildDevInstIdsForNdasScsiLocation(NdasScsiLocation); // Find the disk of TargetID and LUN for all child device instances for (LPCTSTR ChildDevInstId = ChildDevInstIdList; ChildDevInstId && *ChildDevInstId; ChildDevInstId += ::lstrlen(ChildDevInstId) + 1) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_VERBOSE, _T("ChildDevInstId:%s\n"), ChildDevInstId); // Ensure that the child really is present (not ghosted) DEVINST ChildDevInst; CONFIGRET ret = ::CM_Locate_DevNode( &ChildDevInst, const_cast<DEVINSTID>(ChildDevInstId), CM_LOCATE_DEVNODE_NORMAL); if (CR_SUCCESS != ret) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, "CM_Locate_DevNode failed, cret=0x%X\n", ret); continue; } // Query the Disk Class Interface, if there are no disk class // interface, it is not of a disk class. XTL::AutoProcessHeapPtr<TCHAR> SymLinkList; ret = pCMGetDeviceInterfaceList( &SymLinkList, &DiskClassGuid, const_cast<DEVINSTID>(ChildDevInstId), CM_GET_DEVICE_INTERFACE_LIST_PRESENT); if (CR_SUCCESS != ret) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, "pCMGetDeviceInterfaceList failed, cret=0x%X\n", ret); continue; } // Returned list contains the list of the device file names (or // symbolic links) which we can open with CreateFile for IO_CTLs for (LPCTSTR DeviceName = SymLinkList; DeviceName && *DeviceName; DeviceName += ::lstrlen(DeviceName) + 1) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_VERBOSE, _T("Device:%s\n"), DeviceName); XTL::AutoFileHandle hDevice = ::CreateFile( DeviceName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice.IsInvalid()) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, _T("CreateFile(%s) failed, error=0x%X\n"), DeviceName, GetLastError()); continue; } // Query the SCSI Address and compare TargetID and LUN to // compare them with those of NDAS SCSI location. SCSI_ADDRESS scsiAddress; if (!pScsiGetAddress(hDevice, &scsiAddress)) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, _T("GetScsiAddress(%s) failed, error=0x%X\n"), DeviceName, GetLastError()); continue; } if (NdasScsiLocation->TargetID == scsiAddress.TargetId && NdasScsiLocation->LUN == scsiAddress.Lun) { // We found the target disk, and we create a buffer to // return. If SymbolicLinkOrDevInstId is non-zero (TRUE), // we will returns SymbolicLink, otherwise, we will return the DevInstId if (SymbolicLinkOrDevInstId) { DWORD TargetLength = (::lstrlen(DeviceName) + 1) * sizeof(TCHAR); XTL::AutoProcessHeapPtr<TCHAR> TargetDeviceName = static_cast<LPTSTR>( ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, TargetLength)); if (TargetDeviceName.IsInvalid()) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, "HeapAlloc failed, byets=%d\n", TargetLength); return NULL; } ::CopyMemory(TargetDeviceName, DeviceName, TargetLength); return TargetDeviceName.Detach(); } else { DWORD TargetLength = (::lstrlen(ChildDevInstId) + 1) * sizeof(TCHAR); XTL::AutoProcessHeapPtr<TCHAR> TargetDevInstId = static_cast<LPTSTR>( ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, TargetLength)); if (TargetDevInstId.IsInvalid()) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, "HeapAlloc failed, byets=%d\n", TargetLength); return NULL; } ::CopyMemory(TargetDevInstId, ChildDevInstId, TargetLength); return TargetDevInstId.Detach(); } } } } return NULL; }
HRESULT pGetScsiAddressForDisk( __in HANDLE hDisk, __out PSCSI_ADDRESS ScsiAddress) { HRESULT hr; // // Query Storage Property // XTLTRACE2(NdasVolTrace, 3, "DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY)\n"); if (NULL == ScsiAddress) { return E_POINTER; } XTL::AutoProcessHeapPtr<STORAGE_ADAPTER_DESCRIPTOR> adapterDescriptor = pStorageQueryAdapterProperty(hDisk); if (adapterDescriptor.IsInvalid()) { hr = HRESULT_FROM_WIN32(GetLastError()); XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, "pStorageQueryAdapterProperty failed, hr=0x%X\n", hr); return hr; } // // Ignore non-SCSI device // if (BusTypeScsi != adapterDescriptor->BusType) { hr = NDASVOL_ERROR_NON_NDAS_VOLUME; XTLTRACE2(NdasVolTrace, 2, "Ignoring non-scsi bus, hr=0x%X\n", hr); return hr; } // // Query SCSI Address, given that the physical drive is a SCSI device // XTLTRACE2(NdasVolTrace, 3, "DeviceIoControl(IOCTL_SCSI_GET_ADDRESS)\n"); SCSI_ADDRESS scsiAddress = {0}; hr = pScsiGetAddress(hDisk, &scsiAddress); if (FAILED(hr)) { XTLTRACE2(NdasVolTrace, TRACE_LEVEL_ERROR, "pScsiGetAddress failed, hr=0x%X\n", hr); hr = NDASVOL_ERROR_NON_NDAS_VOLUME; return hr; } XTLTRACE2(NdasVolTrace, TRACE_LEVEL_INFORMATION, "SCSIAddress: Len: %d, PortNumber: %d, " "PathId: %d, TargetId: %d, Lun: %d\n", (DWORD) scsiAddress.Length, (DWORD) scsiAddress.PortNumber, (DWORD) scsiAddress.PathId, (DWORD) scsiAddress.TargetId, (DWORD) scsiAddress.Lun); // // Return the result // *ScsiAddress = scsiAddress; return S_OK; }