You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
600 lines
18 KiB
600 lines
18 KiB
#include <nt.h>
|
|
#include <ntddscsi.h>
|
|
#include <ntdddisk.h>
|
|
#include <ntddcdrm.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <process.h>
|
|
#include <memory.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define _NTSCSI_USER_MODE_
|
|
|
|
#include <scsi.h>
|
|
|
|
VOID
|
|
GetDriverName(
|
|
IN ULONG PortNumber
|
|
)
|
|
{
|
|
UNICODE_STRING name;
|
|
UNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
HANDLE key;
|
|
HANDLE portKey;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
NTSTATUS status;
|
|
UCHAR buffer[64];
|
|
ULONG length;
|
|
PKEY_VALUE_FULL_INFORMATION keyData = (PKEY_VALUE_FULL_INFORMATION)buffer;
|
|
|
|
printf("\nSCSI PORT %d\n", PortNumber);
|
|
|
|
//
|
|
// Obtain handle to SCSI path in device map.
|
|
//
|
|
|
|
RtlInitUnicodeString(&name,
|
|
L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
|
|
|
|
//
|
|
// Initialize the object for the key.
|
|
//
|
|
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&name,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL);
|
|
|
|
//
|
|
// Open the key.
|
|
//
|
|
|
|
status = NtOpenKey(&key,
|
|
KEY_READ,
|
|
&objectAttributes);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Create Scsi port name.
|
|
//
|
|
|
|
sprintf(buffer,
|
|
"Scsi Port %d",
|
|
PortNumber);
|
|
|
|
RtlInitString(&ansiString, buffer);
|
|
|
|
status = RtlAnsiStringToUnicodeString(&unicodeString,
|
|
&ansiString,
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
InitializeObjectAttributes( &objectAttributes,
|
|
&unicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
key,
|
|
(PSECURITY_DESCRIPTOR) NULL );
|
|
|
|
status = NtOpenKey(&portKey,
|
|
KEY_READ,
|
|
&objectAttributes);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString(&name,
|
|
L"Driver");
|
|
|
|
status = NtQueryValueKey(portKey,
|
|
&name,
|
|
KeyValueFullInformation,
|
|
keyData,
|
|
64,
|
|
&length);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
printf("Driver name: %S\n",
|
|
(PUCHAR)keyData + keyData->DataOffset);
|
|
|
|
RtlInitUnicodeString(&name,
|
|
L"Interrupt");
|
|
|
|
status = NtQueryValueKey(portKey,
|
|
&name,
|
|
KeyValueFullInformation,
|
|
keyData,
|
|
64,
|
|
&length);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
printf("IRQ %d ",
|
|
*((PUCHAR)keyData + keyData->DataOffset));
|
|
|
|
RtlInitUnicodeString(&name,
|
|
L"IOAddress");
|
|
|
|
status = NtQueryValueKey(portKey,
|
|
&name,
|
|
KeyValueFullInformation,
|
|
keyData,
|
|
64,
|
|
&length);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
printf("\n");
|
|
return;
|
|
}
|
|
|
|
printf("IO Address %x\n",
|
|
*((PULONG)keyData + keyData->DataOffset/4));
|
|
|
|
return;
|
|
}
|
|
|
|
int __cdecl
|
|
main( int argc, char **argv )
|
|
{
|
|
BYTE buffer[32];
|
|
HANDLE volumeHandle;
|
|
STRING string;
|
|
UNICODE_STRING unicodeString;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
NTSTATUS ntStatus;
|
|
IO_STATUS_BLOCK statusBlock;
|
|
ULONG portNumber = 0;
|
|
PSCSI_ADAPTER_BUS_INFO adapterInfo;
|
|
PSCSI_BUS_DATA busData;
|
|
PSCSI_INQUIRY_DATA inquiryData;
|
|
UCHAR prevDeviceInquiryData[INQUIRYDATABUFFERSIZE];
|
|
PINQUIRYDATA deviceInquiryData;
|
|
ULONG bytesTransferred, i, j;
|
|
ULONG deviceNumber;
|
|
BOOLEAN newDisk = FALSE;
|
|
BOOLEAN newCdrom = FALSE;
|
|
UCHAR prevPathId;
|
|
UCHAR prevTargetId;
|
|
UCHAR prevLun;
|
|
BOOLEAN prevDeviceClaimed;
|
|
BOOLEAN listAdapters = FALSE;
|
|
BOOLEAN allAdapters = TRUE;
|
|
UCHAR lunExtra;
|
|
|
|
if(argc == 2) {
|
|
if(argv[1][0] == '*') {
|
|
listAdapters = TRUE;
|
|
} else {
|
|
portNumber = atoi(argv[1]);
|
|
allAdapters = FALSE;
|
|
}
|
|
}
|
|
|
|
printf("\nWindows NT SCSI Bus Rescan Version 1.1\n");
|
|
|
|
if(listAdapters) {
|
|
printf("[only listing adapters]\n");
|
|
} else if(allAdapters) {
|
|
printf("[scanning all adapters]\n");
|
|
} else {
|
|
printf("[scanning adapter %d only]\n", portNumber);
|
|
}
|
|
|
|
while (TRUE) {
|
|
|
|
memset( buffer, 0, sizeof( buffer ) );
|
|
sprintf( buffer,
|
|
"\\\\.\\Scsi%d:",
|
|
portNumber);
|
|
|
|
//
|
|
// Open the volume with the DOS name.
|
|
//
|
|
|
|
volumeHandle = CreateFile( buffer,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
0 );
|
|
|
|
if( volumeHandle == INVALID_HANDLE_VALUE ) {
|
|
break;
|
|
}
|
|
|
|
if(listAdapters) {
|
|
GetDriverName(portNumber);
|
|
portNumber++;
|
|
CloseHandle(volumeHandle);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Issue rescan device control.
|
|
//
|
|
|
|
if( !DeviceIoControl( volumeHandle,
|
|
IOCTL_SCSI_RESCAN_BUS,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&bytesTransferred,
|
|
NULL ) ) {
|
|
|
|
printf( "Rescan SCSI port %d failed [Error %d].\n", portNumber, GetLastError() );
|
|
CloseHandle( volumeHandle );
|
|
exit(4);
|
|
}
|
|
|
|
//
|
|
// Get a big chuck of memory to store the SCSI bus data.
|
|
//
|
|
|
|
adapterInfo = malloc( 0x1000 );
|
|
|
|
if (adapterInfo == NULL) {
|
|
printf( "Can't allocate memory for bus data\n" );
|
|
CloseHandle( volumeHandle );
|
|
exit(4);
|
|
}
|
|
|
|
//
|
|
// Issue device control to get configuration information.
|
|
//
|
|
|
|
if (!DeviceIoControl( volumeHandle,
|
|
IOCTL_SCSI_GET_INQUIRY_DATA,
|
|
NULL,
|
|
0,
|
|
adapterInfo,
|
|
0x1000,
|
|
&bytesTransferred,
|
|
NULL)) {
|
|
|
|
printf( "Get SCSI bus data failed [Error %d].\n", GetLastError() );
|
|
CloseHandle( volumeHandle );
|
|
exit(4);
|
|
}
|
|
|
|
GetDriverName(portNumber);
|
|
|
|
//
|
|
// Display devices on buses.
|
|
//
|
|
|
|
for (i=0; i < adapterInfo->NumberOfBuses; i++) {
|
|
|
|
busData = &adapterInfo->BusData[i];
|
|
printf( "\nBus TID LUN In use Type Vendor FW Rev Advanced SCSI\n" );
|
|
printf( "===============================================================================\n" );
|
|
printf("%2d %2d %2d %2d Initiator",
|
|
i,
|
|
busData->InitiatorBusId & 0x7,
|
|
0,
|
|
1);
|
|
|
|
inquiryData =
|
|
(PSCSI_INQUIRY_DATA)((PUCHAR)adapterInfo + busData->InquiryDataOffset);
|
|
|
|
memset(&prevDeviceInquiryData, 0, INQUIRYDATABUFFERSIZE);
|
|
prevPathId = 0xFF;
|
|
prevTargetId = 0xFF;
|
|
prevLun = 0xFF;
|
|
prevDeviceClaimed = 0xFF;
|
|
for (j=0; j<busData->NumberOfLogicalUnits; j++) {
|
|
|
|
int k;
|
|
|
|
//
|
|
// Make sure VendorId string is null terminated.
|
|
//
|
|
|
|
deviceInquiryData = (PINQUIRYDATA)&inquiryData->InquiryData[0];
|
|
|
|
deviceInquiryData->VendorSpecific[0] = '\0';
|
|
if (prevPathId != inquiryData->PathId ||
|
|
prevTargetId != inquiryData->TargetId ||
|
|
prevLun != (inquiryData->Lun-1) ||
|
|
prevDeviceClaimed != inquiryData->DeviceClaimed ||
|
|
memcmp( &prevDeviceInquiryData, deviceInquiryData, INQUIRYDATABUFFERSIZE)
|
|
) {
|
|
lunExtra = 0;
|
|
printf("\n%2d %2d %2d %2d ",
|
|
inquiryData->PathId,
|
|
inquiryData->TargetId,
|
|
inquiryData->Lun,
|
|
inquiryData->DeviceClaimed);
|
|
} else {
|
|
lunExtra += 1;
|
|
printf("\r%2d %2d %2d-%1d %2d ",
|
|
inquiryData->PathId,
|
|
inquiryData->TargetId,
|
|
inquiryData->Lun-lunExtra,
|
|
inquiryData->Lun,
|
|
inquiryData->DeviceClaimed);
|
|
}
|
|
|
|
prevPathId = inquiryData->PathId;
|
|
prevTargetId = inquiryData->TargetId;
|
|
prevLun = inquiryData->Lun;
|
|
prevDeviceClaimed = inquiryData->DeviceClaimed;
|
|
memmove( &prevDeviceInquiryData, deviceInquiryData, INQUIRYDATABUFFERSIZE);
|
|
|
|
//
|
|
// Determine the perpherial type.
|
|
//
|
|
|
|
switch (deviceInquiryData->DeviceType) {
|
|
case DIRECT_ACCESS_DEVICE:
|
|
if (!inquiryData->DeviceClaimed) {
|
|
newDisk = TRUE;
|
|
}
|
|
printf("Disk Drive ");
|
|
break;
|
|
|
|
case SEQUENTIAL_ACCESS_DEVICE:
|
|
printf("Tape Drive ");
|
|
break;
|
|
|
|
case PRINTER_DEVICE:
|
|
printf("Printer ");
|
|
break;
|
|
|
|
case WRITE_ONCE_READ_MULTIPLE_DEVICE:
|
|
printf("Worm Drive ");
|
|
break;
|
|
|
|
case READ_ONLY_DIRECT_ACCESS_DEVICE:
|
|
if (!inquiryData->DeviceClaimed) {
|
|
newCdrom = TRUE;
|
|
}
|
|
printf("CdRom Drive");
|
|
break;
|
|
|
|
case SCANNER_DEVICE:
|
|
printf("Scanner ");
|
|
break;
|
|
|
|
case OPTICAL_DEVICE:
|
|
if (!inquiryData->DeviceClaimed) {
|
|
newDisk = TRUE;
|
|
}
|
|
printf("OpticalDisk");
|
|
break;
|
|
|
|
case MEDIUM_CHANGER:
|
|
printf("MediumChanger");
|
|
break;
|
|
|
|
case COMMUNICATION_DEVICE:
|
|
printf("Communication");
|
|
break;
|
|
|
|
default:
|
|
printf("OtherPeripheral");
|
|
}
|
|
|
|
//
|
|
// Display product information.
|
|
//
|
|
|
|
printf(" %s", deviceInquiryData->VendorId);
|
|
|
|
//
|
|
// Display SCSI capabilities.
|
|
//
|
|
|
|
printf(" ");
|
|
if (deviceInquiryData->Synchronous) {
|
|
printf(" SN");
|
|
}
|
|
|
|
if (deviceInquiryData->CommandQueue) {
|
|
printf(" CQ");
|
|
}
|
|
|
|
if (deviceInquiryData->Wide16Bit) {
|
|
printf(" W16");
|
|
}
|
|
|
|
if (deviceInquiryData->Wide32Bit) {
|
|
printf(" W32");
|
|
}
|
|
|
|
if (deviceInquiryData->SoftReset) {
|
|
printf(" SR");
|
|
}
|
|
|
|
if (deviceInquiryData->LinkedCommands) {
|
|
printf(" LC");
|
|
}
|
|
|
|
if (deviceInquiryData->RelativeAddressing) {
|
|
printf(" RA");
|
|
}
|
|
|
|
if (deviceInquiryData->DeviceTypeQualifier != DEVICE_QUALIFIER_ACTIVE) {
|
|
printf(" DQ%d", deviceInquiryData->DeviceTypeQualifier);
|
|
}
|
|
|
|
printf("\n [ ");
|
|
for(k = 0; k < 8; k++) {
|
|
printf("%02x ", ((PUCHAR) deviceInquiryData)[k]);
|
|
}
|
|
printf("]");
|
|
|
|
//
|
|
// Get next device data.
|
|
//
|
|
|
|
inquiryData =
|
|
(PSCSI_INQUIRY_DATA)((PUCHAR)adapterInfo + inquiryData->NextInquiryDataOffset);
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
free (adapterInfo);
|
|
|
|
if(allAdapters) {
|
|
CloseHandle( volumeHandle );
|
|
portNumber++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (newDisk) {
|
|
|
|
//
|
|
// Send IOCTL_DISK_FIND_NEW_DEVICES commands to each existing disk.
|
|
//
|
|
|
|
deviceNumber = 0;
|
|
while (TRUE) {
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
sprintf(buffer,
|
|
"\\Device\\Harddisk%d\\Partition0",
|
|
deviceNumber);
|
|
|
|
RtlInitString(&string,
|
|
buffer);
|
|
|
|
ntStatus = RtlAnsiStringToUnicodeString(&unicodeString,
|
|
&string,
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
continue;
|
|
}
|
|
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&unicodeString,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
ntStatus = NtOpenFile(&volumeHandle,
|
|
FILE_READ_DATA |
|
|
FILE_WRITE_DATA |
|
|
SYNCHRONIZE,
|
|
&objectAttributes,
|
|
&statusBlock,
|
|
FILE_SHARE_READ |
|
|
FILE_SHARE_WRITE,
|
|
FILE_SYNCHRONOUS_IO_ALERT);
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Issue find device device control.
|
|
//
|
|
|
|
if (DeviceIoControl( volumeHandle,
|
|
IOCTL_DISK_FIND_NEW_DEVICES,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&bytesTransferred,
|
|
NULL ) ) {
|
|
|
|
printf( "Found new disk (%d)\n", deviceNumber );
|
|
}
|
|
|
|
CloseHandle( volumeHandle );
|
|
deviceNumber++;
|
|
}
|
|
}
|
|
|
|
if (newCdrom) {
|
|
|
|
//
|
|
// Send IOCTL_CDROM_FIND_NEW_DEVICES commands to each existing cdrom.
|
|
//
|
|
|
|
deviceNumber = 0;
|
|
while (TRUE) {
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
sprintf(buffer,
|
|
"\\Device\\Cdrom%d",
|
|
deviceNumber);
|
|
|
|
RtlInitString(&string,
|
|
buffer);
|
|
|
|
ntStatus = RtlAnsiStringToUnicodeString(&unicodeString,
|
|
&string,
|
|
TRUE);
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
continue;
|
|
}
|
|
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&unicodeString,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
ntStatus = NtOpenFile(&volumeHandle,
|
|
FILE_READ_DATA |
|
|
FILE_WRITE_DATA |
|
|
SYNCHRONIZE,
|
|
&objectAttributes,
|
|
&statusBlock,
|
|
FILE_SHARE_READ |
|
|
FILE_SHARE_WRITE,
|
|
FILE_SYNCHRONOUS_IO_ALERT);
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Issue find device device control.
|
|
//
|
|
|
|
if (DeviceIoControl( volumeHandle,
|
|
IOCTL_CDROM_FIND_NEW_DEVICES,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&bytesTransferred,
|
|
NULL ) ) {
|
|
|
|
printf( "Found new cdrom (%d)\n", deviceNumber );
|
|
}
|
|
|
|
CloseHandle( volumeHandle );
|
|
deviceNumber++;
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|