/*
**	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/GETCD.CPP              $Author:: Steve_t									*
 *                     $Modtime:: 1/28/02 10:54a                  $Revision:: 20										*
 *--------------------------------------------------------------------------*
 * Functions:																*
 *		GetCDClass::GetCDClass	--	default constructor						*
 *		GetCDClass::~GetCDClass	--	destructor								*
 *		GetCDClass::GetCDDrive	--	returns the logical CD drive			*
 *		CD_Volume_Verification	--	Check label of the CDRom.				*
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

#include	<windows.h>
#include	<string.h>
//#include	"always.h"
#include	"getcd.h"
//#include	"timer.h"
#include	"wnd_file.h"
//#include	"missiondisk.h"
#include	"winfix.h"

#ifndef ROR_NOT_READY
#define ROR_NOT_READY		21
#endif

/**********************************************************************
**	This macro serves as a general way to determine the number of elements
**	within an array.
*/
#define	ARRAY_SIZE(x)		int(sizeof(x)/sizeof(x[0]))
#define	size_of(typ,id)		sizeof(((typ*)0)->id)

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
#if ( MISSION_DISK )

static char * _CD_Volume_Label[] = {
	"Renegade Mission",		// Yuri's Revenge (mission disk)
};

#else

static char * _CD_Volume_Label[] = {
	"Renegade Game",		// Red Alert 2
	"Renegade Data",		// Red Alert 2
};

#endif


static int _Num_Volumes = ARRAY_SIZE( _CD_Volume_Label );

GetCDClass	CDList;


/****************************************************************************
 * GetCDClass -- default constructor										*
 *																			*
 * INPUT:																	*
 *			none 															*
 * OUTPUT:																	*
 *			none															*
 * WARNINGS:																*
 *																			*
 * HISTORY:																	*
 *   05/26/1994 SW	:	Created.											*
 *   12/04/1995 ST	:	fixed for Win95										*
 *==========================================================================*/
GetCDClass::GetCDClass( void )
{
	char path[]={ "a:\\" };

	CDCount = 0;
	CDIndex = 0;

	Msg( __LINE__, __FILE__, "GetCDClass constructor\n" );

	/*--------------------------------------------------------------------------
	** Set all CD drive placeholders to empty
	*/
	for( int j = 0; j < MAX_CD_DRIVES; j++ ) {
		CDDrives[j] = NO_CD_DRIVE;
	}

	for( char i = 'c'; i <= 'z'; i++ ) {

		path[0] = i;

		if ( GetDriveType( path ) == DRIVE_CDROM ) {
			CDDrives[ CDCount++ ] = (int)( i-'a' );
			Msg( __LINE__, __FILE__, "CD drive found - %c:\n", i +'A'-'a' );
		}
	}

	/*--------------------------------------------------------------------------
	**	Catch the case when there are NO CD-ROM drives available
	*/
	if ( CDCount == 0 ) {
		for ( char i = 'a'; i <= 'b'; i++ ) {
			path[0] = i;
			if ( GetDriveType( path ) == DRIVE_CDROM ) {
				CDDrives[ CDCount++ ] = (int)( i-'a' );
			}
		}
	}
	if ( CDCount == 0 ) {
		Msg( __LINE__, __FILE__, "No CD drives found\n");
	}
}

/********************************************************************************
 * GetCDClass -- destructor														*
 *																				*
 * INPUT:		none															*
 *																				*
 * OUTPUT:		none															*
 *																				*
 * WARNINGS:																	*
 *																				*
 * HISTORY:																		*
 *   05/26/1994 SW: Created.													*
 *   12/4/95    ST: fixed for Win95												*
 *==============================================================================*/
GetCDClass::~GetCDClass(void)
{
//	if(cdDrive_addrp.seg)
//		DPMI_real_free(cdDrive_addrp);		// free up those conventional buffers
}

/********************************************************************************
 * GetCDClass -- Get_CD_Drive_For_This_Volume									*
 *																				*
 * INPUT:		char *volume_name												*
 *																				*
 * OUTPUT:		int																*
 *																				*
 * WARNINGS:																	*
 *																				*
 * HISTORY:																		*
 *   10/18/2000 MML: Created.													*
 *==============================================================================*/

int	GetCDClass::Get_CD_Drive_For_This_Volume ( char *volume_label )
{
	char		volume_name[128] = "";
	int			count = 0;
	char		buffer[128];
	unsigned	misc_dword;
	unsigned	filename_length;
	int			cd_drive;

	CDIndex = 0;

	while( CDIndex < CDCount ) {

		//---------------------------------------------------------------------
		// NOTE: A=0, B=1, C=2, D=3, etc...
		//---------------------------------------------------------------------
		cd_drive = CDDrives[ CDIndex++ ];
		wsprintf( buffer, "%c:\\", 'A' + cd_drive );

		if ( GetVolumeInformation(
				(char const *)buffer,
				&volume_name[0],
				(unsigned long)sizeof(volume_name)-1,
				(unsigned long *)NULL,
				(unsigned long *)&filename_length,
				(unsigned long *)&misc_dword,
				(char *)NULL,
				(unsigned long)0 )) {

			//---------------------------------------------------------------------
			// Windows '95 appears to have a volume name limit of 11 characters. 
			// I cannot find a Win32 call that will return the maximum volume name 
			// length so the value '11' is hard-coded here and the assumption made 
			// that all OS's have this length or better.
			//---------------------------------------------------------------------
			if( WinVersion.Is_Win95()) {
				volume_name[11] = '\0';
			}

			if ( !_stricmp( volume_label, volume_name )) {
				return( cd_drive );
			}

		} else {

#if _DEBUG
			LPVOID lpMsgBuf;
			FormatMessage( 
				FORMAT_MESSAGE_ALLOCATE_BUFFER | 
				FORMAT_MESSAGE_FROM_SYSTEM | 
				FORMAT_MESSAGE_IGNORE_INSERTS,
				NULL,
				GetLastError(),
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
				(LPTSTR) &lpMsgBuf,
				0,
				NULL 
			);
			Msg( __LINE__, __FILE__, (LPTSTR)lpMsgBuf );
			LocalFree( lpMsgBuf );
#endif

		}
	}
	return( Get_First_CD_Drive());
}

/********************************************************************************
 * GetCDClass -- Get_Volume_Label												*
 *																				*
 * INPUT:		int  index														*
 *																				*
 * OUTPUT:		char *															*
 *																				*
 * WARNINGS:																	*
 *																				*
 * HISTORY:																		*
 *   10/31/2000 MML: Created.	* Happy Halloween! *							*
 *==============================================================================*/

char * GetCDClass::Get_Volume_Label	( int index )
{
	if( index >= 0 && index < _Num_Volumes ) {
		return( _CD_Volume_Label[ index ]);
	}
	return( _CD_Volume_Label[0]);
}

/********************************************************************************
 * GetCDClass -- Get_Volume_For_This_CD_Drive									*
 *																				*
 * INPUT:		char *volume_name												*
 *				char *path														*
 *																				*
 * OUTPUT:		int																*
 *																				*
 * WARNINGS:																	*
 *																				*
 * HISTORY:																		*
 *   10/31/2000 MML: Created.	* Happy Halloween! *							*
 *==============================================================================*/

char *GetCDClass::Get_Volume_For_This_CD_Drive ( char *path, char *volume_name )
{
	char			buffer[128];
	unsigned		misc_dword;
	unsigned		filename_length;
	static char		volume_label[ MAX_PATH ] = "";	// [OYO] add static

	if ( path == NULL || volume_name == NULL ) {
		return( NULL );
	}

	memset( volume_name, '\0', sizeof( volume_name ));
	wsprintf( buffer, "%c:\\", path[0] );

	if ( GetVolumeInformation(
			(char const *)buffer,
			&volume_label[0],
			(unsigned long)sizeof(volume_label)-1,
			(unsigned long *)NULL,
			(unsigned long *)&filename_length,
			(unsigned long *)&misc_dword,
			(char *)NULL,
			(unsigned long)0 )) {

		strcpy( volume_name, volume_label );

	} else {

		LPVOID lpMsgBuf;
		FormatMessage( 
		    FORMAT_MESSAGE_ALLOCATE_BUFFER | 
		    FORMAT_MESSAGE_FROM_SYSTEM | 
		    FORMAT_MESSAGE_IGNORE_INSERTS,
		    NULL,
		    GetLastError(),
		    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		    (LPTSTR) &lpMsgBuf,
		    0,
		    NULL 
		);
		Msg( __LINE__, __FILE__, (LPTSTR)lpMsgBuf );
		LocalFree( lpMsgBuf );

		strcpy( volume_name, _CD_Volume_Label[0] );
	}

	//-------------------------------------------------------------------------
	// Windows '95 appears to have a volume name limit of 11 characters. 
	// I cannot find a Win32 call that will return the maximum volume name 
	// length so the value '11' is hard-coded here and the assumption made 
	// that all OS's have this length or better.
	//-------------------------------------------------------------------------
	bool winversion = WinVersion.Is_Win95();

	if( winversion ) {
		volume_name[11] = '\0';
	}

	return( volume_name );
}

/********************************************************************************
 * CD_VOLUME_VERIFICATION -- Check volume label of the CD in the given drive.	*
 *																				*
 * INPUT:		int drive_number												*
 *	  			char *lable														*
 *																				*
 * OUTPUT:		TRUE/FALSE														*
 *																				*
 * WARNINGS:	None															*
 *																				*
 * HISTORY:																		*
 *    01/11/99 4:20PM MML : Created												*
 *==============================================================================*/

bool CD_Volume_Verification ( int cd_drive, char *volume_label, char *volume_to_find )
{
	char		volume_name[128] = "";
	int			count = 0;
	char		buffer[128];
	unsigned	misc_dword;
	unsigned	filename_length;

	/***************************************************************************
	** Get the volume label. If we get a 'not ready' error then retry for the 
	** timeout period.
	*/
	for (;;) {

		//---------------------------------------------------------------------
		// NOTE: A=0, B=1, C=2, D=3, etc...
		//---------------------------------------------------------------------
		wsprintf( buffer, "%c:\\", 'A' + cd_drive );

		if ( GetVolumeInformation(
				(char const *)buffer,
				&volume_name[0],
				(unsigned long)sizeof(volume_name)-1,
				(unsigned long *)NULL,
				(unsigned long *)&filename_length,
				(unsigned long *)&misc_dword,
				(char *)NULL,
				(unsigned long)0 )) {

			/******************************************************************
			** Match the volume label to the list of known volume labels.
			*/

			//---------------------------------------------------------------------
			// Windows '95 appears to have a volume name limit of 11 characters. 
			// I cannot find a Win32 call that will return the maximum volume name 
			// length so the value '11' is hard-coded here and the assumption made 
			// that all OS's have this length or better.
			//---------------------------------------------------------------------
			if( WinVersion.Is_Win95()) {
				volume_name[11] = '\0';
			}

			if ( volume_label != NULL ) {
				strncpy( volume_label, volume_name, 128 );
			}

			if ( !_stricmp( volume_to_find, volume_name )) {
				return TRUE;
			}

			if ( !count ) {
				count++;
			} else {
				return FALSE;
			} 

		} else {

			/*********************************************************************
			** Failed to get the volume label on a known CD drive.  If this is a
			** CD changer it may require time to swap the disks so don't return
			** immediately if the error is ROR_NOT_READY
			*/
			return FALSE;
		}
	}
}




/* ==================================================================== */

