Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

947 lines
24 KiB

#include <windows.h>
#include <winioctl.h>
#include <ntddscsi.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "modesel.h"
/*
* This program was written initially by M. Calligaro for entirely
* different purposes. Mistreated by A. Forin and M. Lucovsky.
* None of the above thinks this code should look like this.
*/
VOID
main(
int argc,
char *argv[]
)
{
SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
DWORD accessMode,
shareMode;
HANDLE fileHandle;
UCHAR string[25];
UCHAR szDriveNum[4];
ULONG errorCode;
BOOLEAN changeSet = FALSE;
ULONG i;
ULONG driveNumber,
sensePage,
senseValues,
saveAction;
UCHAR changeBits[0x24];
ULONG pageLength;
if (argc > 4 || (argc > 1 && argv[1][0] == '?')) {
printf("Usage: %s [ModePage [Action [WhichValues]]]\n", argv[0] );
return;
}
shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; // default
accessMode = GENERIC_WRITE | GENERIC_READ; // default
printf("\nWindows NT SCSI Mode Sense and Select Utility\n");
selectDisk:
printf("\n");
for (i=0;;i++) {
sprintf(string, "\\\\.\\PhysicalDrive%d", i);
fileHandle = CreateFile(string,
accessMode,
shareMode,
NULL,
OPEN_EXISTING,
0,
NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
if (i == 0) {
printf("Error opening PhysicalDrive0. Error: %d\n",
errorCode = GetLastError());
PrintError(errorCode);
return;
} else {
break;
}
} else {
printf("Disk %d is a ", i);
DoInquiry(&sptwb, fileHandle);
printf("at SCSI ID %d\n", sptwb.spt.TargetId);
CloseHandle(fileHandle);
}
}
printf("Enter '99' to exit program\n\n");
while (TRUE) {
printf("Which disk(0-%d)? ", i-1);
scanf("%d", &driveNumber);
if ((driveNumber >= 0) && (driveNumber < i)) {
break;
} else if (driveNumber == 99) {
exit(0);
} else {
printf("There is no disk %d\n",driveNumber);
}
}
newPage:
printf("\n");
printf(" 0:Unit Attention Page\n");
printf(" 1:Error Recovery Page\n");
printf(" 2:Disconnect Page\n");
printf(" 3:Format Device Page\n");
printf(" 4:Rigid Geometry Page\n");
printf(" 5:Flexible Page\n");
printf(" 7:Verify Error Page\n");
printf(" 8:Caching Page\n");
printf(" 9:Peripheral Page\n");
printf("10:Control Page\n");
printf("11:Medium Types Page\n");
printf("12:Notch Partition Page\n");
printf("15:Data Compression Page\n");
printf("16:Device Configuration Page\n");
printf("17:Medium Partition Page\n");
printf("99:Select disk\n");
printf("\nWhich page? ");
scanf("%d", &sensePage);
if (sensePage > 17) {
goto selectDisk;
}
printf("\n0:Get current values\n");
printf("1:Get default values\n");
printf("2:Get saved values\n");
printf("3:Get changable values\n");
if (sensePage == 8) {
printf("4:Enable write cache\n");
printf("5:Disable write cache\n");
}
printf("99:New page\n");
printf("\nWhat action? ");
scanf("%d", &senseValues);
if (senseValues > 5 ||
(sensePage != 8 && senseValues >3)) {
goto newPage;
}
strcpy(string,"\\\\.\\PhysicalDrive");
sprintf(szDriveNum, "%d",driveNumber);
strcat(string,szDriveNum);
fileHandle = CreateFile(string,
accessMode,
shareMode,
NULL,
OPEN_EXISTING,
0,
NULL);
printf("\nMode Sense ");
switch (sensePage) {
case 0:
printf("Unit Attention Page ");
break;
case 1:
printf("Error Recovery Page ");
break;
case 2:
printf("Disconnect Page ");
break;
case 3:
printf("Format Device Page ");
break;
case 4:
printf("Rigid Geometry Page ");
break;
case 5:
printf("Flexible Page ");
break;
case 7:
printf("Verify Error Page ");
break;
case 8:
printf("Caching Page ");
break;
case 9:
printf("Peripheral Page ");
break;
case 10:
printf("Control Page ");
break;
case 11:
printf("Medium Types Page ");
break;
case 12:
printf("Notch Partition Page ");
break;
case 15:
printf("Data Compression Page ");
break;
case 16:
printf("Device Configuration Page ");
break;
case 17:
printf("Medium Partition Page ");
break;
default:
printf("Unknown Page ");
break;
}
switch (senseValues) {
case 0:
printf("(current values)\n");
DoModeSense(&sptwb, fileHandle, sensePage | MODE_SENSE_CURRENT_VALUES);
break;
case 1:
printf("(default values)\n");
DoModeSense(&sptwb, fileHandle, sensePage | MODE_SENSE_DEFAULT_VALUES);
break;
case 2:
printf("(saved values)\n");
DoModeSense(&sptwb, fileHandle, sensePage | MODE_SENSE_SAVED_VALUES);
break;
case 3:
printf("(changable values)\n");
DoModeSense(&sptwb, fileHandle, sensePage | MODE_SENSE_CHANGEABLE_VALUES);
memcpy(changeBits, sptwb.ucDataBuf, sptwb.ucDataBuf[4+1]);
pageLength = changeBits[4+1];
break;
case 4:
case 5:
goto cachePage;
default:
printf("(no values)\n");
break;
}
goto newPage;
cachePage:
//
// Get changable fields mask.
//
printf("(changable values)\n");
DoModeSense(&sptwb,
fileHandle,
sensePage | MODE_SENSE_CHANGEABLE_VALUES);
//
// Set up change mask.
//
memcpy(changeBits, sptwb.ucDataBuf, sptwb.ucDataBuf[4+1]);
pageLength = changeBits[4+1];
//
// Get current values.
//
printf("\nMode Sense Caching Page (old current values)\n");
DoModeSense(&sptwb, fileHandle, sensePage | MODE_SENSE_CURRENT_VALUES);
//
// Clear fields that can't be changed.
//
VerifyModePage(&sptwb.ucDataBuf[0], changeBits, pageLength);
//
// Set or clear write cache enable bit.
//
if (senseValues == 4)
sptwb.ucDataBuf[4 + 2] |= 0x4;
else
sptwb.ucDataBuf[4+2] &= ~0x4;
//
// Determine whether this change should be saved.
//
while (TRUE) {
printf("\n0:Do not save page\n");
printf("1:Save page\n");
printf("99:Select page\n");
printf("\nSave action? ");
scanf("%d", &saveAction);
if (saveAction == 99) {
goto newPage;
}
if (saveAction == 0 ||
saveAction == 1) {
break;
}
}
DoModeSelect(&sptwb,
fileHandle,
saveAction,
pageLength + 6);
//
// Get new current values.
//
printf("\nMode Sense Caching Page (new current values)\n");
DoModeSense(&sptwb, fileHandle, sensePage | MODE_SENSE_CURRENT_VALUES);
goto newPage;
}
BOOL SetDiscPage(PUCHAR dataBuffer, PUCHAR mask, ULONG pageLength)
{
if (((dataBuffer[4+0] & 0x3f) != MODE_PAGE_DISCONNECT) ||
dataBuffer[4+1] != 0x0e) {
return FALSE;
}
dataBuffer[4+2] = 0x80; /* buffer full ratio */
dataBuffer[4+3] = 0x80; /* buffer empty ratio */
VerifyModePage(dataBuffer, mask, pageLength);
return( TRUE);
}
BOOL EnableWriteCache(PUCHAR dataBuffer, ULONG onoff, PUCHAR mask, ULONG pageLength)
{
if (((dataBuffer[4+0] & 0x3f) != MODE_PAGE_CACHING) ||
dataBuffer[4+1] != pageLength) {
return FALSE;
}
return(TRUE);
}
BOOL VerifyModePage( PUCHAR dataBuffer, PUCHAR mask, ULONG length)
{
ULONG i;
/* reserved, mbz, no block descs */
dataBuffer[0] = dataBuffer[2] = dataBuffer[1] = dataBuffer[3] = 0;
/* Turn off what cannot be set back the way it was */
for (i = 0; i < length; i++)
dataBuffer[4+i] &= mask[4+i];
return TRUE;
}
VOID DoInquiry(PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb, HANDLE fileHandle)
{
ULONG length,
returned;
BOOLEAN status;
ZeroMemory(psptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
psptwb->spt.Length = sizeof(SCSI_PASS_THROUGH);
psptwb->spt.PathId = 0;
psptwb->spt.TargetId = 0; /* kernel fixes this */
psptwb->spt.Lun = 0;
psptwb->spt.CdbLength = CDB6GENERIC_LENGTH;
psptwb->spt.SenseInfoLength = 24;
psptwb->spt.DataIn = SCSI_IOCTL_DATA_IN;
psptwb->spt.DataTransferLength = 36;
psptwb->spt.TimeOutValue = 2;
psptwb->spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
psptwb->spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
psptwb->spt.Cdb[0] = SCSIOP_INQUIRY;
psptwb->spt.Cdb[1] = 0x0;
psptwb->spt.Cdb[2] = 0x0;
psptwb->spt.Cdb[3] = 0x0;
psptwb->spt.Cdb[4] = 36;
psptwb->spt.Cdb[5] = 0x0;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
psptwb->spt.DataTransferLength;
status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
psptwb,
sizeof(SCSI_PASS_THROUGH),
psptwb,
length,
&returned,
FALSE);
PrintInquiryStatusResults(status,returned,psptwb,length);
}
VOID
DisplayModeSenseData(
BOOLEAN status,
DWORD returned,
PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb,
ULONG length
)
{
ULONG errorCode;
ULONG count;
if (!status ) {
printf( "Error: %d ",
errorCode = GetLastError() );
PrintError(errorCode);
return;
}
if (psptwb->spt.ScsiStatus) {
PrintSenseInfo(psptwb);
return;
} else {
switch ((((PUCHAR)psptwb->ucDataBuf)[4] & 0x0F)) {
case MODE_PAGE_FORMAT_DEVICE:
{
PMODE_FORMAT_PAGE formatPage =
(PMODE_FORMAT_PAGE)(((PUCHAR)psptwb->ucDataBuf) +
sizeof(SCSI_MODE_HEADER));
printf("\nTracks per zone %x\n",
formatPage->TracksPerZone[1] |
formatPage->TracksPerZone[0] << 8);
printf("Alternate sectors per zone %x\n",
formatPage->AlternateSectorsPerZone[1] |
formatPage->AlternateSectorsPerZone[0] << 8);
printf("Alternate tracks per zone %x\n",
formatPage->AlternateTracksPerZone[1] |
formatPage->AlternateTracksPerZone[0] << 8);
printf("Alternate tracks per logical unit %x\n",
formatPage->AlternateTracksPerLogicalUnit[1] |
formatPage->AlternateTracksPerLogicalUnit[0] << 8);
printf("Sectors per track %x\n",
formatPage->SectorsPerTrack[1] |
formatPage->SectorsPerTrack[0] << 8);
printf("Data bytes per physical sector %x\n",
formatPage->BytesPerPhysicalSector[1] |
formatPage->BytesPerPhysicalSector[0] << 8);
printf("Interleave %x\n",
formatPage->Interleave[1] |
formatPage->Interleave[0] << 8);
printf("Track skew factor %x\n",
formatPage->TrackSkewFactor[1] |
formatPage->TrackSkewFactor[0] << 8);
printf("Cylinder skew factor %x\n",
formatPage->CylinderSkewFactor[1] |
formatPage->CylinderSkewFactor[0] << 8);
if (formatPage->SurfaceFirst) {
printf("Surface first ");
}
if (formatPage->RemovableMedia) {
printf("Removable media ");
}
if (formatPage->HardSectorFormating) {
printf("Hard sector formatting ");
}
if (formatPage->SoftSectorFormating) {
printf("Soft sector formatting ");
}
printf("\n\n");
break;
}
case MODE_PAGE_CACHING:
{
PMODE_CACHING_PAGE cachingPage =
(PMODE_CACHING_PAGE)(((PUCHAR)psptwb->ucDataBuf) +
sizeof(SCSI_MODE_HEADER));
if (cachingPage->PageSavable) {
printf("Page savable\n");
}
if (cachingPage->ReadDisableCache) {
printf("Read cache disabled\n");
} else {
printf("Read cache enabled\n");
}
if (cachingPage->WriteCacheEnable) {
printf("Write cache enabled\n");
} else {
printf("Write cache disabled\n");
}
if (cachingPage->MultiplicationFactor) {
printf("Multiplication factor\n");
}
break;
}
default:
printf("Bytes returned: %Xh, ",
psptwb->spt.ScsiStatus,returned);
printf("Data buffer length: %Xh\n\n\n",
psptwb->spt.DataTransferLength);
printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
printf(" ---------------------------------------------------------------\n");
for (count = 0;
count < length - offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
count++) {
if ((count) % 16 == 0) {
printf(" %03X ",count);
}
printf("%02X ", ((PUCHAR)psptwb->ucDataBuf)[count]);
if ((count+1) % 8 == 0) {
printf(" ");
}
if ((count+1) % 16 == 0) {
printf("\n");
}
}
printf("\n\n");
break;
} // end switch
} // end else
} // end DisplayModeSenseData()
VOID
DoModeSense(
PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb,
HANDLE fileHandle,
ULONG senseType)
{
ULONG length,
returned;
BOOLEAN status;
char *pt[4] = { "current", "changeable", "default", "saved" };
//printf("Here is a MODE SENSE to return Mode Page %d, %s values\n",
// senseType & 0x3f, pt[(senseType >> 6) & 0x3]);
ZeroMemory(psptwb,
sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
psptwb->spt.Length = sizeof(SCSI_PASS_THROUGH);
psptwb->spt.PathId = 0;
psptwb->spt.TargetId = 0; /* kernel fixes this */
psptwb->spt.Lun = 0;
psptwb->spt.CdbLength = CDB6GENERIC_LENGTH;
psptwb->spt.SenseInfoLength = 24;
psptwb->spt.DataIn = SCSI_IOCTL_DATA_IN;
psptwb->spt.DataTransferLength = 0x1c;
psptwb->spt.TimeOutValue = 2;
psptwb->spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
psptwb->spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
psptwb->spt.Cdb[0] = SCSIOP_MODE_SENSE;
psptwb->spt.Cdb[1] = MODE_SENSE_DISABLE_BLOCK_DESCRIPTORS;
psptwb->spt.Cdb[2] = (UCHAR)senseType;
psptwb->spt.Cdb[3] = 0x0;
psptwb->spt.Cdb[4] = 0x1c;
psptwb->spt.Cdb[5] = 0x0;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
psptwb->spt.DataTransferLength;
status = DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
psptwb,
sizeof(SCSI_PASS_THROUGH),
psptwb,
length,
&returned,
FALSE);
DisplayModeSenseData(status,returned,psptwb,length);
}
VOID
DoModeSelect(
PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb,
HANDLE fileHandle,
ULONG save,
ULONG datalength)
{
ULONG length,
returned;
psptwb->spt.Length = sizeof(SCSI_PASS_THROUGH);
psptwb->spt.PathId = 0;
psptwb->spt.TargetId = 0; /* kernel fixes this */
psptwb->spt.Lun = 0;
psptwb->spt.CdbLength = CDB6GENERIC_LENGTH;
psptwb->spt.SenseInfoLength = 26;
psptwb->spt.DataIn = SCSI_IOCTL_DATA_OUT;
psptwb->spt.DataTransferLength = datalength;
psptwb->spt.TimeOutValue = 2000;
psptwb->spt.DataBufferOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
psptwb->spt.SenseInfoOffset =
offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
psptwb->spt.Cdb[0] = SCSIOP_MODE_SELECT;
psptwb->spt.Cdb[1] = (UCHAR)save;
psptwb->spt.Cdb[2] = 0x0;
psptwb->spt.Cdb[3] = 0x0;
psptwb->spt.Cdb[4] = (UCHAR)datalength;
psptwb->spt.Cdb[5] = 0x0;
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
psptwb->spt.DataTransferLength;
DeviceIoControl(fileHandle,
IOCTL_SCSI_PASS_THROUGH,
psptwb,
length,
psptwb,
length,
&returned,
FALSE);
}
VOID
PrintError(ULONG ErrorCode)
{
UCHAR errorBuffer[80];
ULONG count;
count = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
ErrorCode,
0,
errorBuffer,
sizeof(errorBuffer),
NULL
);
if (count != 0) {
printf("%s\n", errorBuffer);
} else {
printf("Format message failed. Error: %d\n", GetLastError());
}
}
VOID
PrintInquiryStatusResults(
BOOLEAN status,DWORD returned,PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb,
ULONG length)
{
ULONG errorCode;
if (!status ) {
printf( "Error: %d ",
errorCode = GetLastError() );
PrintError(errorCode);
return;
}
if (psptwb->spt.ScsiStatus) {
PrintSenseInfo(psptwb);
return;
} else {
printf("%s", &psptwb->ucDataBuf[8]);
return;
PrintInquiryDataBuffer((PUCHAR)psptwb->ucDataBuf,
length - offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf));
}
}
VOID
PrintInquiryDataBuffer(PUCHAR DataBuffer, ULONG BufferLength)
{
char string[9];
printf("%s\n", &DataBuffer[8]);
return;
strncpy(string,&DataBuffer[8],8);
string[8]= '\0';
printf(" %s ",string);
strncpy(string,&DataBuffer[16],8);
string[8]= '\0';
printf("%s ",string);
strncpy(string,&DataBuffer[32],8);
string[8]= '\0';
printf("%s ",string);
}
VOID
PrintErrorStatus(
PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb
)
{
PrintError(GetLastError());
if (psptwb->spt.ScsiStatus) {
PrintSenseInfo(psptwb);
return;
}
}
VOID
PrintSenseInfo(PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb)
{
PSENSE_DATA senseBuffer = (PSENSE_DATA)psptwb->ucSenseBuf;
printf("SCSI request sense data\n");
if (psptwb->spt.SenseInfoLength == 0) {
printf("No sense data\n");
return;
}
printf("Error code is %x\n",
senseBuffer->ErrorCode);
printf("Sense key is %x\n",
senseBuffer->SenseKey);
printf("Additional sense code is %x\n",
senseBuffer->AdditionalSenseCode);
printf("Additional sense code qualifier is %x\n",
senseBuffer->AdditionalSenseCodeQualifier);
printf("\n\n");
switch (senseBuffer->SenseKey & 0xf) {
case SCSI_SENSE_NOT_READY:
printf("Device not ready\n");
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_LUN_NOT_READY:
printf("Lun not ready\n");
switch (senseBuffer->AdditionalSenseCodeQualifier) {
case SCSI_SENSEQ_BECOMING_READY:
printf("In process of becoming ready\n");
break;
case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:
printf("Manual intervention required\n");
break;
case SCSI_SENSEQ_FORMAT_IN_PROGRESS:
printf("Format in progress\n");
break;
case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:
default:
printf("Initializing command required\n");
break;
} // end switch (senseBuffer->AdditionalSenseCodeQualifier)
break;
case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
printf(" No Media in device.\n");
break;
} // end switch (senseBuffer->AdditionalSenseCode)
break;
case SCSI_SENSE_DATA_PROTECT:
printf("Media write protected\n");
break;
case SCSI_SENSE_MEDIUM_ERROR:
printf("Bad media\n");
break;
case SCSI_SENSE_HARDWARE_ERROR:
printf("Hardware error\n");
break;
case SCSI_SENSE_ILLEGAL_REQUEST:
printf("Illegal SCSI request\n");
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_ILLEGAL_COMMAND:
printf("Illegal command\n");
break;
case SCSI_ADSENSE_ILLEGAL_BLOCK:
printf("Illegal block address\n");
break;
case SCSI_ADSENSE_INVALID_LUN:
printf("Invalid LUN\n");
break;
case SCSI_ADSENSE_MUSIC_AREA:
printf("Music area\n");
break;
case SCSI_ADSENSE_DATA_AREA:
printf("Data area\n");
break;
case SCSI_ADSENSE_VOLUME_OVERFLOW:
printf("Volume overflow\n");
break;
case SCSI_ADSENSE_INVALID_CDB:
printf("Invalid field in CDB\n");
break;
} // end switch (senseBuffer->AdditionalSenseCode)
break;
case SCSI_SENSE_UNIT_ATTENTION:
switch (senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_MEDIUM_CHANGED:
printf("Media changed\n");
break;
case SCSI_ADSENSE_BUS_RESET:
printf("Bus reset\n");
break;
default:
printf("Unit attention\n");
break;
} // end switch (senseBuffer->AdditionalSenseCode)
break;
case SCSI_SENSE_ABORTED_COMMAND:
printf("Command aborted\n");
break;
case SCSI_SENSE_RECOVERED_ERROR:
printf("Recovered error\n");
switch(senseBuffer->AdditionalSenseCode) {
case SCSI_ADSENSE_SEEK_ERROR:
printf("Seek error\n");
break;
case SCSI_ADSENSE_TRACK_ERROR:
printf("Track error\n");
break;
case SCSI_ADSENSE_REC_DATA_NOECC:
printf("Recovered data - no ECC\n");
break;
case SCSI_ADSENSE_REC_DATA_ECC:
printf("Recovered data - ECC\n");
break;
default:
break;
} // end switch(senseBuffer->AdditionalSenseCode)
if (senseBuffer->IncorrectLength) {
printf("Incorrect length detected.\n");
}
break;
case SCSI_SENSE_NO_SENSE:
//
// Check other indicators.
//
if (senseBuffer->IncorrectLength) {
printf("Incorrect length detected.\n");
} else {
printf("No specific sense key\n");
}
break;
default:
printf("Unrecognized sense code\n");
break;
} // end switch (senseBuffer->SenseKey & 0xf)
}