请问如何读取光驱的绝对扇区内容? 150 大分. 有DELPHI可用源码再加 150!!(150分)

  • 主题发起人 主题发起人 白河愁
  • 开始时间 开始时间

白河愁

Unregistered / Unconfirmed
GUEST, unregistred user!
比如读取第0扇区的第256字节到512字节,求控件或源代码, FOR DELPHI5
读出的数据应可即时处理,比如是 buf:array[1..16384]of char,不能是写到文件或者
是其它不方便途径.要求各种模式的光盘均可读到.
 
procedure TAudioCD.set_drive_letter (c: char);
var
cd_name: string;
er: integer;
begin
FDriveLetter := UpCase (C);
cd_name := '//./' + FDriveLetter + ':';
// connect to the CD-ROM directly, note the file name used....
hCD := CreateFile (PChar (cd_name), GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, 0, 0);
if hCD = INVALID_HANDLE_VALUE then
begin
er := GetLastError;
Raise Exception.Create ('Failed to connect to CD-ROM drive, error ' +
IntToStr (er));
Exit;
end;
end;
 
建议读一下创新公司(creative)出的多媒体程序设计一书,里面对光驱控制有比较详细的说明
 
我记得光盘的格式并不是和硬盘一样的分区表格式的啊?记得上次有谁说过光盘的是一种
ISO9****的格式,在这里面并没有扇区这一概念的?也许我应该去书店找找这类书看看了:)
 
to RedBeret:
FDriveLetter,hcd来的?
createfile不是创建文件吗?关读取什么事?且光驱又怎能创建文件?
这段程序最多是判断一个盘能否读写而已吧?
to ht99:
请问哪儿有这样的书呢?
to iamfly:
当然有这样的说法,要不找一个CDRWIN看看就知道了.
 
光盘并没有绝对扇区,而是一个包你只有读它的相对扇区!
 
不是有0,1,2,3....扇区吗?这不算绝对吗?
相对是相对于什么?
 
to :ht99
where could I find the book you refer on web?
 
嗯, 可以读出来啊, 不过, 光盘的确没有扇区这个概念, 而叫块(Block), 因为光盘
上都是一条条光轨而已, 不像磁盘那样的同心圆方式的磁道.

看看ASPI(Advanced SCSI Program Interface)或者MSDN中的SPTI(SCSI Pass Through
Interface)中的内容吧, 如果你想直接读出来, 必须通过SCSI接口去读, 可以读出原
始数据, 否则只能通过系统的接口读取处理后的数据.

现在有很多抓音轨的程序, 建议看看, 实际上是一样的算法, 如果你只是读原始数据的话.
 
delphibyte兄,哪儿有类似的程序呢?
 
完全还是没有人懂?
 
去查msdn吧,用CreateFile和DeviceIoControl。
 
DeviceIoControl 是?
 
以下是msdn中有关Read CD-ROM Sectors的内容大意:
1、在winNT系列中,与读硬盘没什么不同,用CreateFile打开光驱(如//./F:),再用
ReadFile读取内容,最后用CloseHandle关闭光驱,中间可以用VirtualAlloc进行定
位。由于必须以整扇区读取,所以最好用DeviceIoControl向光驱发送
IOCTL_CDROM_GET_DRIVE_GEOMETRY命令得到扇区大小。
2、在win9x系列中要麻烦得多,需要建立一个32位dll向16位dll的调用,由16位的dll
在v86模式下调用mscdex的int 2fh功能实现,当然,实际上mscdex的功能是由cdfs
实现的,并不是真的要装载mscdex。我们的程序就调用那个32位dll完成功能。
具体内容请见msdn之Q138434和Q137813。

但是,以上win9x中的方法看起来太麻烦。我想,既然只是调用int 2fh,应该可以调用
vwin32来实现,即用CreateFile打开//./vwin32,再用DeviceIoControl向vwin32发命
令调用int 2fh,就不用调用一堆的dll了。msdn中Eject Removable Media(比如弹出
光驱托盘)就是用的这个方法,可惜我始终就是查不到Load Removable Media的调用
(比如收起光驱托盘)。[:(]
 
这个....能否给个EXAMPLE?
 
jdshoot讲的精彩~~~~~~~,来个Mail~~~~~~:),继续听课。
 
先来两个msdn中的例子吧,我暂时没时间翻译(忙啊,原谅一下吧,或者等我有时间[:D][:P])。
win9x的翻译可能比较困难,用vwin32的应该比较容易,我想好了再写吧。
//winNT
#include <windows.h>
#include <winioctl.h> // From the Win32 SDK /Mstools/Include
#include "ntddcdrm.h" // From the Windows NT DDK /Ddk/Src/Storage/Inc

/*
This code reads sectors 16 and 17 from a compact disc and writes
the contents to a disk file named Sector.dat
*/


{
HANDLE hCD, hFile;
DWORD dwNotUsed;

// Disk file that will hold the CD-ROM sector data.
hFile = CreateFile ("sector.dat",
GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);

// For the purposes of this sample, drive F: is the CD-ROM
// drive.
hCD = CreateFile ("////.//F:", GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL);

// If the CD-ROM drive was successfully opened, read sectors 16
// and 17 from it and write their contents out to a disk file.
if (hCD != INVALID_HANDLE_VALUE)
{
DISK_GEOMETRY dgCDROM;
PREVENT_MEDIA_REMOVAL pmrLockCDROM;

// Lock the compact disc in the CD-ROM drive to prevent accidental
// removal while reading from it.
pmrLockCDROM.PreventMediaRemoval = TRUE;
DeviceIoControl (hCD, IOCTL_CDROM_MEDIA_REMOVAL,
&pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
0, &dwNotUsed, NULL);

// Get sector size of compact disc
if (DeviceIoControl (hCD, IOCTL_CDROM_GET_DRIVE_GEOMETRY,
NULL, 0, &dgCDROM, sizeof(dgCDROM),
&dwNotUsed, NULL))
{
LPBYTE lpSector;
DWORD dwSize = 2 * dgCDROM.BytesPerSector; // 2 sectors

// Allocate buffer to hold sectors from compact disc. Note that
// the buffer will be allocated on a sector boundary because the
// allocation granularity is larger than the size of a sector on a
// compact disk.
lpSector = VirtualAlloc (NULL, dwSize,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);

// Move to 16th sector for something interesting to read.
SetFilePointer (hCD, dgCDROM.BytesPerSector * 16,
NULL, FILE_BEGIN);

// Read sectors from the compact disc and write them to a file.
if (ReadFile (hCD, lpSector, dwSize, &dwNotUsed, NULL))
WriteFile (hFile, lpSector, dwSize, &dwNotUsed, NULL);

VirtualFree (lpSector, 0, MEM_RELEASE);
}

// Unlock the disc in the CD-ROM drive.
pmrLockCDROM.PreventMediaRemoval = FALSE;
DeviceIoControl (hCD, IOCTL_CDROM_MEDIA_REMOVAL,
&pmrLockCDROM, sizeof(pmrLockCDROM), NULL,
0, &dwNotUsed, NULL);

CloseHandle (hCD);
CloseHandle (hFile);
}
}
//------------------------------------------------------------------------------
//win9x
// Code inside the Win32 DLL (the 32-bit side of the thunk)
// ReadSectorsFromCD() is exported by the DLL so that it can be called
// by Win32-based applications.

#include <windows.h>

#define CD_SECTOR_SIZE 2048


__declspec(dllexport)
BOOL WINAPI ReadSectorsFromCD (BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpBuff);

// Prototype for thunk function in 16-bit DLL.
BOOL FAR PASCAL ReadCDRomSectors (BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpBuffer);

/*-------------------------------------------------------------------
ReadSectorsFromCD()

Calls the thunked function, ReadCDRomSectors(). This function is
exported by the Win32 DLL and thus is callable from Win32-based
applications.

Parameters:

bDrive
Drive letter of CD-ROM drive to read from. Specified as
a character in the range 'A', 'B', 'C', ..., 'Z'. May be
upper- or lower-case.

dwStartSector
First sector to read.

wSectors
Number of sectors to read.

lpBuffer
Buffer to contain sector data. Must be large enough to
accommodate all sectors being read. Because this buffer is
provided to the 16-bit DLL via a thunk, its maximum
length is limited to 64K.

Example use:
// Read 5 sectors from CD-ROM drive E: starting at sector 16.
fResult = ReadSectorsFromCD ('E', 16, 5, lpBuff);

Return Value
Returns TRUE if successful, or FALSE if an error occurred
in reading or if a parameter was invalid.

-------------------------------------------------------------------*/
__declspec(dllexport)

BOOL WINAPI ReadSectorsFromCD (BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpBuff)
{
// Call 16-bit DLL to read sectors via a 32->16 thunk
return ReadCDRomSectors (bDrive, dwStartSector, wSectors, lpBuff);

}

//--------------------------------------------------------------------
// Contents of the thunk script


enablemapdirect3216 = true;
typedef unsigned short WORD; typedef unsigned long DWORD; typedef unsigned char BYTE, *LPBYTE;

typedef bool BOOL;

BOOL ReadCDRomSectors (BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpBuffer)
{
lpBuffer = inout;

}

//--------------------------------------------------------------------
// Code inside the 16-bit DLL. This code implements the 16-bit side of
// the thunk, and is where the calls to MSCDEX are made to read
// sectors from a compact disc.

#include <windows.h>
#include <string.h>
#include <ctype.h>

// Cooked-mode sector size in bytes
#define CD_SECTOR_SIZE 2048

// Maximum sector buffer size in bytes
#define MAX_BUFFER_LENGTH 65536

// Maximum number of sectors for each read request
#define MAX_CD_SECTORS_TO_READ ((MAX_BUFFER_LENGTH) / /
(CD_SECTOR_SIZE))

// Processor flags masks -- use for testing wFlags member of RMCS
#define CARRY_FLAG 0x0001

// Real-mode call structure for making DPMI Simulate Real Mode
// Interrupt calls.

typedef struct tagRMCS {
DWORD edi, esi, ebp, RESERVED, ebx, edx, ecx, eax;
WORD wFlags, es, ds, fs, gs, ip, cs, sp, ss;

} RMCS, FAR* LPRMCS;

BOOL FAR PASCAL __export ReadCDRomSectors (BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpBuffer);

BOOL FAR PASCAL MSCDEX_ReadSector (BYTE bDrive,
DWORD dwStartSector,
LPBYTE RMlpBuffer);


BOOL FAR PASCAL SimulateRM_Int (BYTE bIntNum, LPRMCS lpCallStruct);
void FAR PASCAL BuildRMCS (LPRMCS lpCallStruct);

/*-------------------------------------------------------------------
ReadCDRomSectors()

Reads a specified number of sectors from a CD-ROM.

Parameters:

bDrive
Drive letter of CD-ROM drive to read from. Specified as
a character in the range 'A', 'B', 'C', ..., 'Z'. May be
upper- or lower-case.

dwStartSector
First sector to read.

wSectors
Number of sectors to read.

lpBuffer
Buffer to contain sector data. Must be large enough to
accommodate all sectors being read. Since this buffer is
provided by the calling Win32 application, no more than
the first 64K bytes will be used.

Return Value
Returns TRUE if successful, or FALSE if an error occurred
in reading or if a parameter was invalid.

-------------------------------------------------------------------*/

BOOL FAR PASCAL __export ReadCDRomSectors (BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpBuffer)
{
BOOL fResult;
DWORD cbOffset;
DWORD i;
DWORD gdaBuffer; // Return value of GlobalDosAlloc().
LPBYTE RMlpBuffer; // Real-mode buffer pointer
LPBYTE PMlpBuffer; // Protected-mode buffer pointer


// Convert drive letter into drive number for MSCDEX call.
bDrive = toupper(bDrive) - 'A';

/*
Validate parameters:
bDrive must be between 0 and 25, inclusive.
lpBuffer must not be NULL.
wSectors must be between 1 and the maximum number of
sectors that can fit into a 64K buffer, inclusive.
*/
if (bDrive > 25 || !lpBuffer)
return FALSE;

if (!wSectors || (wSectors > MAX_CD_SECTORS_TO_READ))
return FALSE;

/*
Allocate buffer for MSCDEX call. This buffer must be below 1MB
because the MSCDEX function will be called using DPMI. Like real-
mode MSCDEX.EXE, CDFS implements the MSCDEX API as V86-mode
Interrupt 2Fh functions.

Free memory below 1MB is relatively scarce, so allocating a
small sector buffer increases the chances that it can be
allocated no matter how many other applications and MS-DOS
device drivers are running. Also, a small sector buffer leaves
more memory for other applications to use.
*/
gdaBuffer = GlobalDosAlloc (CD_SECTOR_SIZE);

if (!gdaBuffer)
return FALSE;

RMlpBuffer = (LPBYTE)MAKELONG(0, HIWORD(gdaBuffer));
PMlpBuffer = (LPBYTE)MAKELONG(0, LOWORD(gdaBuffer));

// Call MSCDEX to read each sector.
for (i = cbOffset = 0;
i < wSectors;
i++, cbOffset += CD_SECTOR_SIZE)
{
if (fResult = MSCDEX_ReadSector (bDrive,
dwStartSector + i,
RMlpBuffer))
_fmemcpy (lpBuffer + cbOffset, PMlpBuffer, CD_SECTOR_SIZE);
else
break;
}

GlobalDosFree (LOWORD(gdaBuffer));

return (fResult);

}

/*-------------------------------------------------------------------
MSCDEX_ReadSector()

Calls MSCDEX to read a single sector from a CD-ROM compact disc.

Parameters:

bDrive
Drive number of CD-ROM drive to read from. Expected to be
a number in the following series: 0 = A, 1 = B, 2 = C, etc.

dwStartSector
First sector of read.

RMlpBuffer
Real-mode segment:offset pointer to a buffer that will receive
sector data. Must be large enough to accommodate a single
sector in cooked mode.

Return Value
Returns TRUE if successful, or FALSE if an error occurred in
reading.

-------------------------------------------------------------------*/

BOOL FAR PASCAL MSCDEX_ReadSector (BYTE bDrive,
DWORD dwStartSector,
LPBYTE RMlpBuffer)
{
RMCS callStruct;
BOOL fResult;

/*
Prepare DPMI Simulate Real Mode Interrupt call structure with
the register values used to make the MSCDEX Absolute read call.
Then, call MSCDEX using DPMI and check for errors in both the DPMI
call and the MSCDEX call.
*/
BuildRMCS (&callStruct);
callStruct.eax = 0x1508; // MSCDEX Absolute read
callStruct.ebx = LOWORD(RMlpBuffer); // Offset of sect buffer
callStruct.es = HIWORD(RMlpBuffer); // Segment of sect buffer
callStruct.ecx = bDrive; // 0=A, 1=B, 2=C, etc.
callStruct.edx = 1; // Read one sector
callStruct.esi = HIWORD(dwStartSector);
callStruct.edi = LOWORD(dwStartSector);

if (fResult = SimulateRM_Int (0x2F, &callStruct))
fResult = !(callStruct.wFlags & CARRY_FLAG);

return fResult;

}

/*-------------------------------------------------------------------
SimulateRM_Int()

Allows protected-mode software to execute real-mode interrupts
such as calls to MS-DOS, MS-DOS TSRs, MS-DOS device drivers.

This function implements the "Simulate Real Mode Interrupt"
function of the DPMI specification v0.9 and later.

Parameters:

bIntNum
Number of the interrupt to simulate.

lpCallStruct
Call structure that contains params (register values)
for bIntNum.

Return Value
SimulateRM_Int returns TRUE if it succeeded or FALSE if
it failed.

Comments
lpCallStruct is a protected-mode selector:offset address, not
a real-mode segment:offset address.

-------------------------------------------------------------------*/
BOOL FAR PASCAL SimulateRM_Int (BYTE bIntNum, LPRMCS lpCallStruct) {

BOOL fRetVal = FALSE; // Assume failure

_asm {
push di
mov ax, 0300h ; DPMI Simulate Real Mode Interrupt
mov bl, bIntNum ; Number of the interrupt to simulate
mov bh, 01h ; Bit 0 = 1; all other bits must be 0
xor cx, cx ; No words to copy from PM to RM stack
les di, lpCallStruct ; Real mode call structure
int 31h ; Call DPMI
jc END1 ; CF set if error occurred

mov fRetVal, TRUE
END1:
pop di
}
return (fRetVal);

}

/*-------------------------------------------------------------------
BuildRMCS()

Initializes a real-mode call structure by zeroing all its members.

Parameters:

lpCallStruct
Points to a real-mode call structure

Return Value
None.

Comments
lpCallStruct is a protected-mode selector:offset address,
not a real-mode segment:offset address.

-------------------------------------------------------------------*/

void FAR PASCAL BuildRMCS (LPRMCS lpCallStruct)
{
_fmemset (lpCallStruct, 0, sizeof(RMCS));
}
 
c++? 懂就不在这里问 。
 
后退
顶部