示例#1
0
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;
}
示例#2
0
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;
}