| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /Renegade Setup/Autorun/CDCNTRL.CPP $*
- * *
- * $Author:: Maria_l $*
- * *
- * $Modtime:: 10/18/01 5:33p $*
- * *
- * $Revision:: 5 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * *
- * CDControlClass::Auto_Eject_Volume -- Eject the removable media *
- * CDControlClass::Auto_Eject_Volume_95 -- Eject the specified CD drive *
- * CDControlClass::CDControlClass -- Class constructor *
- * CDControlClass::Close_Removable_Volume -- Close the handle to a removable volume *
- * CDControlClass::Close_VWin32 -- Closes the handle opened by Open_VWin32. *
- * CDControlClass::Dismount_Volume -- Dismount the given volume *
- * CDControlClass::Eject_CD -- Force the CD drive to eject *
- * CDControlClass::Eject_CD_Win95 -- Eject the cd in the given drive *
- * CDControlClass::Force_CD_Eject -- Ppen the CD tray on the given drive *
- * CDControlClass::Lock_CD_Drive -- Lock the CD tray and prevent ejection *
- * CDControlClass::Lock_CD_Drive_95 -- Prevent the user from ejecting the cd in the given driv*
- * CDControlClass::Lock_CD_Tray -- Prevent CD ejection on the specified drive *
- * CDControlClass::Lock_Logical_Volume -- Take a lock on a logical volume *
- * CDControlClass::Lock_Volume -- Prevent access by other threads to a given volume *
- * CDControlClass::Lock_Volume_95 -- Locks removable media so that it can't be ejected *
- * CDControlClass::Open_Removable_Volume -- Fetch a handle to a removable drive *
- * CDControlClass::Open_VWin32 -- Opens a handle to VWIN32 to issue low-level disk I/O *
- * CDControlClass::Prevent_Removal_Of_Volume -- Disable the eject button on the given drive *
- * CDControlClass::Unlock_CD_Drive -- Unlock the CD tray and allow ejection *
- * CDControlClass::Unlock_CD_Drive_95 -- Allow the user to eject the cd in the given drive *
- * CDControlClass::Unlock_CD_Tray -- Allow CD ejection on the specified drive *
- * CDControlClass::Unlock_Logical_Volume -- Unlocks a logical volume *
- * CDControlClass::Unlock_Volume -- Allow access by other threads to a given volume *
- * CDControlClass::Unlock_Volume_95 -- Unlocks removable media so that it can be ejected *
- * CDControlClass::~CDControlClass -- Class destructor *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "assert.h"
- #include "cdcntrl.h"
- #include "winfix.h"
- #include "wnd_file.h"
- #pragma warning(disable : 4201)
- #include <winioctl.h>
- #include <tchar.h>
- #include <stdio.h>
- CDControlClass CDControl;
- void Last_Error_Text ( LPTSTR szPrefix, HRESULT hr );
- /***********************************************************************************************
- * CDControlClass::CDControlClass -- Class constructor *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 2:03AM ST : Created *
- *=============================================================================================*/
- CDControlClass::CDControlClass(void)
- {
- }
- /***********************************************************************************************
- * CDControlClass::~CDControlClass -- Class destructor *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 2:03AM ST : Created *
- *=============================================================================================*/
- CDControlClass::~CDControlClass(void)
- {
- }
- /***********************************************************************************************
- * CDControlClass::Force_CD_Eject -- Ppen the CD tray on the given drive *
- * *
- * INPUT: Drive number (0=a, 1=b etc) *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 1:17AM ST : Created *
- *=============================================================================================*/
- void CDControlClass::Force_CD_Eject(int drive)
- {
- if ( WinVersion.Is_Win9x() ) {
- Eject_CD_Win95(drive);
- }else{
- Eject_CD(drive);
- }
- }
- /***********************************************************************************************
- * CDControlClass::Lock_CD_Tray -- Prevent CD ejection on the specified drive *
- * *
- * INPUT: drive number (0=a: etc) *
- * *
- * OUTPUT: true if locked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 1:56AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Lock_CD_Tray (int drive)
- {
- if ( WinVersion.Is_Win9x() ) {
- return (Lock_CD_Drive_95(drive));
- }else{
- return (Lock_CD_Drive(drive));
- }
- }
- /***********************************************************************************************
- * CDControlClass::Unlock_CD_Tray -- Allow CD ejection on the specified drive *
- * *
- * INPUT: drive number (0=a: etc) *
- * *
- * OUTPUT: true if unlocked OK *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 1:57AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Unlock_CD_Tray (int drive)
- {
- if ( WinVersion.Is_Win9x() ) {
- return (Unlock_CD_Drive_95(drive));
- }else{
- return (Unlock_CD_Drive(drive));
- }
- }
- /***********************************************************************************************
- * CDControlClass::Open_Removable_Volume -- Fetch a handle to a removable drive *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:25PM ST : Created *
- *=============================================================================================*/
- HANDLE CDControlClass::Open_Removable_Volume( char drive )
- {
- assert (WinVersion.Is_WinNT());
- HANDLE volume;
- unsigned drivetype;
- char volume_name[8];
- char rootname[5];
- unsigned long access_flags;
- /*----------------------------------------------------------------------------------------
- ** Get the drive type to ensure that this is a removable volume.
- */
- _stprintf (rootname, _TEXT( "%c:\\" ), drive + 'A');
- drivetype = GetDriveType( rootname );
- switch( drivetype ) {
- case DRIVE_REMOVABLE:
- access_flags = GENERIC_READ | GENERIC_WRITE;
- break;
- case DRIVE_CDROM:
- access_flags = GENERIC_READ;
- break;
- default:
- // DebugString ("Attempt to open non-removable volume for locking or ejection\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("Attempt to open non-removable volume for locking or ejection" ));
- return( INVALID_HANDLE_VALUE );
- }
- /*----------------------------------------------------------------------------------------
- ** Get a handle to the volume.
- */
- _stprintf( volume_name, _TEXT( "\\\\.\\%c:" ), drive + 'A' );
- volume = CreateFile( volume_name, access_flags, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
- // assert (volume != INVALID_HANDLE_VALUE);
- if ( volume == INVALID_HANDLE_VALUE ) {
- // DebugString ("Unable to open drive %c: for ejection\n", drive + 'A');
- Msg( __LINE__, TEXT(__FILE__), TEXT("Unable to open drive %c: for ejection"), drive + 'A' - 1 );
- }
- return( volume );
- }
- /***********************************************************************************************
- * CDControlClass::Close_Removable_Volume -- Close the handle to a removable volume *
- * *
- * INPUT: HANDLE of volume to close *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:27PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Close_Removable_Volume(HANDLE volume)
- {
- assert (WinVersion.Is_WinNT());
- return ((CloseHandle(volume)) ? true : false);
- }
- /***********************************************************************************************
- * CDControlClass::Lock_Volume -- Prevent access by other threads to a given volume *
- * *
- * INPUT: HANDLE to volume *
- * *
- * OUTPUT: true if locked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:29PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Lock_Volume( HANDLE volume )
- {
- assert( WinVersion.Is_WinNT( ));
- unsigned long bytes_returned = 0;
- unsigned long sleep_amount = LOCK_TIMEOUT / LOCK_RETRIES;
- /*
- ** Do this in a loop until a timeout period has expired
- */
- for ( int trycount = 0; trycount < LOCK_RETRIES; trycount++ ) {
- if ( DeviceIoControl( volume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytes_returned, NULL )) {
- return( true );
- }
- // Msg( __LINE__, TEXT(__FILE__), TEXT("DeviceIoControl failed to lock volume. Error %d - %s"), GetLastError(), Last_Error_Text());
- Last_Error_Text( _TEXT( "DeviceIoControl failed to lock volume." ), GetLastError());
- // Sleep( sleep_amount );
- Sleep( LOCK_TIMEOUT );
- }
- return( false );
- }
- /***********************************************************************************************
- * CDControlClass::Unlock_Volume -- Allow access by other threads to a given volume *
- * *
- * INPUT: HANDLE to volume *
- * *
- * OUTPUT: true if unlocked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:29PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Unlock_Volume(HANDLE volume)
- {
- assert( WinVersion.Is_WinNT());
- unsigned long bytes_returned;
- unsigned long sleep_amount = LOCK_TIMEOUT / LOCK_RETRIES;
- /*
- ** Do this in a loop until a timeout period has expired
- */
- for ( int trycount = 0; trycount < LOCK_RETRIES; trycount++ ) {
- if ( DeviceIoControl( volume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &bytes_returned, NULL )) return( true );
- // DebugString ("DeviceIoControl failed to unlock volume. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to unlock volume. Error %d - %s", GetLastError(), Last_Error_Text());
- Last_Error_Text( _TEXT( "DeviceIoControl failed to unlock volume." ), GetLastError());
- // Sleep( sleep_amount );
- Sleep( LOCK_TIMEOUT );
- }
- return( false );
- }
- /***********************************************************************************************
- * CDControlClass::Dismount_Volume -- Dismount the given volume *
- * *
- * INPUT: HANDLE of volume to dismount *
- * *
- * OUTPUT: true if volume dismounted OK *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:31PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Dismount_Volume(HANDLE volume)
- {
- assert( WinVersion.Is_WinNT());
- unsigned long bytes_returned;
- bool result = ((DeviceIoControl( volume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &bytes_returned, NULL)) ? true : false );
- if (result == false) {
- // DebugString ("DeviceIoControl failed to dismount volume. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to dismount volume. Error %d - %s", GetLastError(), Last_Error_Text());
- Last_Error_Text( _TEXT( "DeviceIoControl failed to dismount volume." ), GetLastError());
- }
- return( result );
- }
- /***********************************************************************************************
- * CDControlClass::Prevent_Removal_Of_Volume -- Disable the eject button on the given drive *
- * *
- * INPUT: HANDLE of volume to enable/disable *
- * true to prevent removal. false to allow it. *
- * *
- * OUTPUT: true if status changed OK *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:32PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Prevent_Removal_Of_Volume( HANDLE volume, bool prevent )
- {
- assert( WinVersion.Is_WinNT());
- unsigned long bytes_returned;
- PREVENT_MEDIA_REMOVAL pmrbuffer;
-
- pmrbuffer.PreventMediaRemoval = prevent;
- bool result = ((DeviceIoControl( volume, IOCTL_STORAGE_MEDIA_REMOVAL, &pmrbuffer, sizeof(PREVENT_MEDIA_REMOVAL), NULL, 0, &bytes_returned, NULL)) ? true : false);
- if (result == false) {
- // DebugString ("DeviceIoControl failed to prevent media removal. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to prevent media removal. Error %d - %s", GetLastError(), Last_Error_Text());
- Last_Error_Text( _TEXT( "DeviceIoControl failed to prevent media removal." ), GetLastError());
- }
- return( result );
- }
- /***********************************************************************************************
- * CDControlClass::Auto_Eject_Volume -- Eject the removable media *
- * *
- * INPUT: HANDLE of volume to eject *
- * *
- * OUTPUT: true if ejection occured *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:34PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Auto_Eject_Volume(HANDLE volume)
- {
- assert (WinVersion.Is_WinNT());
- unsigned long bytes_returned;
- bool result = ((DeviceIoControl( volume, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &bytes_returned, NULL)) ? true : false);
- if (result == false) {
- // DebugString ("DeviceIoControl failed to eject media. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to eject media. Error %d - %s", GetLastError(), Last_Error_Text());
- Last_Error_Text( TEXT("DeviceIoControl failed to eject media."), GetLastError());
- }
- return (result);
- }
- /***********************************************************************************************
- * CDControlClass::Eject_CD -- Force the CD drive to eject *
- * *
- * INPUT: drive number *
- * *
- * OUTPUT: true if ejected *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/16/99 11:35PM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Eject_CD(char drive)
- {
- assert (WinVersion.Is_WinNT());
- HANDLE volume;
- bool ejected = false;
- volume = Open_Removable_Volume(drive);
- if (volume == INVALID_HANDLE_VALUE) return (false);
- /*
- ** Lock and dismount the volume.
- */
- if (Lock_Volume(volume) && Dismount_Volume(volume)) {
- /*
- ** Set prevent removal to false and eject the volume.
- */
- if (Prevent_Removal_Of_Volume(volume, false) && Auto_Eject_Volume(volume)) {
- ejected = true;
- }
- }
- /*
- ** Close the volume so other processes can use the drive.
- */
- Close_Removable_Volume(volume);
- return (ejected);
- }
- /***********************************************************************************************
- * CDControlClass::Lock_CD_Drive -- Lock the CD tray and prevent ejection *
- * *
- * INPUT: drive number *
- * *
- * OUTPUT: true if locked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:11AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Lock_CD_Drive(char drive)
- {
- assert (WinVersion.Is_WinNT());
- HANDLE volume;
- bool retval = false;
- volume = Open_Removable_Volume(drive);
- if (volume == INVALID_HANDLE_VALUE) return (false);
- /*
- ** Lock the volume.
- */
- if (Lock_Volume(volume)) {
- /*
- ** Set prevent removal to false
- */
- if (Prevent_Removal_Of_Volume(volume, true)) {
- retval = true;
- }
- }
- /*
- ** Close the volume so other processes can use the drive.
- */
- Unlock_Volume(volume);
- Close_Removable_Volume(volume);
- return (true);
- }
- /***********************************************************************************************
- * CDControlClass::Unlock_CD_Drive -- Unlock the CD tray and allow ejection *
- * *
- * INPUT: drive number *
- * *
- * OUTPUT: true if unlocked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:11AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Unlock_CD_Drive(char drive)
- {
- assert (WinVersion.Is_WinNT());
- HANDLE volume;
- bool retval = false;
- volume = Open_Removable_Volume(drive);
- if (volume == INVALID_HANDLE_VALUE) return (false);
- /*
- ** Lock the volume.
- */
- if (Lock_Volume(volume)) {
- /*
- ** Set prevent removal to false
- */
- if (Prevent_Removal_Of_Volume(volume, false)) {
- retval = true;
- }
- }
- /*
- ** Close the volume so other processes can use the drive.
- */
- Unlock_Volume(volume);
- Close_Removable_Volume(volume);
- return (true);
- }
- /***********************************************************************************************
- * CDControlClass::Eject_CD_Win95 -- Eject the cd in the given drive *
- * *
- * INPUT: drive. 0=a etc. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 1:04AM ST : Created *
- *=============================================================================================*/
- void CDControlClass::Eject_CD_Win95 (char drive)
- {
- assert (WinVersion.Is_Win9x());
- HANDLE vwin32 = INVALID_HANDLE_VALUE;
- drive++;
- vwin32 = Open_VWin32 ();
- assert (vwin32 != INVALID_HANDLE_VALUE);
- /*
- ** Make sure no other applications are using the drive.
- */
- bool drive_locked = Lock_Logical_Volume (vwin32, drive, 0, 0);
- // assert (drive_locked);
- if (!drive_locked) {
- // DebugString("Unable to lock volume %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Unable to lock volume %c: "), 'A' + drive - 1 );
- return;
- }
- /*
- ** Make sure there is no software lock keeping the media in the drive.
- */
- if (!Unlock_Volume_95 (vwin32, drive)) {
- // DebugString("Could not unlock media from drive %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Could not unlock media from drive %c: "), 'A' + drive - 1 );
- Unlock_Logical_Volume (vwin32, drive);
- return;
- }
- /*
- ** Eject!
- */
- if (!Auto_Eject_Volume_95 (vwin32, drive)) {
- // DebugString("Could not eject media from drive %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Could not eject media from drive %c: "), 'A' + drive - 1 );
- }
- Unlock_Logical_Volume (vwin32, drive);
- Close_VWin32 (vwin32);
- }
- /***********************************************************************************************
- * CDControlClass::Lock_CD_Drive_95 -- Prevent the user from ejecting the cd in the given drive*
- * *
- * INPUT: drive. 0=a etc. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 1:04AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Lock_CD_Drive_95 (char drive)
- {
- // DebugString ("CDControlClass::Lock_CD_Drive_95\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("CDControlClass::Lock_CD_Drive_95." ));
- bool retval = true;
- assert (WinVersion.Is_Win9x());
- HANDLE vwin32 = INVALID_HANDLE_VALUE;
- // DebugString ("Preventing ejection on CD drive %c\n", drive + 'A');
- Msg( __LINE__, TEXT(__FILE__), TEXT("Preventing ejection on CD drive %c: "), 'A' + drive -1 );
- drive++;
- vwin32 = Open_VWin32();
- assert (vwin32 != INVALID_HANDLE_VALUE);
- /*
- ** Make sure no other applications are using the drive.
- */
- // DebugString ("About to lock logical volume to enable exclusive access\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("About to lock logical volume to enable exclusive access." ));
- bool drive_locked = Lock_Logical_Volume (vwin32, drive, 0, 0);
- // assert (drive_locked);
- if (!drive_locked) {
- // DebugString("Unable to lock volume %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Unable to lock volume %c:"), 'A' + drive - 1 );
- return(false);
- }
- // DebugString ("Volume locked OK\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("Volume locked OK." ));
- /*
- ** Lock the tray in the closed position.
- */
- // DebugString ("About to prevent CD tray ejection\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("About to prevent CD tray ejection." ));
- if (!Lock_Volume_95 (vwin32, drive)) {
- // DebugString("Could not lock CD tray in drive %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Could not lock CD tray in drive %c:"), 'A' + drive - 1 );
- retval = false;
- }else{
- // DebugString ("CD tray ejection disabled OK\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("CD tray ejection disabled OK." ));
- }
- Unlock_Logical_Volume (vwin32, drive);
- Close_VWin32 (vwin32);
- // DebugString ("CDControlClass::Lock_CD_Drive_95 returning %s\n", retval ? "true" : "false");
- Msg( __LINE__, TEXT(__FILE__), TEXT("CDControlClass::Lock_CD_Drive_95 returning %s."), retval ? "true" : "false" );
- return (retval);
- }
- /***********************************************************************************************
- * CDControlClass::Unlock_CD_Drive_95 -- Allow the user to eject the cd in the given drive *
- * *
- * INPUT: drive. 0=a etc. *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 1:04AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Unlock_CD_Drive_95 (char drive)
- {
- // DebugString ("CDControlClass::Unlock_CD_Drive_95\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("CDControlClass::Unlock_CD_Drive_95 returning %s." ));
- bool retval = true;
- assert (WinVersion.Is_Win9x());
- HANDLE vwin32 = INVALID_HANDLE_VALUE;
- // DebugString ("Allowing ejection on CD drive %c\n", drive + 'A');
- Msg( __LINE__, TEXT(__FILE__), TEXT("Allowing ejection on CD drive %c."), drive + 'A' - 1 );
- drive++;
- vwin32 = Open_VWin32();
- assert (vwin32 != INVALID_HANDLE_VALUE);
- /*
- ** Make sure no other applications are using the drive.
- */
- // DebugString ("About to lock logical volume to enable exclusive access\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("About to lock logical volume to enable exclusive access." ));
- bool drive_locked = Lock_Logical_Volume (vwin32, drive, 0, 0);
- // assert (drive_locked);
- if (!drive_locked) {
- // DebugString("Unable to lock volume %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Unable to lock volume %c:."), 'A' + drive - 1 );
- return(false);
- }
- // DebugString ("Volume locked OK\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("Volume locked OK." ));
- /*
- ** Unlock the tray to allow ejection.
- */
- // DebugString ("About to allow CD tray ejection\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("About to allow CD tray ejection." ));
- if (!Unlock_Volume_95 (vwin32, drive)) {
- // DebugString("Could not unlock CD tray in drive %c:\n", 'A' + drive - 1);
- Msg( __LINE__, TEXT(__FILE__), TEXT("Could not unlock CD tray in drive %c:"), 'A' + drive - 1 );
- retval = false;
- }else{
- // DebugString ("CD tray ejection enabled OK\n");
- Msg( __LINE__, TEXT(__FILE__), TEXT("CD tray ejection enabled OK." ));
- }
- Unlock_Logical_Volume (vwin32, drive);
- Close_VWin32 (vwin32);
- // DebugString ("CDControlClass::Unlock_CD_Drive_95 returning %s\n", retval ? "true" : "false");
- Msg( __LINE__, TEXT(__FILE__), TEXT("CDControlClass::Unlock_CD_Drive_95 returning %s."), retval ? "true" : "false" );
- return (retval);
- }
- /***********************************************************************************************
- * CDControlClass::Unlock_Volume_95 -- Unlocks removable media so that it can be ejected *
- * *
- * INPUT: Handle to VWIN32 *
- * drive to unlock (DOS format) *
- * *
- * OUTPUT: true if unlocked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:19AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Unlock_Volume_95 (HANDLE vwin32, char drive)
- {
- assert (WinVersion.Is_Win9x());
- DIOC_REGISTERS regs = {0};
- PARAMBLOCK unlock_params = {0};
- bool result;
- unsigned long cb;
- /*
- ** First, check the lock status. This way, we'll know the number of pending locks we must unlock.
- */
- unlock_params.bOperation = 2; // return lock/unlock status
- regs.reg_EAX = 0x440D;
- regs.reg_EBX = drive;
- regs.reg_ECX = MAKEWORD(0x48, 0x08);
- regs.reg_EDX = (unsigned long)&unlock_params;
- result = (DeviceIoControl (vwin32, VWIN32_DIOC_DOS_IOCTL, ®s, sizeof(regs), ®s, sizeof(regs), &cb, 0)) ? true : false;
- if (result) {
- /*
- ** DeviceIoControl succeeded. Now see if the unlock succeeded. It
- ** succeeded if the carry flag is not set, or if the carry flag is
- ** set but EAX is 0x01 or 0xB0.
- **
- ** It failed if the carry flag is set and EAX is not 0x01 or 0xB0.
- **
- ** If the carry flag is clear, then unlock succeeded. However, you
- ** don't need to set fResult because it is already TRUE when you get
- ** in here.
- */
- if (regs.reg_Flags & CARRY_FLAG) {
- result = (regs.reg_EAX == 0xB0) || (regs.reg_EAX == 0x01);
- }
- } else {
- // DebugString ("DeviceIoControl failed to perform DOS IO control function. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to perform DOS IO control function. Error %d - %s.", GetLastError(), Last_Error_Text() );
- Last_Error_Text( TEXT("DeviceIoControl failed to perform DOS IO control function.."), GetLastError());
- }
- if (!result) return (false);
- /*
- ** Now we have to unlock the media for every time it was locked. This gets us a lock count of
- ** 0 and totally unlocked media.
- */
- for (int i = 0; i < unlock_params.bNumLocks; ++i) {
- unlock_params.bOperation = 1; // unlock the media
- regs.reg_EAX = 0x440D;
- regs.reg_EBX = drive;
- regs.reg_ECX = MAKEWORD(0x48, 0x08); // LOCK/UNLOCK
- regs.reg_EDX = (unsigned long)&unlock_params;
- result = (DeviceIoControl (vwin32, VWIN32_DIOC_DOS_IOCTL, ®s, sizeof(regs), ®s, sizeof(regs), &cb, 0)) ? true : false;
- if (result == false) {
- // DebugString ("DeviceIoControl failed to perform DOS IO control function. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to perform DOS IO control function. Error %d - %s.", GetLastError(), Last_Error_Text() );
- Last_Error_Text( TEXT("DeviceIoControl failed to perform DOS IO control function.."), GetLastError());
- }
- /*
- ** See if DeviceIoControl and the lock succeeded
- */
- result = result && !(regs.reg_Flags & CARRY_FLAG);
- if (!result) break;
- }
- return (result);
- }
- /***********************************************************************************************
- * CDControlClass::Lock_Volume_95 -- Locks removable media so that it can't be ejected *
- * *
- * INPUT: Handle to VWIN32 *
- * drive to lock (DOS format) *
- * *
- * OUTPUT: true if unlocked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:19AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Lock_Volume_95 (HANDLE vwin32, char drive)
- {
- assert (WinVersion.Is_Win9x());
- DIOC_REGISTERS regs = {0};
- PARAMBLOCK unlock_params = {0};
- bool result;
- unsigned long cb;
- /*
- ** Bring the lock count down to 0.
- */
- Unlock_Volume_95(vwin32, drive);
- /*
- ** Increment the lock count.
- */
- unlock_params.bOperation = 0; // lock the media
- regs.reg_EAX = 0x440D;
- regs.reg_EBX = drive;
- regs.reg_ECX = MAKEWORD(0x48, 0x08); // LOCK/UNLOCK
- regs.reg_EDX = (unsigned long)&unlock_params;
- result = (DeviceIoControl (vwin32, VWIN32_DIOC_DOS_IOCTL, ®s, sizeof(regs), ®s, sizeof(regs), &cb, 0)) ? true : false;
- if (result == false) {
- // DebugString ("DeviceIoControl failed to perform DOS IO control function. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to perform DOS IO control function. Error %d - %s.", GetLastError(), Last_Error_Text() );
- Last_Error_Text( TEXT("DeviceIoControl failed to perform DOS IO control function."), GetLastError());
- }
- /*
- ** See if DeviceIoControl and the lock succeeded
- */
- result = result && !(regs.reg_Flags & CARRY_FLAG);
- return (result);
- }
- /***********************************************************************************************
- * CDControlClass::Auto_Eject_Volume_95 -- Eject the specified CD drive *
- * *
- * INPUT: Handle to VWIN32 *
- * Drive number (DOS format) *
- * *
- * OUTPUT: True if ejected *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:24AM ST : Created *
- *=============================================================================================*/
- bool CDControlClass::Auto_Eject_Volume_95 (HANDLE vwin32, char drive)
- {
- assert (WinVersion.Is_Win9x());
- DIOC_REGISTERS regs = {0};
- bool result;
- unsigned long cb;
- regs.reg_EAX = 0x440D;
- regs.reg_EBX = drive;
- regs.reg_ECX = MAKEWORD(0x49, 0x08); //EJECT
- result = (DeviceIoControl (vwin32, VWIN32_DIOC_DOS_IOCTL, ®s, sizeof(regs), ®s, sizeof(regs), &cb, 0)) ? true : false;
- if (result == false) {
- // DebugString ("DeviceIoControl failed to perform DOS IO control function. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to perform DOS IO control function. Error %d - %s.", GetLastError(), Last_Error_Text() );
- Last_Error_Text( TEXT("DeviceIoControl failed to perform DOS IO control function."), GetLastError());
- }
- /*
- ** See if we ejected OK
- */
- result = result && !(regs.reg_Flags & CARRY_FLAG);
- return (result);
- }
- /***********************************************************************************************
- * CDControlClass::Open_VWin32 -- Opens a handle to VWIN32 to issue low-level disk I/O *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: HANDLE to VWin32 *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:26AM ST : Created *
- *=============================================================================================*/
- HANDLE WINAPI CDControlClass::Open_VWin32 (void)
- {
- assert (WinVersion.Is_Win9x());
- HANDLE result = CreateFile ( TEXT("\\\\.\\vwin32"), 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL);
- assert (result != INVALID_HANDLE_VALUE);
- return (result);
- }
- /***********************************************************************************************
- * CDControlClass::Close_VWin32 -- Closes the handle opened by Open_VWin32. *
- * *
- * INPUT: Handle to VWin32 *
- * *
- * OUTPUT: Nothing *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:26AM ST : Created *
- *=============================================================================================*/
- bool WINAPI CDControlClass::Close_VWin32 (HANDLE vwin32)
- {
- assert (WinVersion.Is_Win9x());
- return ((CloseHandle (vwin32)) ? true : false);
- }
- /***********************************************************************************************
- * CDControlClass::Lock_Logical_Volume -- Take a lock on a logical volume *
- * *
- * INPUT: Handle to VWin32 *
- * drive number (DOS format) *
- * lock level *
- * permissions *
- * *
- * OUTPUT: true if locked *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 2/17/99 0:33AM ST : Created *
- *=============================================================================================*/
- bool WINAPI CDControlClass::Lock_Logical_Volume (HANDLE vwin32, char drive, char lock_level, short permissions)
- {
- assert (WinVersion.Is_Win9x());
- bool result;
- DIOC_REGISTERS regs = {0};
- char device_cat; // can be either 0x48 or 0x08
- unsigned long cb;
- /*
- ** lock_level
- ** Can be 0, 1, 2, or 3. Level 0 is an exclusive lock that can only
- ** be taken when there are no open files on the specified drive.
- ** Levels 1 through 3 form a hierarchy where 1 must be taken before
- ** 2, which must be taken before 3.
- **
- ** permissions
- ** Specifies how the lock will affect file operations when lock levels
- ** 1 through 3 are taken. Also specifies whether a formatting lock
- ** should be taken after a level 0 lock.
- */
- /*
- ** Try first with device category 0x48 for FAT32 volumes. If it
- ** doesn't work, try again with device category 0x08. If that
- ** doesn't work, then the lock failed.
- */
- device_cat = 0;
- do {
- if (device_cat == 0) {
- device_cat = 0x48;
- }else{
- device_cat = 0x08;
- }
- /*
- ** Set up the parameters for the call.
- */
- regs.reg_EAX = 0x440D;
- regs.reg_EBX = MAKEWORD(drive, lock_level);
- regs.reg_ECX = MAKEWORD(0x4A, device_cat);
- regs.reg_EDX = permissions;
- result = (DeviceIoControl (vwin32, VWIN32_DIOC_DOS_IOCTL, ®s, sizeof(regs), ®s, sizeof(regs), &cb, 0)) ? true : false;
- if (result == false) {
- // DebugString ("DeviceIoControl failed to perform DOS IO control function. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to perform DOS IO control function. Error %d - %s.", GetLastError(), Last_Error_Text() );
- Last_Error_Text( TEXT("DeviceIoControl failed to perform DOS IO control function."), GetLastError());
- }
- result = result && !(regs.reg_Flags & CARRY_FLAG);
- } while (result == false && device_cat != 0x08);
- return (result);
- }
- /***********************************************************************************************
- * CDControlClass::Unlock_Logical_Volume -- Unlocks a logical volume *
- * *
- * INPUT: Handle to VWin32 *
- * drive number (DOS format) *
- * *
- * OUTPUT: true if unlocked *
- * *
- * WARNINGS: None *
- * *
- * Must be called the same number of times as LockLogicalVolume() to *
- * completely unlock a volume. *
- * *
- * Only the lock owner can unlock a volume. *
- * *
- * HISTORY: *
- * 2/17/99 0:39AM ST : Created *
- *=============================================================================================*/
- bool WINAPI CDControlClass::Unlock_Logical_Volume (HANDLE vwin32, char drive)
- {
- assert (WinVersion.Is_Win9x());
- bool result;
- DIOC_REGISTERS regs = {0};
- char device_cat; // can be either 0x48 or 0x08
- unsigned long cb;
- /*
- ** Try first with device category 0x48 for FAT32 volumes. If it
- ** doesn't work, try again with device category 0x08. If that
- ** doesn't work, then the unlock failed.
- */
- device_cat = 0;
- do {
- if (device_cat == 0) {
- device_cat = 0x48;
- }else{
- device_cat = 0x08;
- }
- /*
- ** Set up the parameters for the call.
- */
- regs.reg_EAX = 0x440D;
- regs.reg_EBX = drive;
- regs.reg_ECX = MAKEWORD(0x6A, device_cat);
- result = (DeviceIoControl (vwin32, VWIN32_DIOC_DOS_IOCTL, ®s, sizeof(regs), ®s, sizeof(regs), &cb, 0)) ? true : false;
- if (result == false) {
- // DebugString ("DeviceIoControl failed to perform DOS IO control function. Error %d - %s\n", GetLastError(), Last_Error_Text());
- // Msg( __LINE__, __FILE__, "DeviceIoControl failed to perform DOS IO control function. Error %d - %s.", GetLastError(), Last_Error_Text());
- Last_Error_Text( TEXT("DeviceIoControl failed to perform DOS IO control function."), GetLastError());
- }
- result = result && !(regs.reg_Flags & CARRY_FLAG);
- } while (result == false && device_cat != 0x08);
- return (result);
- }
- /************************************************************************************************
- * Last_Error_Text -- Display error messages based on FormatMessage() and GetLastError(). *
- * *
- * INPUT: LPSTR - title. *
- * HRESULT - last error message. *
- * *
- * OUTPUT: None *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 6/24/99 4:44PM MML : Created *
- *==============================================================================================*/
- void Last_Error_Text ( LPTSTR szPrefix, HRESULT hr )
- {
- LPVOID szMessage;
- char szDisplay[1000];
-
- if ( hr == S_OK ) {
- _stprintf( szDisplay, TEXT("%s"), szPrefix );
- // MessageBox( NULL, szDisplay, TEXT("Msg"),0 );
- return;
- }
- if ( HRESULT_FACILITY( hr ) == FACILITY_WIN32 ) {
- hr = HRESULT_CODE( hr );
- }
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- hr,
- MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
- (LPTSTR)&szMessage,
- 0,
- NULL );
- _stprintf( szDisplay, TEXT( "%s: %s(%lx)" ), szPrefix, szMessage, hr );
- Msg( __LINE__, TEXT(__FILE__), TEXT("GetLastError: %s"), szDisplay );
- // MessageBox( NULL, szDisplay, TEXT( "GetLastError" ), MB_OK );
- LocalFree( szMessage );
- }
|