NDASBUSCTLAPI
BOOL 
WINAPI
NdasBusCtlQueryPdoSlotList(
	PNDASBUS_INFORMATION *BusInfo
) {
	BOOL						bret;
	NDASBUS_QUERY_INFORMATION	query;
	NDASBUS_INFORMATION			tmpInfo;
	PNDASBUS_INFORMATION		info;
	LONG						infoLen;

	*BusInfo = NULL;

	query.Size		= sizeof(query);
	query.InfoClass = INFORMATION_PDOSLOTLIST;
	query.Flags		= 0;
	query.SlotNo	= 0;
	bret = NdasBusCtlQueryInformation(
					&query,
					sizeof(query),
					&tmpInfo,
					sizeof(tmpInfo)
				);
	if(bret == FALSE) {
		if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
			return FALSE;
		}
	}

	infoLen = tmpInfo.Size;

	info = HeapAlloc(GetProcessHeap(), 0, infoLen);
	if (NULL == info) {
		SetLastError(ERROR_OUTOFMEMORY);
		return FALSE;
	}

	bret = NdasBusCtlQueryInformation(
					&query,
					sizeof(query),
					info,
					infoLen
				);
	if(bret == FALSE) {
		HeapFree(GetProcessHeap(), 0, info);
		return FALSE;
	}

	*BusInfo = info;

	return TRUE;
}
NDASBUSCTLAPI BOOL WINAPI
NdasBusCtlQueryEvent(
	ULONG SlotNo,
	PULONG pStatus)
{
	BOOL fSuccess = FALSE;

	NDASBUS_QUERY_INFORMATION Query;
	NDASBUS_INFORMATION	Information;

	//
	//	Query AccessRight to LanscsiBus
	//
	Query.InfoClass = INFORMATION_PDO;
	Query.Size		= sizeof(Query) ;
	Query.SlotNo	= SlotNo;
	Query.Flags		= NDASBUS_QUERYFLAG_EVENTQUEUE;

	fSuccess = NdasBusCtlQueryInformation(
				&Query,
				sizeof(Query),
				&Information,
				sizeof(Information));

	if (!fSuccess) {
		return FALSE;
	}

	// ndasscsiioctl.h
	// ADAPTERINFO_STATUS_*
	// ADAPTERINFO_STATUSFLAG_*
	*pStatus = Information.PdoInfo.AdapterStatus;

	return TRUE;
}
NDASBUSCTLAPI BOOL WINAPI
NdasBusCtlQueryDeviceMode(
	ULONG SlotNo,
	PULONG pDeviceMode)
{
	BOOL fSuccess = FALSE;

	NDASBUS_QUERY_INFORMATION Query;
	NDASBUS_INFORMATION	Information;

	//
	//	Query AccessRight to LanscsiBus
	//
	Query.InfoClass = INFORMATION_PDO;
	Query.Size		= sizeof(Query);
	Query.SlotNo	= SlotNo;
	Query.Flags		= 0;

	fSuccess = NdasBusCtlQueryInformation(
		&Query,
		sizeof(Query),
		&Information,
		sizeof(Information));

	if (!fSuccess) {
		return FALSE;
	}

	// lurdesc.h
	// DEVMODE_*
	*pDeviceMode = Information.PdoInfo.DeviceMode;

	return TRUE;
}
NDASBUSCTLAPI
BOOL 
WINAPI
NdasBusCtlQueryPdoEvent(
	ULONG	SlotNo,
	PHANDLE	AlarmEvent,
	PHANDLE	DisconnectEvent
) {
	BOOL						bret;
	NDASBUS_QUERY_INFORMATION	query;
	NDASBUS_INFORMATION			tmpInfo;

	query.Size		= sizeof(query);
	query.InfoClass = INFORMATION_PDOEVENT;
	query.Flags		= NDASBUS_QUERYFLAG_USERHANDLE;
	query.SlotNo	= SlotNo;
	bret = NdasBusCtlQueryInformation(
					&query,
					sizeof(query),
					&tmpInfo,
					sizeof(tmpInfo)
				);
	if(bret == FALSE) {
		return FALSE;
	}

	if(!(tmpInfo.PdoEvents.Flags & NDASBUS_QUERYFLAG_USERHANDLE)) {
		SetLastError(ERROR_INVALID_DATA);
		return FALSE;
	}
	if(tmpInfo.PdoEvents.SlotNo != SlotNo) {
		SetLastError(ERROR_INVALID_DATA);
		return FALSE;
	}

	*AlarmEvent = tmpInfo.PdoEvents.AlarmEvent;
	*DisconnectEvent = tmpInfo.PdoEvents.DisconEvent;

	return TRUE;
}
NDASBUSCTLAPI 
BOOL 
WINAPI
NdasBusCtlQueryPdoFileHandle(
	ULONG	SlotNo,
	PHANDLE	PdoFileHandle)
{
	BOOL						bret;
	NDASBUS_QUERY_INFORMATION	query;
	NDASBUS_INFORMATION			tmpInfo;

	query.Size		= sizeof(query);
	query.InfoClass = INFORMATION_PDOFILEHANDLE;
	query.Flags		= NDASBUS_QUERYFLAG_USERHANDLE;
	query.SlotNo	= SlotNo;
	bret = NdasBusCtlQueryInformation(
					&query,
					sizeof(query),
					&tmpInfo,
					sizeof(tmpInfo)
				);
	if(bret == FALSE) {
		return FALSE;
	}

	if(!(tmpInfo.PdoEvents.Flags & NDASBUS_QUERYFLAG_USERHANDLE)) {
		SetLastError(ERROR_INVALID_DATA);
		return FALSE;
	}
	if(tmpInfo.PdoEvents.SlotNo != SlotNo) {
		SetLastError(ERROR_INVALID_DATA);
		return FALSE;
	}

	*PdoFileHandle = tmpInfo.PdoFile.PdoFileHandle;

	return TRUE;
}
Exemple #6
0
BOOL
CNdasIXBcast::BroadcastStatus()
{
	NDASBUS_QUERY_INFORMATION BusEnumQuery;
	NDASBUS_INFORMATION BusEnumInformation;

	CNdasLogicalDeviceManager& manager = pGetNdasLogicalDeviceManager();
	CNdasLogicalDeviceVector logDevices;
	manager.Lock();
	manager.GetItems(logDevices);
	manager.Unlock();

	for (CNdasLogicalDeviceVector::const_iterator itr = logDevices.begin();
		itr != logDevices.end();
		++itr)
	{
		CNdasLogicalDevicePtr pLogDevice = *itr;

		if (NDAS_LOGICALDEVICE_STATUS_MOUNTED != pLogDevice->GetStatus()) {
			continue;
		}

		CONST NDAS_LOCATION& location = pLogDevice->GetNdasLocation();

		BusEnumQuery.InfoClass = INFORMATION_PDO;
		BusEnumQuery.Size = sizeof(NDASBUS_QUERY_INFORMATION);
		BusEnumQuery.SlotNo = location;
		BusEnumQuery.Flags = 0;

		BOOL fSuccess = NdasBusCtlQueryInformation(
			&BusEnumQuery,
			sizeof(NDASBUS_QUERY_INFORMATION),
			&BusEnumInformation,
			sizeof(NDASBUS_INFORMATION));

		if (!fSuccess) {
			XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR,
				"LanscsiQueryInformation failed, slot=%d, error=0x%X\n",
				location, GetLastError());
			continue;
		}

		//
		// Broadcast a primary write access status
		//
		if (BusEnumInformation.PdoInfo.DeviceMode == DEVMODE_SHARED_READWRITE &&
			!(BusEnumInformation.PdoInfo.EnabledFeatures & NDASFEATURE_SECONDARY)) {

			const DWORD cbBuffer = 
				sizeof(LSINFOX_HEADER) + sizeof(LSINFOX_PRIMARY_UPDATE);

			BYTE lpbBuffer[cbBuffer] = {0};

			PLSINFOX_HEADER pixHeader = 
				reinterpret_cast<PLSINFOX_HEADER>(lpbBuffer);

			PLSINFOX_DATA pixData = 
				reinterpret_cast<PLSINFOX_DATA>(lpbBuffer + sizeof(LSINFOX_HEADER));

			//
			// CAUTION: InfoExchange Protocol uses little-endian (Intel)
			//

			//
			// Header
			//
			UCHAR ixProtocolName[4] = INFOX_DATAGRAM_PROTOCOL;
			::CopyMemory(pixHeader->Protocol, ixProtocolName, 4);
			pixHeader->LSInfoXMajorVersion = INFOX_DATAGRAM_MAJVER;
			pixHeader->LSInfoXMinorVersion = INFOX_DATAGRAM_MINVER;
			pixHeader->OsMajorType = OSTYPE_WINDOWS;
			
			DWORD dwOSMajorVersion, dwOSMinorVersion;
			pGetOSVersion(&dwOSMajorVersion, &dwOSMinorVersion);
			USHORT usLfsOsMinorType = 
				pInfoXGetOSType(dwOSMajorVersion, dwOSMinorVersion);
			pixHeader->OsMinorType = usLfsOsMinorType;
			pixHeader->Type = LSINFOX_PRIMARY_UPDATE_MESSAGE;
			pixHeader->MessageSize = cbBuffer;

			//
			// Data
			//

			// primary node is dependent to each interface
			pixData->Update.PrimaryNode; 
			pixData->Update.PrimaryPort = LPXRP_LFS_PRIMARY;
			pixData->Update.SWMajorVersion = NDASIX_VERSION_MAJOR; // TODO: Change these values
			pixData->Update.SWMinorVersion = NDASIX_VERSION_MINOR;
			pixData->Update.SWBuildNumber = NDASIX_VERSION_BUILD;
			pixData->Update.NDFSCompatVersion = m_NDFSVersion.wMajor;
			pixData->Update.NDFSVersion = m_NDFSVersion.wMinor;

			//
			// NetDisk Node is a property of each unit device
			//
			pixData->Update.NetDiskNode;
			//
			// We have fixed the port 
			// (CNdasDevice does not store Port Number internally)
			// Do not try to retrieve from GetRemoteLpxAddress()
			//
			pixData->Update.NetDiskPort = NDAS_DEVICE_LPX_PORT;

			//
			// Unit Disk Number is a property of each unit device
			//
			pixData->Update.UnitDiskNo;

			//
			// pLogDevice->GetStatus()
			//
			for (DWORD n = 0; n < pLogDevice->GetUnitDeviceCount(); ++n) {
				//
				// Actually, we should traverse the real entry
				// from the device registrar.
				// However, here we do the shortcut for using NDAS device id
				// and fixed NetDiskPort, etc.
				//
				NDAS_UNITDEVICE_ID unitDeviceId = pLogDevice->GetUnitDeviceID(n);

				C_ASSERT(sizeof(pixData->Update.NetDiskNode) ==
					sizeof(unitDeviceId.DeviceId.Node));

				::CopyMemory(
					pixData->Update.NetDiskNode,
					unitDeviceId.DeviceId.Node,
					sizeof(pixData->Update.NetDiskNode));

				pixData->Update.UnitDiskNo = static_cast<USHORT>(unitDeviceId.UnitNo);

				//
				// Broadcast the data to every interface
				//
				for (DWORD i = 0; i < MAX_SOCKETLPX_INTERFACE; ++i) {

					if (INVALID_SOCKET != (SOCKET) m_senders[i]) {
						
						//
						// Fill the Primary Node (LPX Address Node)
						//
						LPX_ADDRESS localLpxAddress = 
							m_senders[i].GetBoundAddr()->LpxAddress;

						C_ASSERT(sizeof(pixData->Update.PrimaryNode) ==
							sizeof(localLpxAddress.Node));

						::CopyMemory(
							pixData->Update.PrimaryNode,
							localLpxAddress.Node,
							sizeof(pixData->Update.PrimaryNode));
						
						//
						// Send the data
						//
						DWORD cbSent = 0;
						BOOL fSuccess =	m_senders[i].SendToSync(
								&NDASIX_BCAST_ADDR,
								cbBuffer,
								lpbBuffer,
								0,
								&cbSent);
						if (!fSuccess) {
							XTLTRACE2(NDASSVC_IX, TRACE_LEVEL_ERROR,
								"SendToSync failed, bytes=%d, error=0x%X\n",
								cbBuffer, GetLastError());
						}

					} // end if
				} // for each local LPX address
			} // for each unit device
		} // if the logical device has a primary write access.
	} // for each logical device

	return TRUE;
}
Exemple #7
0
int __cdecl _tmain(int argc, LPTSTR* argv)
{
    BOOL	fSuccess(FALSE);
    ULONG	SlotNo;
    BOOL	bret;

    if(argc < 2) {
        usage();
        return 1;
    }

    if (lstrcmpi(argv[1],TEXT("version")) == 0) {
        WORD VersionMajor;
        WORD VersionMinor;
        WORD VersionBuild;
        WORD VersionPrivate;

        bret = NdasBusCtlGetVersion(
                   &VersionMajor,
                   &VersionMinor,
                   &VersionBuild,
                   &VersionPrivate
               );
        if(bret == FALSE) {
            _tprintf(TEXT("LanscsiBus control failed. LastError:%lu\n"), GetLastError());
        } else {
            _tprintf(TEXT("- LanscsiBus version\n"));
            _tprintf(	TEXT("Major   : %u\n")
                        TEXT("Minor   : %u\n")
                        TEXT("Build   : %u\n")
                        TEXT("Private : %u\n"),
                        VersionMajor, VersionMinor, VersionBuild, VersionPrivate);
        }
#if 0
    } else if(lstrcmpi(argv[1],TEXT("mpversion")) == 0) {
        WORD VersionMajor;
        WORD VersionMinor;
        WORD VersionBuild;
        WORD VersionPrivate;

        if(argc < 3) {
            usage();
            return 1;
        }

        SlotNo = _tstoi(argv[2]);
        bret = NdasBusCtlGetMiniportVersion(
                   SlotNo,
                   &VersionMajor,
                   &VersionMinor,
                   &VersionBuild,
                   &VersionPrivate
               );
        if(bret == FALSE) {
            _tprintf(TEXT("NDASSCSI control failed. LastError:%lu\n"), GetLastError());
        } else {
            _tprintf(TEXT("- NDASSCSI version\n"));
            _tprintf(	TEXT("Major   : %u\n")
                        TEXT("Minor   : %u\n")
                        TEXT("Build   : %u\n")
                        TEXT("Private : %u\n"),
                        VersionMajor, VersionMinor, VersionBuild, VersionPrivate);
        }
#endif
    } else if(lstrcmpi(argv[1],TEXT("slotlist")) == 0) {
        PNDASBUS_INFORMATION	busInfo;

        bret = NdasBusCtlQueryPdoSlotList(&busInfo);
        if(bret == FALSE) {
            _tprintf(TEXT("Querying slot list failed. LastError:%lu\n"), GetLastError());
        } else {
            ULONG idx_slot;
            _tprintf(TEXT("Slot list:"));
            for(idx_slot = 0; idx_slot < busInfo->PdoSlotList.SlotNoCnt; idx_slot++ ) {
                _tprintf(TEXT(" %lu"), busInfo->PdoSlotList.SlotNo[idx_slot]);
            }
            _tprintf(TEXT("\n"));
            HeapFree(GetProcessHeap(), 0, busInfo);
        }
    } else if(lstrcmpi(argv[1],TEXT("pdoinfo")) == 0) {
        NDASBUS_QUERY_INFORMATION BusEnumQuery = {0};
        NDASBUS_INFORMATION BusEnumInformation = {0};

        if(argc < 3) {
            usage();
            return 1;
        }

        SlotNo = _tstoi(argv[2]);

        //
        // Get default priamry/secondary information from the NDAS bus drver.
        //

        BusEnumQuery.InfoClass = INFORMATION_PDO;
        BusEnumQuery.Size = sizeof(NDASBUS_QUERY_INFORMATION);
        BusEnumQuery.SlotNo = SlotNo;
        BusEnumQuery.Flags = 0;
        bret = NdasBusCtlQueryInformation(
                   &BusEnumQuery,
                   sizeof(NDASBUS_QUERY_INFORMATION),
                   &BusEnumInformation,
                   sizeof(NDASBUS_INFORMATION));
        if(bret == FALSE) {
            _tprintf(TEXT("NdasBusCtlQueryInformation failed. LASTERR=%x\n"), GetLastError());
            return 1;
        }

        _tprintf(TEXT("Ndas logical address: %d\n"), SlotNo);
        _tprintf(TEXT("Adapter status    : %08lx\n"), BusEnumInformation.PdoInfo.AdapterStatus);
        _tprintf(TEXT("Device mode       : %08lx\n"), BusEnumInformation.PdoInfo.DeviceMode);
        _tprintf(TEXT("Supported features: %08lx\n"), BusEnumInformation.PdoInfo.SupportedFeatures);
        _tprintf(TEXT("Enabled features  : %08lx\n"), BusEnumInformation.PdoInfo.EnabledFeatures);

    } else if(lstrcmpi(argv[1],TEXT("pdoevent")) == 0) {
        ULONG ulStatus;
        if(argc < 3) {
            usage();
            return 1;
        }

        SlotNo = _tstoi(argv[2]);
        bret = NdasBusCtlQueryEvent(SlotNo, &ulStatus);

        if(bret == FALSE) {
            DWORD lastError = GetLastError();

            if(lastError == ERROR_NO_MORE_ITEMS) {
                _tprintf(TEXT("No more event exists.\n"));
            } else if(lastError == ERROR_FILE_NOT_FOUND) {
                _tprintf(TEXT("No PDO exists.\n"));
            } else {
                _tprintf(TEXT("Querying PDO event failed. LastError:%lu\n"), GetLastError());
            }
        } else {
            PrintStatus(ulStatus);
        }
    } else if(lstrcmpi(argv[1],TEXT("pdoeventptr")) == 0) {
        HANDLE	alarm;
        HANDLE	discon;

        if(argc < 3) {
            usage();
            return 1;
        }

        SlotNo = _tstoi(argv[2]);
        bret = NdasBusCtlQueryPdoEvent(SlotNo, &alarm, &discon);
        if(bret == FALSE) {
            _tprintf(TEXT("Querying pdo events failed. LastError:%lu\n"), GetLastError());
        } else {
            _tprintf(	TEXT("Alarm event        : %p\n")
                        TEXT("Disconnection event: %p\n"),
                        alarm, discon
                    );
            bret = CloseHandle(alarm);
            if(bret == FALSE) {
                _tprintf(TEXT("Closing alarm event failed. LastError:%lu\n"), GetLastError());
            }
            bret = CloseHandle(discon);
            if(bret == FALSE) {
                _tprintf(TEXT("Closing disconnection event failed. LastError:%lu\n"), GetLastError());
            }
        }

    } else if(lstrcmpi(argv[1],TEXT("status")) == 0) {
        ULONG ulStatus;
        if(argc < 3) {
            usage();
            return 1;
        }

        SlotNo = _tstoi(argv[2]);
        bret = NdasBusCtlQueryStatus(SlotNo, &ulStatus);

        if(bret == FALSE) {
            _tprintf(TEXT("Querying PDO status failed. LastError:%lu\n"), GetLastError());
        } else {
            PrintStatus(ulStatus);
        }

    } else if(lstrcmpi(argv[1],TEXT("fdoinfo")) == 0) {
        PNDSCIOCTL_LURINFO	lurFullInfo;

        if(argc < 3) {
            usage();
            return 1;
        }

        SlotNo = _tstoi(argv[2]);
        bret = NdasBusCtlQueryMiniportFullInformation(SlotNo, &lurFullInfo);
        if(bret == FALSE) {
            _tprintf(TEXT("Querying LUR full information  failed. LastError:%lu\n"), GetLastError());
        } else {
            ULONG				idx_ud;
            PNDSC_LURN_FULL		unitDisk;

            _tprintf(TEXT("Structure length                     :%u\n"), lurFullInfo->Length);
            _tprintf(TEXT("Lur.Length                           :%u\n"), lurFullInfo->Lur.Length);
            _tprintf(TEXT("Lur.DevType                          :%08lx\n"), lurFullInfo->Lur.DevType);
            _tprintf(TEXT("Lur.TargetId                         :%u\n"), lurFullInfo->Lur.TargetId);
            _tprintf(TEXT("Lur.Lun                              :%u\n"), lurFullInfo->Lur.Lun);
            _tprintf(TEXT("Lur.DeviceMode                       :%08lx\n"), lurFullInfo->Lur.DeviceMode);
            _tprintf(TEXT("Lur.SupportedFeatures                :%08lx\n"), lurFullInfo->Lur.SupportedFeatures);
            _tprintf(TEXT("Lur.EnabledFeatures                  :%08lx\n"), lurFullInfo->Lur.EnabledFeatures);
            _tprintf(TEXT("Lur.LurnCnt                          :%u\n"), lurFullInfo->Lur.LurnCnt);
            _tprintf(TEXT("EnableTime                           :%I64u\n"), lurFullInfo->EnabledTime.QuadPart);
            _tprintf(TEXT("UnitDiskCnt                          :%u\n"), lurFullInfo->UnitDiskCnt);
            for(idx_ud = 0; idx_ud < lurFullInfo->UnitDiskCnt; idx_ud++) {
                unitDisk = lurFullInfo->UnitDisks + idx_ud;
                _tprintf(TEXT("- LURN #%u   :\n"), idx_ud);
                _tprintf(TEXT("Length       :%u\n"), unitDisk->Length);
                _tprintf(TEXT("LurnId       :%u\n"), unitDisk->LurnId);
                _tprintf(TEXT("LurnType     :%u\n"), unitDisk->LurnType);

                _tprintf(TEXT("NetDiskAddress.TAAddressCount            :%u\n"), unitDisk->NetDiskAddress.TAAddressCount);
                _tprintf(TEXT("NetDiskAddress.Address[0].AddressType    :%x\n"), unitDisk->NetDiskAddress.Address[0].AddressType);
                _tprintf(TEXT("NetDiskAddress.Address[0].AddressLength  :%x\n"), unitDisk->NetDiskAddress.Address[0].AddressLength);
                _tprintf(TEXT("NetDiskAddress.Address[0].Address        :%02X %02X | %02X %02X %02X %02X %02X %02X\n"),
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[0],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[1],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[2],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[3],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[4],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[5],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[6],
                         (int)unitDisk->NetDiskAddress.Address[0].Address.Address[7]
                        );

                _tprintf(TEXT("BindingAddress.TAAddressCount            :%u\n"), unitDisk->BindingAddress.TAAddressCount);
                _tprintf(TEXT("BindingAddress.Address[0].AddressType    :%x\n"), unitDisk->BindingAddress.Address[0].AddressType);
                _tprintf(TEXT("BindingAddress.Address[0].AddressLength  :%x\n"), unitDisk->BindingAddress.Address[0].AddressLength);
                _tprintf(TEXT("BindingAddress.Address[0].Address        :%02X %02X | %02X %02X %02X %02X %02X %02X\n"),
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[0],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[1],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[2],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[3],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[4],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[5],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[6],
                         (int)unitDisk->BindingAddress.Address[0].Address.Address[7]
                        );
                _tprintf(TEXT("UnitDiskId   :%u\n"), (int)unitDisk->UnitDiskId);
                _tprintf(TEXT("UserID       :%02x %02x %02x %02x\n"),
                         (int)unitDisk->UserID[0],
                         (int)unitDisk->UserID[1],
                         (int)unitDisk->UserID[2],
                         (int)unitDisk->UserID[3]
                        );
                _tprintf(TEXT("Password     :%02x %02x %02x %02x %02x %02x\n"),
                         (int)unitDisk->Password[0],
                         (int)unitDisk->Password[1],
                         (int)unitDisk->Password[2],
                         (int)unitDisk->Password[3],
                         (int)unitDisk->Password[4],
                         (int)unitDisk->Password[5]
                        );
                _tprintf(TEXT("AccessRight  :%08lx\n"), unitDisk->AccessRight);
                _tprintf(TEXT("UnitBlocks   :%u\n"), unitDisk->UnitBlocks);
                _tprintf(TEXT("StatusFlags  :%u\n"), unitDisk->StatusFlags);
            }
            _tprintf(TEXT("\n"));
            HeapFree(GetProcessHeap(), 0, lurFullInfo);
        }

    }  else if(lstrcmpi(argv[1],TEXT("pdofile")) == 0) {
        HANDLE	pdoFileHandle;

        SlotNo = _tstoi(argv[2]);
        bret = NdasBusCtlQueryPdoFileHandle(SlotNo, &pdoFileHandle);
        if(bret == FALSE) {
            _tprintf(TEXT("Querying PDO file handle  failed. LastError:%lu\n"), GetLastError());
        } else {
            _tprintf(TEXT("PDO file handle  :%p\n"), pdoFileHandle);
            CloseHandle(pdoFileHandle);
        }
    } else {
        usage();
    }


    return fSuccess ? 0 : 1;
}