📄 kernel.cpp
字号:
// FIXME: error reporting
return 0;
}
int WriteFile(dvs_file_handle file_handle, unsigned offset, unsigned offset_high, unsigned count, void* buf) {
HANDLE h = HANDLE(file_handle);
LONG oh = offset_high;
::SetFilePointer(h, offset, &oh, FILE_BEGIN);
DWORD written = count;
if (::WriteFile(h, buf, count, &written, NULL))
return written;
else
// FIXME: error reporting
return 0;
}
void SetEvent(unsigned event_handle) {
::SetEvent(HANDLE(event_handle));
}
DvsDockingBayKernelGlobal kernel_callbacks = {
MemSet,
MemCpy,
DebugPrintf,
AsyncUserModeCall,
ReadFile,
WriteFile,
SetEvent,
};
scsi_result_t SendUserModeRequest(UserModeRequest* req, unsigned char* buffer, SenseData* sense) {
// check CDB length
static const BYTE expected_cdb_lengths[] = { 6, 10, 10, 0, 0, 12, 0, 0 };
BYTE expected_cdb_length = expected_cdb_lengths[req->cdb[0]>>5];
if (expected_cdb_length ? (expected_cdb_length > req->cdb_length) : (req->cdb_length < 6 || req->cdb_length > 16)) {
return MAKE_SCSIRESULT_ERROR(0x51A00); // PARAMETER LIST LENGTH ERROR
}
// convert READ(6) and READ(12) commands into READ(10)
if (req->cdb[0] == SCSIOP_READ6) {
req->cdb_length = 10;
req->cdb[9] = req->cdb[5]; // control
req->cdb[8] = req->cdb[4]; // transfer length
req->cdb[7] = !req->cdb[4];
req->cdb[6] = 0;
req->cdb[5] = req->cdb[3]; // logical block address
req->cdb[4] = req->cdb[2];
req->cdb[3] = req->cdb[1] & 0x1F;
req->cdb[2] = 0;
req->cdb[1] = req->cdb[1] & 0xE0;
req->cdb[0] = SCSIOP_READ;
} else if (req->cdb[0] == SCSIOP_READ12) {
req->cdb_length = 10;
if (req->cdb[6] == 0 && req->cdb[7] == 0) {
req->cdb[7] = req->cdb[8];
req->cdb[8] = req->cdb[9];
req->cdb[9] = req->cdb[11];
req->cdb[0] = SCSIOP_READ;
} else {
// The caller wants to transfer 65536 or
// more *blocks* in one call -- unlikely!
return SCSIRESULT_INVALID_CDB;
}
}
// dispatch
DvsDeviceKernel* handlr = handler[req->target-1];
if (handlr) {
scsi_result_t result = handlr->ScsiCommand(handlr, req->cdb, req->cdb_length, buffer, &req->data_transfer_length, req->data_transfer_direction, sense);
return result;
} else {
return MAKE_SCSIRESULT(SRB_STATUS_INVALID_TARGET_ID,0,0,0,0);
}
}
const SenseData default_sense = { 0x70, 0, 0, {0,0,0,0}, 10, {0,0,0,0}, 0, 0, 0, {0,0,0} };
scsi_result_t DoDispatch(unsigned char* buffer) {
SenseData sense = default_sense;
UserModeRequest* req = (UserModeRequest*)buffer;
scsi_result_t result = SendUserModeRequest(req, buffer+sizeof(UserModeRequest), &sense);
sense.sense_key = (sense.sense_key & 0xF0) | SCSIRESULT_SENSEKEY(result);
sense.asc = SCSIRESULT_ASC(result);
sense.ascq = SCSIRESULT_ASCQ(result);
if (!(req->data_transfer_direction & 1)) {
req->data_transfer_length = 0;
}
*(SenseData*)(buffer + sizeof(UserModeRequest) + req->data_transfer_length) = sense;
return result;
}
unsigned __stdcall ThreadMain(void*) {
for (;;) {
KernelRequest* req = request_queue.Get();
switch (req->type) {
case KernelRequest::quit:
return 0;
case KernelRequest::dispatch:
*req->dispatch_args.result_storage = DoDispatch(req->dispatch_args.buffer);
::SetEvent(req->dispatch_args.event_done);
break;
case KernelRequest::setHandler:
//assert(req->setHandler_args.target > 0 && req->setHandler_args.target <= num_bays);
handler[req->setHandler_args.target-1] = req->setHandler_args.kernel_handler;
ListenerThread::AsyncRescanBus();
break;
case KernelRequest::callInitFunc:
{
typedef void __cdecl DvdsynthDriverInit_func(DvsDockingBayKernelGlobal*);
DvdsynthDriverInit_func* init_func = (DvdsynthDriverInit_func*)
GetProcAddress(req->callInitFunc_args.hmodule, "DvdsynthDriverInit");
if (init_func) {
init_func(&kernel_callbacks);
}
}
break;
case KernelRequest::driverCall:
*req->driverCall_args.return_value = MakeThunkCall(req->driverCall_args.func,
req->driverCall_args.args, req->driverCall_args.arg_bytes);
::SetEvent(req->driverCall_args.return_notify);
break;
default:
/*assert(0)*/;
}
delete req;
}
}
HANDLE hthread;
void Spawn() {
unsigned id;
hthread = (HANDLE)_beginthreadex(NULL, 0, ThreadMain, NULL, 0, &id);
}
void AsyncDispatch(unsigned char* buffer, scsi_result_t* result_storage, HANDLE event_done) {
KernelRequest* req = new KernelRequest;
req->type = KernelRequest::dispatch;
req->dispatch_args.buffer = buffer;
req->dispatch_args.result_storage = result_storage;
req->dispatch_args.event_done = event_done;
request_queue.Put(req);
}
void AsyncSetHandler(int target, DvsDeviceKernel* kernel_handler) {
KernelRequest* req = new KernelRequest;
req->type = KernelRequest::setHandler;
req->setHandler_args.target = target;
req->setHandler_args.kernel_handler = kernel_handler;
request_queue.Put(req);
}
void AsyncCallInitFunc(HMODULE hmodule) {
KernelRequest* req = new KernelRequest;
req->type = KernelRequest::callInitFunc;
req->callInitFunc_args.hmodule = hmodule;
request_queue.Put(req);
}
void* _stdcall AsyncDriverCall(dvs_driver_handle handle, const char* exported_name, const char* types, ...) {
void* func = GetProcAddress(HMODULE(handle), exported_name);
if (func) {
KernelRequest* req = new KernelRequest;
req->type = KernelRequest::driverCall;
req->driverCall_args.func = func;
req->driverCall_args.args = (&types)+1;
req->driverCall_args.arg_bytes = lstrlen(types)*sizeof(void*);
void* result;
req->driverCall_args.return_value = &result;
static HANDLE hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
req->driverCall_args.return_notify = hDone;
request_queue.Put(req);
WaitForSingleObject(hDone, INFINITE);
return result;
} else {
char buf[256];
g_callbacks->Sprint(buf, 256, "Call to driver-exported function \"%1\" failed: the function was not found.", 0, exported_name);
MessageBox(NULL, buf, "DVDSynth", MB_OK);
return 0;
}
}
}
/*******************************************************************\
\*******************************************************************/
namespace ListenerThread {
HANDLE heventFinishedSRB = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE heventRescanBus = CreateEvent(NULL, FALSE, FALSE, NULL);
unsigned char* buffer = new unsigned char[66606];
unsigned long buffer_size = 66606;
unsigned __stdcall ThreadProc(void*) {
for (;;) {
scsi_result_t result = Miniport::GetSRB(buffer, buffer_size, 1000, 2, 5);
if (result == SCSIRESULT_SUCCESS) {
// send message
UserModeRequest* req = (UserModeRequest*)buffer;
unsigned required_buffer_size = sizeof(UserModeRequest) + req->data_transfer_length + 18 + 1024;
if (buffer_size < required_buffer_size) {
buffer_size = required_buffer_size;
printf("Resizing buffer to %d\n", buffer_size);
BYTE* new_buffer = new BYTE[buffer_size];
req = (UserModeRequest*)new_buffer;
*req = *(UserModeRequest*)buffer;
delete[] buffer;
buffer = new_buffer;
}
scsi_result_t scsi_result;
KernelThread::AsyncDispatch(buffer, &scsi_result, heventFinishedSRB);
HANDLE events[] = { heventFinishedSRB, heventRescanBus };
for (;;) {
DWORD obj = WaitForMultipleObjects(2, events, FALSE, 4000);
if (obj == WAIT_OBJECT_0) {
Miniport::RetireRequest(buffer, scsi_result);
break;
} else if (obj == WAIT_OBJECT_0+1) {
Miniport::BusChange();
} else {
Miniport::KeepAlive(5);
}
}
} else {
if (result == MAKE_SCSIRESULT_ERROR(DVDPROXY_ERROR_NEED_MORE_DATA_SPACE)) {
delete[] buffer;
buffer_size += 2048;
buffer = new unsigned char[buffer_size];
} else if (result != MAKE_SCSIRESULT_ERROR(DVDPROXY_ERROR_LISTEN_TIMEOUT)) {
printf("result = %x!\n", result);
Sleep(200);
Miniport::Init();
}
if (WAIT_OBJECT_0 == WaitForSingleObject(heventRescanBus, 0)) {
Miniport::BusChange();
}
}
}
}
void AsyncRescanBus() {
SetEvent(heventRescanBus);
}
HANDLE hthread;
void Spawn() {
unsigned id;
hthread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, &id);
}
void Join() {
WaitForSingleObject(hthread, INFINITE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -