/* * XBoxMediaPlayer * Copyright (c) 2002 d7o3g4q and RUNTiME * Portions Copyright (c) by the authors of ffmpeg and xvid * * 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 2 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // IoSupport.cpp: implementation of the CIoSupport class. // ////////////////////////////////////////////////////////////////////// #include "../stdafx.h" #include "IoSupport.h" #ifdef HAS_UNDOCUMENTED #ifdef _XBOX #include "Undocumented.h" #include "../xbox/XKExports.h" #else #include "ntddcdrm.h" #endif #endif typedef struct { char cDriveLetter; char* szDevice; int iPartition; } stDriveMapping; #ifdef _XBOX stDriveMapping driveMapping[] = { { 'C', "Harddisk0\\Partition2", 2}, { 'D', "Cdrom0", -1}, { 'E', "Harddisk0\\Partition1", 1}, { 'F', "Harddisk0\\Partition6", 6}, { 'X', "Harddisk0\\Partition3", 3}, { 'Y', "Harddisk0\\Partition4", 4}, { 'Z', "Harddisk0\\Partition5", 5}, { 'G', "Harddisk0\\Partition7", 7}, }; #else stDriveMapping driveMapping[] = { { 'C', "C:", 2}, { 'D', "D:", -1}, { 'E', "E:", 1}, { 'F', "F:", 6}, { 'X', "X:", 3}, { 'Y', "Y:", 4}, { 'Z', "Z:", 5}, { 'G', "G:", 7}, }; #include "../../Tools/Win32/XBMC_PC.h" #endif #define NUM_OF_DRIVES ( sizeof( driveMapping) / sizeof( driveMapping[0] ) ) ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CIoSupport::CIoSupport() { } CIoSupport::~CIoSupport() { } // cDriveLetter e.g. 'D' // szDevice e.g. "Cdrom0" or "Harddisk0\Partition6" HRESULT CIoSupport::MapDriveLetter(char cDriveLetter, char * szDevice) { #ifdef _XBOX char szSourceDevice[MAX_PATH+32]; char szDestinationDrive[16]; // TEMPORARY FIX: There are dangling handles left open somewhere - these must be found! Dismount(szDevice); sprintf(szSourceDevice, "\\Device\\%s", szDevice); sprintf(szDestinationDrive, "\\??\\%c:", cDriveLetter); ANSI_STRING DeviceName, LinkName; RtlInitAnsiString(&DeviceName, szSourceDevice); RtlInitAnsiString(&LinkName, szDestinationDrive); IoCreateSymbolicLink(&LinkName, &DeviceName); #else if ((strnicmp(szDevice, "Harddisk0", 9) == 0) || (strnicmp(szDevice, "Cdrom", 5) == 0)) return S_OK; #endif return S_OK; } // cDriveLetter e.g. 'D' HRESULT CIoSupport::UnmapDriveLetter(char cDriveLetter) { #ifdef _XBOX char szDestinationDrive[16]; ANSI_STRING LinkName; sprintf(szDestinationDrive, "\\??\\%c:", cDriveLetter); RtlInitAnsiString(&LinkName, szDestinationDrive); IoDeleteSymbolicLink(&LinkName); #endif return S_OK; } HRESULT CIoSupport::RemapDriveLetter(char cDriveLetter, char * szDevice) { // TEMPORARY FIX: There are dangling handles left open somewhere - these must be found! Dismount(szDevice); if (DriveExists(cDriveLetter)) UnmapDriveLetter(cDriveLetter); return MapDriveLetter(cDriveLetter, szDevice); } // to be used with CdRom devices. HRESULT CIoSupport::Dismount(char * szDevice) { #ifdef _XBOX char szSourceDevice[MAX_PATH+32]; ANSI_STRING DeviceName; sprintf(szSourceDevice, "\\Device\\%s", szDevice); RtlInitAnsiString(&DeviceName, szSourceDevice); return IoDismountVolumeByName(&DeviceName); #else return S_OK; #endif } void CIoSupport::GetPartition(char cDriveLetter, char * szPartition) { for (int i=0; i < NUM_OF_DRIVES; i++) if (driveMapping[i].cDriveLetter == toupper(cDriveLetter)) { strcpy(szPartition, driveMapping[i].szDevice); return; } *szPartition = 0; } void CIoSupport::GetDrive(char * szPartition, char * cDriveLetter) { for (int i=0; i < NUM_OF_DRIVES; i++) if (strnicmp(driveMapping[i].szDevice, szPartition, strlen(driveMapping[i].szDevice)) == 0) { *cDriveLetter = driveMapping[i].cDriveLetter; return; } *cDriveLetter = 0; } HRESULT CIoSupport::EjectTray() { #ifdef _XBOX HalWriteSMBusValue(0x20, 0x0C, FALSE, 0); // eject tray #endif return S_OK; } HRESULT CIoSupport::CloseTray() { #ifdef _XBOX HalWriteSMBusValue(0x20, 0x0C, FALSE, 1); // close tray #endif return S_OK; } DWORD CIoSupport::GetTrayState() { #ifdef _XBOX DWORD dwTrayState, dwTrayCount; if (g_advancedSettings.m_usePCDVDROM) { dwTrayState = TRAY_CLOSED_MEDIA_PRESENT; } else { HalReadSMCTrayState(&dwTrayState, &dwTrayCount); } return dwTrayState; #endif return DRIVE_NOT_READY; } HRESULT CIoSupport::Shutdown() { #ifdef _XBOX // fails assertion on debug bios (symptom lockup unless running dr watson) // so you can continue past the failed assertion). if (IsDebug()) return E_FAIL; KeRaiseIrqlToDpcLevel(); HalInitiateShutdown(); #endif return S_OK; } HANDLE CIoSupport::OpenCDROM() { HANDLE hDevice; #ifdef _XBOX NTSTATUS error; IO_STATUS_BLOCK status; ANSI_STRING filename; OBJECT_ATTRIBUTES attributes; RtlInitAnsiString(&filename, "\\Device\\Cdrom0"); InitializeObjectAttributes(&attributes, &filename, OBJ_CASE_INSENSITIVE, NULL); if (!NT_SUCCESS(error = NtCreateFile(&hDevice, GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attributes, &status, NULL, 0, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))) { return NULL; } #else hDevice = CreateFile("\\\\.\\Cdrom0", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL ); #endif return hDevice; } INT CIoSupport::ReadSector(HANDLE hDevice, DWORD dwSector, LPSTR lpczBuffer) { DWORD dwRead; DWORD dwSectorSize = 2048; LARGE_INTEGER Displacement; Displacement.QuadPart = ((INT64)dwSector) * dwSectorSize; for (int i = 0; i < 5; i++) { SetFilePointer(hDevice, Displacement.LowPart, &Displacement.HighPart, FILE_BEGIN); if (ReadFile(hDevice, lpczBuffer, dwSectorSize, &dwRead, NULL)) return dwRead; } OutputDebugString("CD Read error\n"); return -1; } INT CIoSupport::ReadSectorMode2(HANDLE hDevice, DWORD dwSector, LPSTR lpczBuffer) { #ifdef HAS_DVD_DRIVE DWORD dwBytesReturned; RAW_READ_INFO rawRead = {0}; // Oddly enough, DiskOffset uses the Red Book sector size rawRead.DiskOffset.QuadPart = 2048 * dwSector; rawRead.SectorCount = 1; rawRead.TrackMode = XAForm2; for (int i = 0; i < 5; i++) { if ( DeviceIoControl( hDevice, IOCTL_CDROM_RAW_READ, &rawRead, sizeof(RAW_READ_INFO), lpczBuffer, RAW_SECTOR_SIZE, &dwBytesReturned, NULL ) != 0 ) return MODE2_DATA_SIZE; else { int iErr = GetLastError(); // printf("%i\n", iErr); } } #endif return -1; } INT CIoSupport::ReadSectorCDDA(HANDLE hDevice, DWORD dwSector, LPSTR lpczBuffer) { #ifdef HAS_DVD_DRIVE DWORD dwBytesReturned; RAW_READ_INFO rawRead; // Oddly enough, DiskOffset uses the Red Book sector size rawRead.DiskOffset.QuadPart = 2048 * dwSector; rawRead.SectorCount = 1; rawRead.TrackMode = CDDA; for (int i = 0; i < 5; i++) { if ( DeviceIoControl( hDevice, IOCTL_CDROM_RAW_READ, &rawRead, sizeof(RAW_READ_INFO), lpczBuffer, sizeof(RAW_SECTOR_SIZE), &dwBytesReturned, NULL ) != 0 ) return RAW_SECTOR_SIZE; } #endif return -1; } VOID CIoSupport::CloseCDROM(HANDLE hDevice) { CloseHandle(hDevice); } // returns true if this is a debug machine BOOL CIoSupport::IsDebug() { #ifdef _XBOX return (XboxKrnlVersion->Qfe & 0x8000) || ((DWORD)XboxHardwareInfo & 0x10); #else return FALSE; #endif } VOID CIoSupport::GetXbePath(char* szDest) { #ifdef _XBOX //Function to get the XBE Path like: //E:\DevKit\xbplayer\xbplayer.xbe PANSI_STRING pImageFileName = (PANSI_STRING)XeImageFileName; char szTemp[MAX_PATH]; char cDriveLetter = 0; strncpy(szTemp, pImageFileName->Buffer + 8, pImageFileName->Length - 8); szTemp[20] = 0; GetDrive(szTemp, &cDriveLetter); strncpy(szTemp, pImageFileName->Buffer + 29, pImageFileName->Length - 29); szTemp[pImageFileName->Length - 29] = 0; sprintf(szDest, "%c:\\%s", cDriveLetter, szTemp); #else GetCurrentDirectory(XBMC_MAX_PATH, szDest); strcat(szDest, "\\XBMC_PC.exe"); #endif } bool CIoSupport::DriveExists(char cDriveLetter) { #ifdef _XBOX char szDrive[32]; ANSI_STRING drive_string; NTSTATUS status; HANDLE hTemp; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iosb; bool retval; sprintf(szDrive, "\\??\\%c:", cDriveLetter); RtlInitAnsiString(&drive_string, szDrive); oa.Attributes = OBJ_CASE_INSENSITIVE; oa.ObjectName = &drive_string; oa.RootDirectory = 0; status = NtOpenFile(&hTemp, GENERIC_READ | GENERIC_WRITE, &oa, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); if (NT_SUCCESS(status)) retval = true; else retval = false; CloseHandle(hTemp); return retval; #else return false; #endif } bool CIoSupport::PartitionExists(int nPartition) { #ifdef _XBOX char szPartition[32]; ANSI_STRING part_string; NTSTATUS status; HANDLE hTemp; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iosb; bool retval; sprintf(szPartition, "\\Device\\Harddisk0\\Partition%u", nPartition); RtlInitAnsiString(&part_string, szPartition); oa.Attributes = OBJ_CASE_INSENSITIVE; oa.ObjectName = &part_string; oa.RootDirectory = 0; status = NtOpenFile(&hTemp, GENERIC_READ | GENERIC_WRITE, &oa, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); if (NT_SUCCESS(status)) retval = true; else retval = false; CloseHandle(hTemp); return retval; #else return false; #endif }