📄 kernel.cpp
字号:
/***********************************************************************
Copyright 2002 Ben Rudiak-Gould.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/
// Under Win2K the DVDSynth "kernel" runs in user mode. It duplicates some
// of the functionality of the Win95 kernel-mode code.
#include "kernel.h"
#include "miniport.h"
#include "asm.h"
#include "../dvdproxy2k/dvdproxy2k.h"
#include "../include/dvdsynth-device.h"
#include <stdio.h>
#include <process.h>
namespace KernelThread {
void AsyncDispatch(unsigned char* buffer, scsi_result_t* result_storage, HANDLE event_done);
}
extern DvsBasePluginCallbacks* g_callbacks; // in VDevice.cpp
void AsyncUserModeCall(void (*f)(void*, int), void* p, int i); // in VDevice.cpp
/*******************************************************************\
\*******************************************************************/
class Semaphore {
HANDLE s;
public:
Semaphore() {
s = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
}
void P() {
WaitForSingleObject(s, INFINITE);
}
bool TimedP(unsigned timeout) {
return WaitForSingleObject(s, timeout) == WAIT_OBJECT_0;
}
void V() {
ReleaseSemaphore(s, 1, NULL);
}
};
class CriticalSection {
CRITICAL_SECTION cs;
public:
CriticalSection() { InitializeCriticalSection(&cs); }
~CriticalSection() { DeleteCriticalSection(&cs); }
void Acquire() { EnterCriticalSection(&cs); }
void Release() { LeaveCriticalSection(&cs); }
};
// clobbers "next" pointer in Msg class
template<class Msg>
class MessageQueue {
CriticalSection mutex;
Semaphore slots_used;
Msg* head;
Msg** tail;
public:
MessageQueue() {
head = 0;
tail = &head;
}
void Put(Msg* msg) {
mutex.Acquire();
*tail = msg;
tail = &msg->next;
*tail = 0;
mutex.Release();
slots_used.V();
}
Msg* Get() {
slots_used.P();
mutex.Acquire();
Msg* result = head;
if (result) {
head = result->next;
if (head == 0) {
tail = &head;
}
}
mutex.Release();
return result;
}
};
/*******************************************************************\
\*******************************************************************/
#ifdef __GNUC__
#define ASM __asm__ (
#define ENDASM );
#define L(l) #l ":\n"
#define EAX "%eax"
#define EBX "%ebx"
#define ECX "%ecx"
#define EDX "%edx"
#define ESI "%esi"
#define EDI "%edi"
#define EBP "%ebp"
#define ESP "%esp"
#define RI(r,i) #i "(" r ")"
#define RR(r1,r2) "(" r1 "," r2 ")"
#define RRI(r1,r2,i) #i "(" r1 "," r2 ")"
#define RRS(r1,r2,s) "(" r1 "," r2 "," #s ")"
#define RRSI(r1,r2,s,i) #i "(" r1 "," r2 "," #s ")"
#define PUSH(r) "\tpush\t" r "\n"
#define POP(r) "\tpop\t" r "\n"
#define RET "\tret\n"
#define RETP(n) "\tretn\t" #n "\n"
#define MOV(d,s) "\tmovl\t" s "," d "\n"
#define DEC(r) "\tdecl\t" r "\n"
#define SHR(r,n) "\tshrl\t" r "," #n "\n"
#define JZ(l) "\tjz\t" #l "\n"
#define JNZ(l) "\tjnz\t" #l "\n"
#define CALL(a) "\tcall\t" a "\n"
#if 0
__declspec(naked)
void* __cdecl MakeThunkCall(void* func, void* args, unsigned arg_bytes) {
ASM
PUSH(EBP)
MOV(EBP,ESP)
MOV(EDX,RI(EBP,12)) /* args */
MOV(ECX,RI(EBP,16)) /* arg_bytes */
SHR(ECX,2)
JZ(make_call)
L(copy_loop)
DEC(ECX)
PUSH(RRS(EDX,ECX,4))
JNZ(copy_loop)
L(make_call)
CALL(RI(EBP,8)) /* func */
MOV(ESP,EBP)
POP(EBP)
RET
ENDASM
}
#endif
#else
__declspec(naked)
void* __cdecl MakeThunkCall(void* func, void* args, unsigned arg_bytes) {
__asm {
push ebp
mov ebp,esp
mov edx,[ebp+12] /* args */
mov ecx,[ebp+16] /* arg_bytes */
shr ecx,2
jz make_call
copy_loop:
dec ecx
push [edx+ecx*4]
jnz copy_loop
make_call:
call [ebp+8] /* func */
mov esp,ebp
pop ebp
ret
}
}
#endif
/*******************************************************************\
\*******************************************************************/
namespace KernelThread {
DvsDeviceKernel* handler[num_bays];
struct KernelRequest {
enum { dispatch, setHandler, callInitFunc, driverCall, quit } type;
union {
struct {
unsigned char* buffer;
scsi_result_t* result_storage;
HANDLE event_done;
} dispatch_args;
struct {
int target;
DvsDeviceKernel* kernel_handler;
} setHandler_args;
struct {
HMODULE hmodule;
} callInitFunc_args;
struct {
void* func;
void* args;
int arg_bytes;
void** return_value;
HANDLE return_notify;
} driverCall_args;
};
KernelRequest* next;
};
MessageQueue<KernelRequest> request_queue;
void MemSet(void* dst, int val, unsigned long count) {
memset(dst, val, count);
}
void MemCpy(void* dst, const void* src, unsigned long count) {
memcpy(dst, src, count);
}
void DebugPrintf(const char* fmt, ...) {
OutputDebugString("DvsDockingBayKernelGlobal::DebugPrintf\n");
}
int ReadFile(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 read = count;
if (::ReadFile(h, buf, count, &read, NULL))
return read;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -