3 * Copyright (c) 2002 d7o3g4q and RUNTiME
4 * Portions Copyright (c) by the authors of ffmpeg and xvid
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 // IoSupport.cpp: implementation of the CIoSupport class.
23 //////////////////////////////////////////////////////////////////////
26 #include "IoSupport.h"
28 #include "utils/log.h"
30 #include "my_ntddcdrm.h"
31 #include "WIN32Util.h"
32 #include "CharsetConverter.h"
34 #if defined (_LINUX) && !defined(__APPLE__)
35 #include <linux/limits.h>
36 #include <sys/types.h>
37 #include <sys/ioctl.h>
40 #include <linux/cdrom.h>
43 #include <sys/param.h>
44 #include <mach-o/dyld.h>
45 #include <IOKit/IOKitLib.h>
46 #include <IOKit/IOBSD.h>
47 #include <IOKit/storage/IOCDTypes.h>
48 #include <IOKit/storage/IODVDTypes.h>
49 #include <IOKit/storage/IOMedia.h>
50 #include <IOKit/storage/IOCDMedia.h>
51 #include <IOKit/storage/IODVDMedia.h>
52 #include <IOKit/storage/IOCDMediaBSDClient.h>
53 #include <IOKit/storage/IODVDMediaBSDClient.h>
54 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
56 #include "../FileSystem/cdioSupport.h"
57 #include "../FileSystem/iso9660.h"
58 #include "../MediaManager.h"
63 #define NT_STATUS_OBJECT_NAME_NOT_FOUND long(0xC0000000 | 0x0034)
64 #define NT_STATUS_VOLUME_DISMOUNTED long(0xC0000000 | 0x026E)
69 char szDevice
[MAX_PATH
];
75 stDriveMapping driveMapping
[] =
77 { 'C', "Harddisk0\\Partition2", 2},
79 { 'E', "Harddisk0\\Partition1", 1},
80 { 'X', "Harddisk0\\Partition3", 3},
81 { 'Y', "Harddisk0\\Partition4", 4},
82 { 'Z', "Harddisk0\\Partition5", 5},
85 stDriveMapping driveMapping
[] =
95 stDriveMapping driveMapping
[] =
107 #define NUM_OF_DRIVES ( sizeof( driveMapping) / sizeof( driveMapping[0] ) )
110 PVOID
CIoSupport::m_rawXferBuffer
;
111 PARTITION_TABLE
CIoSupport::m_partitionTable
;
112 bool CIoSupport::m_fPartitionTableIsValid
;
115 // cDriveLetter e.g. 'D'
116 // szDevice e.g. "Cdrom0" or "Harddisk0\Partition6"
117 HRESULT
CIoSupport::MapDriveLetter(char cDriveLetter
, const char* szDevice
)
120 char szSourceDevice
[MAX_PATH
+32];
121 char szDestinationDrive
[16];
124 CLog::Log(LOGNOTICE
, "Mapping drive %c to %s", cDriveLetter
, szDevice
);
126 sprintf(szSourceDevice
, "\\Device\\%s", szDevice
);
127 sprintf(szDestinationDrive
, "\\??\\%c:", cDriveLetter
);
129 ANSI_STRING DeviceName
, LinkName
;
131 RtlInitAnsiString(&DeviceName
, szSourceDevice
);
132 RtlInitAnsiString(&LinkName
, szDestinationDrive
);
134 status
= IoCreateSymbolicLink(&LinkName
, &DeviceName
);
136 if (!NT_SUCCESS(status
))
137 CLog::Log(LOGERROR
, "Failed to create symbolic link! (status=0x%08x)", status
);
142 // still legacy support (only used in DetectDVDType.cpp)
143 if((strnicmp(szDevice
, "Harddisk0",9)==0) || (strnicmp(szDevice
, "Cdrom",5)==0))
146 CStdString
device(szDevice
);
147 device
.TrimRight("/\\");
148 char upperLetter
= toupper(cDriveLetter
);
149 for (unsigned int i
=0; i
< NUM_OF_DRIVES
; i
++)
150 if (driveMapping
[i
].cDriveLetter
== upperLetter
)
152 strcpy(driveMapping
[i
].szDevice
, device
.c_str());
153 CLog::Log(LOGNOTICE
, "Mapping drive %c to %s", cDriveLetter
, device
.c_str());
160 // cDriveLetter e.g. 'D'
161 HRESULT
CIoSupport::UnmapDriveLetter(char cDriveLetter
)
164 char szDestinationDrive
[16];
165 ANSI_STRING LinkName
;
168 sprintf(szDestinationDrive
, "\\??\\%c:", cDriveLetter
);
169 RtlInitAnsiString(&LinkName
, szDestinationDrive
);
171 status
= IoDeleteSymbolicLink(&LinkName
);
173 if (NT_SUCCESS(status
))
174 CLog::Log(LOGNOTICE
, "Unmapped drive %c", cDriveLetter
);
175 else if(status
!= NT_STATUS_OBJECT_NAME_NOT_FOUND
)
176 CLog::Log(LOGERROR
, "Failed to delete symbolic link! (status=0x%08x)", status
);
184 HRESULT
CIoSupport::RemapDriveLetter(char cDriveLetter
, const char* szDevice
)
186 UnmapDriveLetter(cDriveLetter
);
188 return MapDriveLetter(cDriveLetter
, szDevice
);
190 // to be used with CdRom devices.
191 HRESULT
CIoSupport::Dismount(const char* szDevice
)
194 char szSourceDevice
[MAX_PATH
+32];
195 ANSI_STRING DeviceName
;
198 sprintf(szSourceDevice
, "\\Device\\%s", szDevice
);
200 RtlInitAnsiString(&DeviceName
, szSourceDevice
);
202 status
= IoDismountVolumeByName(&DeviceName
);
204 if (NT_SUCCESS(status
))
205 CLog::Log(LOGNOTICE
, "Dismounted %s", szDevice
);
206 else if(status
!= NT_STATUS_VOLUME_DISMOUNTED
)
207 CLog::Log(LOGERROR
, "Failed to dismount volume! (status=0x%08x)", status
);
215 void CIoSupport::GetPartition(char cDriveLetter
, char* szPartition
)
217 char upperLetter
= toupper(cDriveLetter
);
218 if (upperLetter
>= 'F' && upperLetter
<= 'O')
220 sprintf(szPartition
, "Harddisk0\\Partition%u", upperLetter
- 'A' + 1);
223 for (unsigned int i
=0; i
< NUM_OF_DRIVES
; i
++)
224 if (driveMapping
[i
].cDriveLetter
== upperLetter
)
226 strcpy(szPartition
, driveMapping
[i
].szDevice
);
232 const char* CIoSupport::GetPartition(char cDriveLetter
)
234 char upperLetter
= toupper(cDriveLetter
);
235 for (unsigned int i
=0; i
< NUM_OF_DRIVES
; i
++)
236 if (driveMapping
[i
].cDriveLetter
== upperLetter
)
237 return driveMapping
[i
].szDevice
;
241 void CIoSupport::GetDrive(const char* szPartition
, char* cDriveLetter
)
243 int part_str_len
= strlen(szPartition
);
246 if (part_str_len
< 19)
252 part_num
= atoi(szPartition
+ 19);
256 *cDriveLetter
= part_num
+ 'A' - 1;
259 for (unsigned int i
=0; i
< NUM_OF_DRIVES
; i
++)
260 if (strnicmp(driveMapping
[i
].szDevice
, szPartition
, strlen(driveMapping
[i
].szDevice
)) == 0)
262 *cDriveLetter
= driveMapping
[i
].cDriveLetter
;
268 HRESULT
CIoSupport::EjectTray( const bool bEject
, const char cDriveLetter
)
272 return CWIN32Util::EjectTray(cDriveLetter
);
274 CLibcdio
*c_cdio
= CLibcdio::GetInstance();
275 char* dvdDevice
= c_cdio
->GetDeviceFileName();
278 while (nRetries
-- > 0)
280 CdIo_t
* cdio
= c_cdio
->cdio_open(dvdDevice
, DRIVER_UNKNOWN
);
283 c_cdio
->cdio_eject_media(&cdio
);
284 c_cdio
->cdio_destroy(cdio
);
294 HRESULT
CIoSupport::CloseTray()
298 HalWriteSMBusValue(0x20, 0x0C, FALSE
, 1); // close tray
302 #elif defined(_LINUX)
303 char* dvdDevice
= CLibcdio::GetInstance()->GetDeviceFileName();
304 if (strlen(dvdDevice
) != 0)
306 int fd
= open(dvdDevice
, O_RDONLY
| O_NONBLOCK
);
309 ioctl(fd
, CDROMCLOSETRAY
, 0);
313 #elif defined(_WIN32)
314 return CWIN32Util::CloseTray();
320 DWORD
CIoSupport::GetTrayState()
322 #if defined(_LINUX) || defined(_WIN32)
323 return g_mediaManager
.GetDriveStatus();
325 return DRIVE_NOT_READY
;
329 HRESULT
CIoSupport::ToggleTray()
331 if (GetTrayState() == TRAY_OPEN
|| GetTrayState() == DRIVE_OPEN
)
337 HRESULT
CIoSupport::Shutdown()
340 // fails assertion on debug bios (symptom lockup unless running dr watson)
341 // so you can continue past the failed assertion).
344 KeRaiseIrqlToDpcLevel();
345 HalInitiateShutdown();
350 HANDLE
CIoSupport::OpenCDROM()
356 IO_STATUS_BLOCK status
;
357 ANSI_STRING filename
;
358 OBJECT_ATTRIBUTES attributes
;
359 RtlInitAnsiString(&filename
, "\\Device\\Cdrom0");
360 InitializeObjectAttributes(&attributes
, &filename
, OBJ_CASE_INSENSITIVE
, NULL
);
361 if (!NT_SUCCESS(NtOpenFile(&hDevice
,
362 GENERIC_READ
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
,
366 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
)))
370 #elif defined(_LINUX)
371 int fd
= open(CLibcdio::GetInstance()->GetDeviceFileName(), O_RDONLY
| O_NONBLOCK
);
372 hDevice
= new CXHandle(CXHandle::HND_FILE
);
374 hDevice
->m_bCDROM
= true;
375 #elif defined(_WIN32)
376 hDevice
= CreateFile(g_mediaManager
.TranslateDevicePath("",true), GENERIC_READ
, FILE_SHARE_READ
,
378 FILE_FLAG_RANDOM_ACCESS
, NULL
);
381 hDevice
= CreateFile("\\\\.\\Cdrom0", GENERIC_READ
, FILE_SHARE_READ
,
383 FILE_FLAG_RANDOM_ACCESS
, NULL
);
390 void CIoSupport::AllocReadBuffer()
393 m_rawXferBuffer
= GlobalAlloc(GPTR
, RAW_SECTOR_SIZE
);
397 void CIoSupport::FreeReadBuffer()
400 GlobalFree(m_rawXferBuffer
);
404 INT
CIoSupport::ReadSector(HANDLE hDevice
, DWORD dwSector
, LPSTR lpczBuffer
)
408 DWORD dwSectorSize
= 2048;
411 dk_cd_read_t cd_read
;
412 memset( &cd_read
, 0, sizeof(cd_read
) );
414 cd_read
.sectorArea
= kCDSectorAreaUser
;
415 cd_read
.buffer
= lpczBuffer
;
417 cd_read
.sectorType
= kCDSectorTypeMode1
;
418 cd_read
.offset
= dwSector
* kCDSectorSizeMode1
;
420 cd_read
.bufferLength
= 2048;
422 if( ioctl(hDevice
->fd
, DKIOCCDREAD
, &cd_read
) == -1 )
427 #elif defined(_LINUX)
428 if (hDevice
->m_bCDROM
)
430 int fd
= hDevice
->fd
;
432 // seek to requested sector
433 off_t offset
= (off_t
)dwSector
* (off_t
)MODE1_DATA_SIZE
;
435 if (lseek(fd
, offset
, SEEK_SET
) < 0)
437 CLog::Log(LOGERROR
, "CD: ReadSector Request to read sector %d\n", (int)dwSector
);
438 CLog::Log(LOGERROR
, "CD: ReadSector error: %s\n", strerror(errno
));
439 OutputDebugString("CD Read error\n");
443 // read data block of this sector
444 while (read(fd
, lpczBuffer
, MODE1_DATA_SIZE
) < 0)
446 // read was interrupted - try again
450 // error reading sector
451 CLog::Log(LOGERROR
, "CD: ReadSector Request to read sector %d\n", (int)dwSector
);
452 CLog::Log(LOGERROR
, "CD: ReadSector error: %s\n", strerror(errno
));
453 OutputDebugString("CD Read error\n");
457 return MODE1_DATA_SIZE
;
460 LARGE_INTEGER Displacement
;
461 Displacement
.QuadPart
= ((INT64
)dwSector
) * dwSectorSize
;
463 for (int i
= 0; i
< 5; i
++)
465 SetFilePointer(hDevice
, Displacement
.u
.LowPart
, &Displacement
.u
.HighPart
, FILE_BEGIN
);
467 if (ReadFile(hDevice
, m_rawXferBuffer
, dwSectorSize
, &dwRead
, NULL
))
469 memcpy(lpczBuffer
, m_rawXferBuffer
, dwSectorSize
);
474 OutputDebugString("CD Read error\n");
479 INT
CIoSupport::ReadSectorMode2(HANDLE hDevice
, DWORD dwSector
, LPSTR lpczBuffer
)
483 dk_cd_read_t cd_read
;
485 memset( &cd_read
, 0, sizeof(cd_read
) );
487 cd_read
.sectorArea
= kCDSectorAreaUser
;
488 cd_read
.buffer
= lpczBuffer
;
490 cd_read
.offset
= dwSector
* kCDSectorSizeMode2Form2
;
491 cd_read
.sectorType
= kCDSectorTypeMode2Form2
;
492 cd_read
.bufferLength
= kCDSectorSizeMode2Form2
;
494 if( ioctl( hDevice
->fd
, DKIOCCDREAD
, &cd_read
) == -1 )
498 return MODE2_DATA_SIZE
;
499 #elif defined(_LINUX)
500 if (hDevice
->m_bCDROM
)
502 int fd
= hDevice
->fd
;
503 int lba
= (dwSector
+ CD_MSF_OFFSET
) ;
507 struct cdrom_msf msf
;
511 // convert sector offset to minute, second, frame format
512 // since that is what the 'ioctl' requires as input
519 arg
.msf
.cdmsf_min0
= m
;
520 arg
.msf
.cdmsf_sec0
= s
;
521 arg
.msf
.cdmsf_frame0
= f
;
523 int ret
= ioctl(fd
, CDROMREADMODE2
, &arg
);
526 memcpy(lpczBuffer
, arg
.buffer
, MODE2_DATA_SIZE
); // don't think offset is needed here
527 return MODE2_DATA_SIZE
;
529 CLog::Log(LOGERROR
, "CD: ReadSectorMode2 Request to read sector %d\n", (int)dwSector
);
530 CLog::Log(LOGERROR
, "CD: ReadSectorMode2 error: %s\n", strerror(errno
));
531 CLog::Log(LOGERROR
, "CD: ReadSectorMode2 minute %d, second %d, frame %d\n", m
, s
, f
);
532 OutputDebugString("CD Read error\n");
536 DWORD dwBytesReturned
;
537 RAW_READ_INFO rawRead
= {0};
539 // Oddly enough, DiskOffset uses the Red Book sector size
540 rawRead
.DiskOffset
.QuadPart
= 2048 * dwSector
;
541 rawRead
.SectorCount
= 1;
542 rawRead
.TrackMode
= XAForm2
;
545 for (int i
= 0; i
< 5; i
++)
547 if ( DeviceIoControl( hDevice
,
548 IOCTL_CDROM_RAW_READ
,
550 sizeof(RAW_READ_INFO
),
556 memcpy(lpczBuffer
, (char*)m_rawXferBuffer
+MODE2_DATA_START
, MODE2_DATA_SIZE
);
557 return MODE2_DATA_SIZE
;
561 int iErr
= GetLastError();
569 INT
CIoSupport::ReadSectorCDDA(HANDLE hDevice
, DWORD dwSector
, LPSTR lpczBuffer
)
573 DWORD dwBytesReturned
;
574 RAW_READ_INFO rawRead
;
576 // Oddly enough, DiskOffset uses the Red Book sector size
577 rawRead
.DiskOffset
.QuadPart
= 2048 * dwSector
;
578 rawRead
.SectorCount
= 1;
579 rawRead
.TrackMode
= CDDA
;
581 for (int i
= 0; i
< 5; i
++)
583 if ( DeviceIoControl( hDevice
,
584 IOCTL_CDROM_RAW_READ
,
586 sizeof(RAW_READ_INFO
),
588 sizeof(RAW_SECTOR_SIZE
),
592 memcpy(lpczBuffer
, m_rawXferBuffer
, RAW_SECTOR_SIZE
);
593 return RAW_SECTOR_SIZE
;
601 VOID
CIoSupport::CloseCDROM(HANDLE hDevice
)
603 CloseHandle(hDevice
);
606 // returns true if this is a debug machine
607 BOOL
CIoSupport::IsDebug()
610 return (XboxKrnlVersion
->Qfe
& 0x8000) || ((DWORD
)XboxHardwareInfo
& 0x10);
617 VOID
CIoSupport::GetXbePath(char* szDest
)
620 //Function to get the XBE Path like:
621 //E:\DevKit\xbplayer\xbplayer.xbe
623 char szTemp
[MAX_PATH
];
624 char cDriveLetter
= 0;
626 strncpy(szTemp
, XeImageFileName
->Buffer
+ 8, XeImageFileName
->Length
- 8);
628 GetDrive(szTemp
, &cDriveLetter
);
630 strncpy(szTemp
, XeImageFileName
->Buffer
+ 29, XeImageFileName
->Length
- 29);
631 szTemp
[XeImageFileName
->Length
- 29] = 0;
633 sprintf(szDest
, "%c:\\%s", cDriveLetter
, szTemp
);
636 wchar_t szAppPathW
[MAX_PATH
] = L
"";
637 ::GetModuleFileNameW(0, szAppPathW
, sizeof(szAppPathW
) - 1);
638 CStdStringW strPathW
= szAppPathW
;
640 g_charsetConverter
.wToUTF8(strPathW
,strPath
);
641 strncpy(szDest
,strPath
.c_str(),strPath
.length()+1);
644 char given_path
[2*MAXPATHLEN
];
645 uint32_t path_size
= 2*MAXPATHLEN
;
647 result
= _NSGetExecutablePath(given_path
, &path_size
);
649 realpath(given_path
, szDest
);
651 /* Get our PID and build the name of the link in /proc */
652 pid_t pid
= getpid();
653 char linkname
[64]; /* /proc/<pid>/exe */
654 snprintf(linkname
, sizeof(linkname
), "/proc/%i/exe", pid
);
656 /* Now read the symbolic link */
658 int ret
= readlink(linkname
, buf
, 1024);
665 bool CIoSupport::DriveExists(char cDriveLetter
)
667 cDriveLetter
= toupper(cDriveLetter
);
669 // new kernel detection method
670 if (m_fPartitionTableIsValid
)
673 ANSI_STRING drive_string
;
676 OBJECT_ATTRIBUTES oa
;
677 IO_STATUS_BLOCK iosb
;
679 sprintf(szDrive
, "\\??\\%c:", cDriveLetter
);
680 RtlInitAnsiString(&drive_string
, szDrive
);
682 oa
.Attributes
= OBJ_CASE_INSENSITIVE
;
683 oa
.ObjectName
= &drive_string
;
684 oa
.RootDirectory
= 0;
686 status
= NtOpenFile(&hTemp
, GENERIC_READ
| GENERIC_WRITE
, &oa
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
688 if (NT_SUCCESS(status
))
698 LARGE_INTEGER drive_size
= GetDriveSize();
699 // old kernel detection method
700 if (cDriveLetter
== 'F')
702 // if the drive is bigger than the old 8gb drive (plus a bit of room for error),
703 // the F drive can exist
704 if (drive_size
.QuadPart
>= 9000000000)
708 if (cDriveLetter
== 'G')
710 // if the kernel is set to use partitions 6 and 7 by default
711 // the g drive can exist
712 if(((XboxKrnlVersion
->Qfe
& 67) == 67))
714 // not all kernel versions return 67, if the drive is bigger than
715 // 137 gb drive (plus a bit of room for error), the G drive can exist
716 else if ( drive_size
.QuadPart
>= 150000000000 )
723 if (cDriveLetter
< 'A' || cDriveLetter
> 'Z')
727 DWORD bitposition
= cDriveLetter
- 'A';
729 drivelist
= GetLogicalDrives();
734 return (drivelist
>> bitposition
) & 1;
740 bool CIoSupport::PartitionExists(int nPartition
)
743 char szPartition
[32];
744 ANSI_STRING part_string
;
747 OBJECT_ATTRIBUTES oa
;
748 IO_STATUS_BLOCK iosb
;
750 sprintf(szPartition
, "\\Device\\Harddisk0\\Partition%u", nPartition
);
751 RtlInitAnsiString(&part_string
, szPartition
);
753 oa
.Attributes
= OBJ_CASE_INSENSITIVE
;
754 oa
.ObjectName
= &part_string
;
755 oa
.RootDirectory
= 0;
757 status
= NtOpenFile(&hTemp
, GENERIC_READ
| GENERIC_WRITE
, &oa
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
759 if (NT_SUCCESS(status
))
771 LARGE_INTEGER
CIoSupport::GetDriveSize()
773 LARGE_INTEGER drive_size
;
776 char szHardDrive
[32] = "\\Device\\Harddisk0\\Partition0";
777 ANSI_STRING hd_string
;
778 OBJECT_ATTRIBUTES oa
;
779 IO_STATUS_BLOCK iosb
;
780 DISK_GEOMETRY disk_geometry
;
783 RtlInitAnsiString(&hd_string
, szHardDrive
);
784 drive_size
.QuadPart
= 0;
786 oa
.Attributes
= OBJ_CASE_INSENSITIVE
;
787 oa
.ObjectName
= &hd_string
;
788 oa
.RootDirectory
= 0;
790 status
= NtOpenFile(&hDevice
, GENERIC_READ
| GENERIC_WRITE
, &oa
, &iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_SYNCHRONOUS_IO_ALERT
);
791 if (!NT_SUCCESS(status
))
794 status
= NtDeviceIoControlFile(hDevice
, NULL
, NULL
, NULL
, &iosb
,
795 IOCTL_DISK_GET_DRIVE_GEOMETRY
, NULL
, 0, &disk_geometry
, sizeof(disk_geometry
));
797 CloseHandle(hDevice
);
799 if (!NT_SUCCESS(status
))
802 drive_size
.QuadPart
= disk_geometry
.BytesPerSector
*
803 disk_geometry
.SectorsPerTrack
*
804 disk_geometry
.TracksPerCylinder
*
805 disk_geometry
.Cylinders
.QuadPart
;
809 drive_size
.QuadPart
= 0;
813 bool CIoSupport::ReadPartitionTable()
818 retval
= ReadPartitionTable(&m_partitionTable
);
819 if (retval
== STATUS_SUCCESS
)
821 m_fPartitionTableIsValid
= true;
826 m_fPartitionTableIsValid
= false;
834 bool CIoSupport::HasPartitionTable()
836 return m_fPartitionTableIsValid
;
839 void CIoSupport::MapExtendedPartitions()
842 if (!m_fPartitionTableIsValid
)
844 char szDevice
[32] = "\\Harddisk0\\Partition0";
846 // we start at 5 - the first 5 partitions are the mandatory standard Xbox partitions
847 // we don't deal with those here.
848 for (int i
= EXTEND_PARTITION_BEGIN
; i
<= EXTEND_PARTITION_END
; i
++)
850 if (m_partitionTable
.pt_entries
[i
- 1].pe_flags
& PE_PARTFLAGS_IN_USE
)
852 driveletter
= 'A' + i
- 1;
853 CLog::Log(LOGINFO
, " map drive %c:", driveletter
);
854 szDevice
[20] = '1' + i
- 1;
855 MapDriveLetter(driveletter
, szDevice
);
861 unsigned int CIoSupport::ReadPartitionTable(PARTITION_TABLE
*p_table
)
865 OBJECT_ATTRIBUTES obj_attr
;
866 IO_STATUS_BLOCK io_stat_block
;
869 unsigned int ioctl_cmd_in_buf
[100];
870 unsigned int ioctl_cmd_out_buf
[100];
871 unsigned int partition_table_addr
;
873 memset(p_table
, 0, sizeof(PARTITION_TABLE
));
875 RtlInitAnsiString(&a_file
, "\\Device\\Harddisk0\\partition0");
876 obj_attr
.RootDirectory
= 0;
877 obj_attr
.ObjectName
= &a_file
;
878 obj_attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
880 stat
= NtOpenFile(&handle
, (GENERIC_READ
| 0x00100000), &obj_attr
, &io_stat_block
, (FILE_SHARE_READ
| FILE_SHARE_WRITE
), 0x10);
882 if (stat
!= STATUS_SUCCESS
)
887 memset(ioctl_cmd_out_buf
, 0, sizeof(ioctl_cmd_out_buf
));
888 memset(ioctl_cmd_in_buf
, 0, sizeof(ioctl_cmd_in_buf
));
889 ioctl_cmd_in_buf
[0] = IOCTL_SUBCMD_GET_INFO
;
892 stat
= NtDeviceIoControlFile(handle
, 0, 0, 0, &io_stat_block
,
893 IOCTL_CMD_LBA48_ACCESS
,
894 ioctl_cmd_in_buf
, sizeof(ioctl_cmd_in_buf
),
895 ioctl_cmd_out_buf
, sizeof(ioctl_cmd_out_buf
));
898 if (stat
!= STATUS_SUCCESS
)
903 if ((ioctl_cmd_out_buf
[LBA48_GET_INFO_MAGIC1_IDX
] != LBA48_GET_INFO_MAGIC1_VAL
) ||
904 (ioctl_cmd_out_buf
[LBA48_GET_INFO_MAGIC2_IDX
] != LBA48_GET_INFO_MAGIC2_VAL
))
907 return STATUS_UNSUCCESSFUL
;
910 partition_table_addr
= ioctl_cmd_out_buf
[LBA48_GET_INFO_LOWCODE_BASE_IDX
];
911 partition_table_addr
+= ioctl_cmd_out_buf
[LBA48_GET_INFO_PART_TABLE_OFS_IDX
];
913 memcpy(p_table
, (void *)partition_table_addr
, sizeof(PARTITION_TABLE
));
915 return STATUS_SUCCESS
;
917 return (unsigned int) -1;