📄 block.cpp
字号:
PBYTE pbCommand = (PBYTE) ptcCommand->CommandBlock;
PBYTE pbData = (PBYTE) ptdData->DataBlock;
DWORD dwResult = EXECUTE_FAIL;
// don't test if LUN is valid; LUNs are deprecated
// test if data block is large enough
if (ptdData->RequestLength < sizeof(READ_CAPACITY_DATA)) {
DEBUGMSG(ZONE_ERROR, (_T(
"%s host requesting less than required; ptdData->RequestLength < %u\r\n"
), pszFname, sizeof(READ_CAPACITY_DATA)));
goto EXIT;
}
ZeroMemory(pbData, ptdData->RequestLength);
ptdData->TransferLength = ptdData->RequestLength;
// pack logical block address
PREAD_CAPACITY_DATA pReadCapacityData;
pReadCapacityData = (PREAD_CAPACITY_DATA) pbData;
// -1 to return last addressable
pReadCapacityData->LastLogicalBlockAddress = ByteSwapUlong(g_diDiskInfo.di_total_sectors - 1);
// pack block length in bytes
pReadCapacityData->BlockLength = ByteSwapUlong(BytesPerSector());
dwResult = EXECUTE_PASS;
EXIT:;
return dwResult;
}
// ----------------------------------------------------------------------------
// Function: ProcessScsiStartStop
// Process a SCSI-2 START STOP command
//
// Parameters:
// ptcCommand - command block wrapper
// ----------------------------------------------------------------------------
static
DWORD
ProcessScsiStartStop(
PTRANSPORT_COMMAND ptcCommand
)
{
SETFNAME(_T("ProcessScsiStartStop"));
PBYTE pbCommand = (PBYTE) ptcCommand->CommandBlock;
DWORD dwResult = EXECUTE_FAIL;
// don't test if LUN is valid; LUNs are deprecated
if (pbCommand[4] & 0x02) {
// LoEj = 1
if (pbCommand[4] & 0x01) {
// Start = 1
// load medium
DEBUGMSG(ZONE_COMMENT, (_T("%s load medium\r\n"), pszFname));
}
else {
// Start = 0
// unload medium
DEBUGMSG(ZONE_COMMENT, (_T("%s unload medium\r\n"), pszFname));
}
}
else {
// LoEj = 0
if (pbCommand[4] & 0x01) {
// Start = 1
// start medium
DEBUGMSG(ZONE_COMMENT, (_T("%s start medium\r\n"), pszFname));
}
else {
// Start = 0
// stop medium
DEBUGMSG(ZONE_COMMENT, (_T("%s stop medium\r\n"), pszFname));
}
}
dwResult = EXECUTE_PASS;
return dwResult;
}
// ----------------------------------------------------------------------------
// Function: ProcessScsiWrite10
// Process a SCSI-2 WRITE (10) command
//
// Parameters:
// ptcCommand - command block wrapper
// ptdData - data block wrapper
// ----------------------------------------------------------------------------
static
DWORD
ProcessScsiWrite10(
PTRANSPORT_COMMAND ptcCommand,
PTRANSPORT_DATA ptdData
)
{
SETFNAME(_T("ProcessScsiWrite10"));
PBYTE pbCommand = (PBYTE) ptcCommand->CommandBlock;
PBYTE pbData = (PBYTE) ptdData->DataBlock;
DWORD dwLogicalBlockAddress;
DWORD dwTransferLength;
DWORD dwResult = EXECUTE_FAIL;
SG_REQ sgSgReq;
SG_BUF sgSgBuf;
DWORD dwBytesReturned;
BOOL fResult = FALSE;
DWORD dwIndex;
PUFI_CB pUfiCb = (PUFI_CB) pbCommand;
DEBUGCHK(pUfiCb->bReserved1 == 0);
// don't test if LUN is valid; LUNs are deprecated
if (g_hStore==NULL||g_hStore==INVALID_HANDLE_VALUE)
g_hStore=OpenStore(g_szDeviceName2);
// test if logical block address is valid
dwLogicalBlockAddress = ByteSwapUlong(pUfiCb->dwLogicalBlockAddress);
// test if transfer length is valid
dwTransferLength = ByteSwapUshort(pUfiCb->wTransferLength);
DEBUGMSG(ZONE_COMMENT, (_T(
"%s starting LBA/sector = %u, transfer length = %u (sectors)\r\n"
), pszFname, dwLogicalBlockAddress, dwTransferLength));
ptdData->TransferLength = dwTransferLength * BytesPerSector();
// is the host attempting to overwrite the virtual disk's MBR?
if ((dwLogicalBlockAddress == 0) && (g_lpbMBR != NULL)) {
DEBUGMSG(ZONE_COMMENT, (_T(
"%s write request targeting virtual disk's MBR; virtual disk's MBR is write-protected\r\n"
), pszFname));
dwResult = EXECUTE_FAIL;
goto EXIT;
}
// if partitions being exposed selectively, then an unexposed partition
// appears as unallocated space to the host; we want to prevent access to
// unexposed partitions; ensure write request does not target a sector in
// an unexposed partition
// are partitions being exposed selectively?
if (g_lpbMBR != NULL) {
// cycle through bit mast of partitions selected for exposure; (0
// denotes an unexposed partition)
for (dwIndex = 0; dwIndex < MAX_PARTTABLE_ENTRIES; dwIndex += 1) {
if ((g_bmPartitions & (1 << dwIndex)) == 0) {
// this partition is unexposed
// fetch corresponding partition table entry
PPARTENTRY pPartEntry = (PPARTENTRY) ((g_lpbPhysMBR + PARTTABLE_OFFSET) + (dwIndex * sizeof(PARTENTRY)));
// determine whether the current write request lies in the
// range of the unexposed partition
if ((dwLogicalBlockAddress >= pPartEntry->Part_StartSector) &&
(dwLogicalBlockAddress <= (pPartEntry->Part_StartSector + pPartEntry->Part_TotalSectors))
) {
DEBUGMSG(ZONE_COMMENT, (_T(
"%s write request targets unexposed partition\r\n"
), pszFname));
dwResult = EXECUTE_FAIL;
goto EXIT;
}
}
}
}
// prepare scatter/gather buffer
sgSgBuf.sb_buf = (PBYTE) pbData;
sgSgBuf.sb_len = ptdData->TransferLength;
// prepare scatter/gather request
sgSgReq.sr_start = dwLogicalBlockAddress;
sgSgReq.sr_num_sec = dwTransferLength;
sgSgReq.sr_status = 0;
sgSgReq.sr_callback = NULL;
sgSgReq.sr_num_sg = 1;
sgSgReq.sr_sglist[0] = sgSgBuf;
DWORD dwIoControlCode = (g_fLegacyBlockDriver) ? DISK_IOCTL_WRITE : IOCTL_DISK_WRITE;
fResult = DeviceIoControl(
g_hStore,
dwIoControlCode,
&sgSgReq,
sizeof(sgSgReq),
NULL,
0,
&dwBytesReturned,
NULL);
if (fResult) {
DEBUGMSG(ZONE_COMMENT, (_T(
"%s IOCTL_DISK_WRITE passed; %u bytes read\r\n"
), pszFname, dwBytesReturned));
}
else {
DWORD dwError = GetLastError();
RETAILMSG(1, (_T("%s IOCTL_DISK_WRITE failed; error = %u\r\n"
), pszFname, dwError));
goto EXIT;
}
dwResult = EXECUTE_PASS;
EXIT:;
return dwResult;
}
// ----------------------------------------------------------------------------
// Function: ProcessScsiPreventAllowMediumRemoval
// Process a SCSI-2 PREVENT ALLOW MEDIUM REMOVAL command
//
// Parameters:
// ptcCommand - command block wrapper
// ----------------------------------------------------------------------------
static
DWORD
ProcessScsiPreventAllowMediumRemoval(
PTRANSPORT_COMMAND ptcCommand
)
{
SETFNAME(_T("ProcessScsiPreventAllowMediumRemoval"));
const BYTE bPreventBit = 0x01;
PBYTE pbCommand = (PBYTE) ptcCommand->CommandBlock;
DWORD dwResult = EXECUTE_FAIL;
// don't test if LUN is valid; LUNs are deprecated
// test if prevent bit high
if (pbCommand[4] & bPreventBit) {
DEBUGMSG(ZONE_COMMENT, (_T("%s prevent enabled\r\n"), pszFname));
}
else {
DEBUGMSG(ZONE_COMMENT, (_T("%s prevent disabled\r\n"), pszFname));
}
dwResult = EXECUTE_PASS;
return dwResult;
}
// ----------------------------------------------------------------------------
// Function: ProcessScsiVerify
// Process a SCSI-2 VERIFY command
//
// Parameters:
// ptcCommand - command block wrapper
// ----------------------------------------------------------------------------
static
DWORD
ProcessScsiVerify(
PTRANSPORT_COMMAND ptcCommand
)
{
SETFNAME(_T("ProcessScsiVerify"));
PBYTE pbCommand = (PBYTE) ptcCommand->CommandBlock;
DWORD dwResult = EXECUTE_FAIL;
// don't test if LUN is valid; LUNs are deprecated
DEBUGMSG(ZONE_COMMENT, (_T(
"%s DPO = %u; BytChk = %u; RelAdr = %u\r\n"),
pszFname,
pbCommand[1] & (1 << 4), // DPO bit
pbCommand[1] & (1 << 1), // BytChk bit
pbCommand[1] & (1 << 0) // RelAdr
));
// fake the verification
dwResult = EXECUTE_PASS;
return dwResult;
}
// ----------------------------------------------------------------------------
// Function: STORE_Init
// Initialize SCSI-2 direct-access device emulator
//
// Parameters:
// pszContext - driver's configuration key
// ----------------------------------------------------------------------------
DWORD
STORE_Init(
LPCTSTR pszActiveKey
)
{
SETFNAME(_T("STORE_Init"));
HKEY hKey = NULL;
DWORD cbData;
DWORD dwError;
DWORD dwType;
BOOL fResult;
DWORD dwBytesReturned;
FUNCTION_ENTER_MSG();
// mark self as uninitialized
g_fInitialized = FALSE;
// open the client driver key
hKey = OpenDeviceKey(pszActiveKey);
if (hKey == NULL) {
dwError = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T(
"%s Failed to open device key for \"%s\"; Error = %u\r\n"
), pszFname, pszActiveKey, dwError));
goto EXIT;
}
// read name of store to expose
cbData = sizeof(g_szDeviceName);
dwError = RegQueryValueEx(hKey, PRX_DEVICE_NAME_VAL, NULL, &dwType, (PBYTE) g_szDeviceName, &cbData);
if ((dwError != ERROR_SUCCESS) || (dwType != REG_SZ)) {
DEBUGMSG(ZONE_ERROR, (_T(
"%s Failed to read %s; error = %u\r\n"
), pszFname, PRX_DEVICE_NAME_VAL, dwError));
goto EXIT;
}
g_szDeviceName[dim(g_szDeviceName) - 1] = 0; // force null-termination
_tcscpy(g_szDeviceName,L"DSK1:");
if (g_szDeviceName2[0]==0)
_tcscpy(g_szDeviceName2,L"DSK1:");
DEBUGMSG(ZONE_INIT, (_T(
"%s %s = %s\r\n"
), pszFname, PRX_DEVICE_NAME_VAL, g_szDeviceName));
// g_szDeviceName should be a valid stream name, e.g., "DSK1:"
if (_tcslen(g_szDeviceName) > PRX_STREAM_NAME_LEN) {
DEBUGMSG(ZONE_ERROR, (_T(
"%s %s is not a valid stream name\r\n"
), pszFname, g_szDeviceName));
goto EXIT;
}
// read removable media flag; default is true if flag not present
cbData = sizeof(g_dwRemovable);
dwError = RegQueryValueEx(hKey, PRX_RMB_VAL, NULL, &dwType, (PBYTE) &g_dwRemovable, &cbData);
if ( (dwError != ERROR_SUCCESS) || (dwType != REG_DWORD) ) {
DEBUGMSG(ZONE_WARNING, (_T(
"%s %s not present; default is true\r\n"
), pszFname, PRX_RMB_VAL, dwError));
}
DEBUGMSG(ZONE_INIT, (_T(
"%s %s = %u\r\n"
), pszFname, PRX_RMB_VAL, g_dwRemovable));
// open store
g_hStore = OpenStore(g_szDeviceName);
if ((g_hStore == NULL) || (g_hStore == INVALID_HANDLE_VALUE)) {
dwError = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T(
"%s failed to open store %s; error = %u\r\n"
), pszFname, g_szDeviceName, dwError));
goto EXIT;
}
DEBUGMSG(ZONE_COMMENT, (_T("%s opened store %s\r\n"), pszFname, g_szDeviceName));
// read disk information
fResult = DeviceIoControl(
g_hStore,
IOCTL_DISK_GETINFO,
NULL,
0,
&g_diDiskInfo,
sizeof(g_diDiskInfo),
&dwBytesReturned,
NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -