⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 使用ASPI控制CDROM旋转速度的程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:

void __fastcall TMainWindow::FormCreate(TObject *Sender)
{
//if "-debug" was specified in the command line, or shift was
// held down as the program was run, turn on logging and indicate
// debug mode by changing the label at the bottom of the form
if( !strcmp(CommandLineGlobal.c_str(), "-debug") || isKeyDown( VK_SHIFT ) )
  {
  LOG = true;
  DebugLabel->Caption = "DEBUG";
  }
else
  LOG = false;

log( "-----------" );

char buffer[50];
DWORD dwStatus;

//Load the Win32 ASPI DLL
ASPIDLL = LoadLibrary("wnaspi32.dll");

//if there was an error loading the DLL, bail out
if( ASPIDLL == NULL )
  {
  Application->MessageBox( "Couldn't load wnaspi32.dll; make sure ASPI is properly installed", "Error - Must Quit", MB_OK );
  log( "ERROR - wnaspi32.dll failed to load" );
  Application->Terminate();
  }
else log( "Loaded wnaspi32.dll OK" );

//Get the addresses of the two DLL functions I'll be using
(FARPROC)gpfnGetASPI32SupportInfo = GetProcAddress( ASPIDLL, "GetASPI32SupportInfo" );
if( gpfnGetASPI32SupportInfo == NULL )
  {
  Application->MessageBox( "Couldn't get proc address of GetASPI32SupportInfo", "Error - Must Quit", MB_OK );
  log( "ERROR - Couldn't get proc address of GetASPI32SupportInfo" );
  Application->Terminate();
  }
else log( "Got GetASPI32SupportInfo proc address OK" );

(FARPROC)gpfnSendASPI32Command = GetProcAddress( ASPIDLL, "SendASPI32Command" );
if( gpfnSendASPI32Command == NULL )
  {
  Application->MessageBox( "Couldn't get proc address of SendASPI32Command", "Error - Must Quit", MB_OK );
  log( "ERROR - Couldn't get proc address of SendASPI32Command" );
  Application->Terminate();
  }
else log( "Got SendASPI32Command proc address OK" );

//Figure out how many host adapters are in the machine:
//Call gpfnGetASPI32SupportInfo(), which returns a DWORD.
// -The high byte of the low word shall be filled with
//  an ASPI status code.
// -If this code is SS_COMP, at least one host adapter was
//  found, and the number of host adapters is stored in
//  the low byte of the low word.
// -If this code is SS_NO_ADAPTERS, no host adapters were found
// -If this code is anything else, the function has failed and
//  this is an error code
DWORD dwSupportInfo;
dwSupportInfo = gpfnGetASPI32SupportInfo();
BYTE byASPIStatus = HIBYTE(LOWORD(dwSupportInfo));
if( SS_COMP == byASPIStatus )
  {
  gbyHostAdapterCount = LOBYTE(LOWORD(dwSupportInfo));

  sprintf( buffer, "Found %d Host Adapter(s)", gbyHostAdapterCount );
  log( buffer );
  }
else if( SS_NO_ADAPTERS == byASPIStatus )
  {
  Application->MessageBox( "ASPI reported 0 host adapters", "Error - Must Quit", MB_OK );
  log( "ERROR - ASPI reported 0 host adapters" );
  Application->Terminate();
  }
else
  {
  Application->MessageBox( ((AnsiString)"Error calling GetASPI32SupportInfo: " + LookupASPIStatus(byASPIStatus)).c_str(), "Error - Must Quit", MB_OK );
  log( ((AnsiString)"Error calling GetASPI32SupportInfo: " + LookupASPIStatus(byASPIStatus)).c_str() );
  Application->Terminate();
  }

//Figure out how many CD drives are in the system:
//-Add the name of each drive found to the CdromsCombo control
//-Add the host adapter and target number of each drive
// to the gDriveInfoList
gDriveInfoList = new TList;
SRB_GDEVBlock srbGDEVBlock;
for( BYTE j = 0; j < gbyHostAdapterCount; j++ )
  {
  for( BYTE i = 0; i < MAX_SCSI_TARGETS; i++ )
    {
    memset( &srbGDEVBlock, 0, sizeof(SRB_GDEVBlock) );
    srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
    srbGDEVBlock.SRB_Target = i;
    srbGDEVBlock.SRB_HaId = j;
    gpfnSendASPI32Command( (LPSRB)&srbGDEVBlock );

    //if the i'th target on the j'th host adapter is a CD-Rom . . .
    if( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM )
       {
       //if this is the first CD-Rom found . . .
       if( CdromsCombo->Items->Count == 0 )
           {
           //make this HA and CD drive the current settings
           gbyCurrentHostAdapter = j;
           gbyCurrentTarget = i;
           }
       //add its descriptive string to the combo
       char buffer[50];
       dwStatus = getDriveName( j, i, buffer );

       //display a warning if there was a problem getting the drive name
       if( dwStatus != SS_COMP)
         {
         if( IDCANCEL == Application->MessageBox( ((AnsiString)("getDriveName returned " + LookupASPIStatus( (BYTE)dwStatus )) + (AnsiString)"\r\n\nYou may try to continue by pressing OK, or\r\nTerminate the program with CANCEL").c_str(), "Error", MB_OKCANCEL ) )
           Application->Terminate();
         }

       log( ((AnsiString)"Found CD-ROM " +
             (AnsiString)buffer +
             (AnsiString)": HA " +
             (AnsiString)j +
             (AnsiString)" Target " +
             (AnsiString)i ).c_str() );

       CdromsCombo->Items->Add( buffer );

       //add its HA and target number to the gDriveInfoList
       DriveInfo* DI = new DriveInfo;
       DI->HostAdapter = j;
       DI->Target = i;
       gDriveInfoList->Add( DI );
       }
    }
  }

//if no CD-ROM drives were found, bail out
if( CdromsCombo->Items->Count == 0 )
  {
  Application->MessageBox( "No CD-ROM drives found by ASPI", "Error - Must Quit", MB_OK );
  log( "ERROR - No CD-ROM drives found by ASPI" );
  Application->Terminate();
  }

//make the first drive in the combo be the one initially displayed
CdromsCombo->ItemIndex = 0;

//fill up the spindown times combo with all
// standard spindown times
SpindownTimesCombo->Items->Add("125 ms");
SpindownTimesCombo->Items->Add("250 ms");
SpindownTimesCombo->Items->Add("500 ms");
SpindownTimesCombo->Items->Add("1 s");
SpindownTimesCombo->Items->Add("2 s");
SpindownTimesCombo->Items->Add("4 s");
SpindownTimesCombo->Items->Add("8 s");
SpindownTimesCombo->Items->Add("16 s");
SpindownTimesCombo->Items->Add("32 s");
SpindownTimesCombo->Items->Add("1 min");
SpindownTimesCombo->Items->Add("2 min");
SpindownTimesCombo->Items->Add("4 min");
SpindownTimesCombo->Items->Add("8 min");
SpindownTimesCombo->Items->Add("16 min");
SpindownTimesCombo->Items->Add("32 min");

//make it so that all spindown times are visible at once
// when the combo box is dropped down
SpindownTimesCombo->DropDownCount = SpindownTimesCombo->Items->Count;

TRegistry* reg = new TRegistry;
//if the CD-ROM Tool registry key exists
if( reg->KeyExists( "\\Software\\Naiobrin Software\\CD-ROM Tool" ) )
  {
  //open the CD-ROM Tool registry key
  reg->OpenKey( "\\Software\\Naiobrin Software\\CD-ROM Tool", false );
  //read the tolerance
  ToleranceEdit->Text = (AnsiString)reg->ReadInteger( "Tolerance" );
  }
delete reg;

//update the speed & timeout reading as well as the speed
// choices to reflect the selected drive's current settings and
// capabilities
RefreshItems();
}
//---------------------------------------------------------------------------

void __fastcall TMainWindow::FormDestroy(TObject *Sender)
{
TRegistry* reg = new TRegistry;
//create or open the CD-ROM Tool registry key
reg->OpenKey( "\\Software\\Naiobrin Software\\CD-ROM Tool", true );
//write the tolerance
reg->WriteInteger( "Tolerance", ToleranceEdit->Text.ToInt() );
delete reg;

//Free memory allocated by gDriveInfoList and its elements
for( int i = 0; i < gDriveInfoList->Count; i++ )
  delete gDriveInfoList->Items[i];
delete gDriveInfoList;

//Clean up after DLL
if( FreeLibrary( ASPIDLL ) != 0 )
  log( "Freed wnaspi32.dll OK" );
else log( "Error freeing wnaspi32.dll" );
}
//---------------------------------------------------------------------------


void __fastcall TMainWindow::RefreshItems()
{
ModeSenseDump();

log( ((AnsiString)"RefreshItems feedback for HA " +
     (AnsiString)gbyCurrentHostAdapter +
     (AnsiString)" Target " +
     (AnsiString)gbyCurrentTarget).c_str() );

//find maximum and current speed, set the labels accordingly
Label22->Caption = "Maximum Speed: " + (AnsiString)LookupX( getMAXCDSpeed() ) + (AnsiString)"x";
log( ((AnsiString)"Maximum Speed: " +
      (AnsiString)getMAXCDSpeed()).c_str() );
Label21->Caption = "Current Speed: " + (AnsiString)LookupX( getCDSpeed() ) + (AnsiString)"x";
log( ((AnsiString)"Current Speed: " +
      (AnsiString)getCDSpeed()).c_str() );

//find the current spindown time, set the label accordingly
Label23->Caption = "Current Time: " + LookupSpindownText( getCDSpindown() );
log( Label23->Caption.c_str() );

//if current time was set to VS, indicate in the popup hint that this means Vendor Specific
Label23->ShowHint = false;
if( Label23->Caption == "Current Time: VS" )
  Label23->ShowHint = true;

//clear the possible speed settings pulldown box
PossibleSpeedsCombo->Clear();

//set up the progress bar (this'll show progress made in determining
// the possible read speeds of the drive)
ProgressBar->Min = 0;
ProgressBar->Max = LookupX(getMAXCDSpeed());

//If LookupKB([some X rating]) returns a positive integer, then
// it was able to find a transfer rate in Kilobytes corresponding
// to that X rating for this particular drive.  Thus, I can
// determine which X speeds are supported by this drive by testing
// LookupKB with each X value between 1x and [MAX]x.
int MAX_X = LookupX(getMAXCDSpeed());
for( int i = 1; i <= MAX_X; i++ )
  {
  log( ((AnsiString)"Trying " +
        (AnsiString)i +
        (AnsiString)"x").c_str() );

  if( LookupKB(i) > 0 )
     PossibleSpeedsCombo->Items->Add( (AnsiString)i + "x" );
  ProgressBar->Position++;
  }

//if none of the tests was successful, I can assume that either the
// tolerance value is set too low (see LookupKB) or, more likely, the drive's speed
// is locked.  In any case, put a dash item in the combo box to
// indicate this.
if( PossibleSpeedsCombo->Items->Count == 0 )
  PossibleSpeedsCombo->Items->Add( "-" );

log( (PossibleSpeedsCombo->Items->CommaText +
      (AnsiString)" were found to be possible speeds").c_str() );

//reset the progress bar to zero
ProgressBar->Position = 0;

//set the combo box containing the possible speeds to show
// the drive's current speed
for( int i = 0; i < PossibleSpeedsCombo->Items->Count; i++ )
  if( PossibleSpeedsCombo->Items->Strings[i] == (AnsiString)LookupX(getCDSpeed())+(AnsiString)"x" )
     PossibleSpeedsCombo->ItemIndex = i;

//set the combo box containing spindown times to show
// the drive's current spindown time
for( int i = 0; i < SpindownTimesCombo->Items->Count; i++ )
  if( SpindownTimesCombo->Items->Strings[i] == LookupSpindownText(getCDSpindown()) )
     SpindownTimesCombo->ItemIndex = i;
}

void __fastcall TMainWindow::PossibleSpeedsComboChange(TObject *Sender)
{
//extract the integer value from the combo box item
// selected(which has the form "[integer]x"):
//1)put the selected combo box item in an AnsiString variable
//2)trim off the last character
//
//This leaves me with an AnsiString containing an integer value
AnsiString SelectedItem = PossibleSpeedsCombo->Items->Strings[ PossibleSpeedsCombo->ItemIndex ];
SelectedItem = SelectedItem.SubString( 1, SelectedItem.Length()-1 );

//set new speed for the current drive
setCDSpeed( LookupKB(SelectedItem.ToInt()) );

//update the current speed text
Label21->Caption = "Current Speed: " + (AnsiString)LookupX( getCDSpeed() ) + (AnsiString)"x";
}
//---------------------------------------------------------------------------

void __fastcall TMainWindow::SpindownTimesComboChange(TObject *Sender)
{
//set new spindown time for the current drive
setCDSpindown( LookupSpindownCode(SpindownTimesCombo->Items->Strings[ SpindownTimesCombo->ItemIndex ]) );

//update the current time text
Label23->Caption = "Current Time: " + LookupSpindownText( getCDSpindown() );
}
//---------------------------------------------------------------------------

void __fastcall TMainWindow::CdromsComboChange(TObject *Sender)
{
//set current host adapter & target to reflect the
// drive that was selected in the CdromsCombo
gbyCurrentHostAdapter = ((DriveInfo*)(gDriveInfoList->Items[CdromsCombo->ItemIndex]))->HostAdapter;
gbyCurrentTarget = ((DriveInfo*)(gDriveInfoList->Items[CdromsCombo->ItemIndex]))->Target;

//update the speed & timeout reading as well as the speed
// choices to reflect the selected drive's current settings and
// capabilities
RefreshItems();
}
//---------------------------------------------------------------------------








void __fastcall TMainWindow::AboutButtonClick(TObject *Sender)
{
AboutWindow->ShowModal();
}
//---------------------------------------------------------------------------

void __fastcall TMainWindow::Button1Click(TObject *Sender)
{
setCDSpeed( 0 );
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -