📄 vdevice.cpp
字号:
AsyncCallRecord* acr = (AsyncCallRecord*)lparam;
acr->f(acr->p, acr->i);
delete acr;
return 0;
} else {
if (msg == WM_APP && lparam == WM_MOUSEMOVE) {
// Because drive-letter scanning is not instantaneous, try
// to do it slightly in advance of the user's clicking on
// the icon.
static DWORD last_scan_time = 0;
DWORD current_time = GetTickCount();
if (DWORD(current_time - last_scan_time) >= 5000) {
last_scan_time = current_time;
ScanDriveLetters();
}
}
return OldWndProc(hwnd, msg, wparam, lparam);
}
}
void SubclassTrayWindow() {
HWND hwnd = (HWND)g_callbacks->GetTaskbarHWND();
OldWndProc = (WindowProcedure*)GetWindowLong(hwnd, GWL_WNDPROC);
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)MyWndProc);
}
void AsyncUserModeCall(void (*f)(void*, int), void* p, int i) {
AsyncCallRecord* acr = new AsyncCallRecord;
acr->f = f; acr->p = p; acr->i = i;
PostMessage((HWND)g_callbacks->GetTaskbarHWND(), WM_APP_APC, 0, (LPARAM)acr);
}
/*******************************************************************\
\*******************************************************************/
#define PELDR_ERR_NOERROR 0
#define PELDR_ERR_INVALIDHANDLE -1
dvs_driver_handle Driver_Load(const char* filename) {
// FIXME: corresponding work in dvdsynth95
if (strchr(filename, '\\') || strchr(filename, '/') || strchr(filename, ':')) {
MessageBox(NULL, "INTERNAL ERROR: A plugin tried to load a kernel component from outside the DVDSynth directory", "DVDSynth", MB_OK);
return 0;
}
HMODULE h = LoadLibrary(filename); // FIXME: need explicit path
if (h) {
KernelThread::AsyncCallInitFunc(h);
return dvs_driver_handle(h);
} else {
DWORD error = GetLastError();
char buf[1024];
g_callbacks->Sprint(buf, 256, "INTERNAL ERROR: There was an error loading the driver file \"%1\": ", 0, filename);
int len = lstrlen(buf);
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, buf+len, sizeof(buf)-len, NULL)) {
wsprintf(buf+len, "error #%d", error);
}
MessageBox(NULL, buf, "DVDSynth", MB_OK);
return 0;
}
}
void Driver_Unload(dvs_driver_handle handle) {
if (!FreeLibrary(HMODULE(handle))) {
MessageBox(NULL, "INTERNAL ERROR: An invalid handle was passed to UnloadDriver. This is almost certainly a plugin bug.", "DVDSynth", MB_OK);
}
}
/*******************************************************************\
\*******************************************************************/
int OpenFileRO(dvs_file_handle* phandle, const char* pathname) {
HANDLE h = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
if (h == INVALID_HANDLE_VALUE) {
return -1;
} else {
*phandle = dvs_file_handle(h);
return 0;
}
}
int CreateOrOpenFileRW(dvs_file_handle* phandle, const char* pathname, int creation_disposition) {
DWORD disp = (creation_disposition <= 0) ? OPEN_EXISTING : (creation_disposition == 1) ? CREATE_ALWAYS : CREATE_NEW;
HANDLE h = CreateFile(pathname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
return -1;
} else {
*phandle = dvs_file_handle(h);
return 0;
}
}
void CloseFile(dvs_file_handle handle) {
CloseHandle(HANDLE(handle));
}
/*******************************************************************\
\*******************************************************************/
unsigned OpenKernelEventHandle(void* user_handle) {
return unsigned(user_handle);
}
void CloseKernelEventHandle(unsigned kernel_handle) {}
/*******************************************************************\
\*******************************************************************/
scsi_result_t KernelScsiCommand(DvsDeviceKernel* kdev, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense) {
return kdev->ScsiCommand(kdev, cdb, cdblen, buffer, pbuflen, inout, sense);
}
/*******************************************************************\
\*******************************************************************/
Vector<Plugin> plugins;
typedef DvsDeviceGlobal* __cdecl DDPE_func(DvsDockingBayGlobal*);
void AddPlugin(DDPE_func* plugin_entry) {
static DvsDockingBayGlobal callbacks = {
ReserveDockingBay,
Driver_Load,
KernelThread::AsyncDriverCall,
Driver_Unload,
OpenFileRO,
CreateOrOpenFileRW,
CloseFile,
OpenKernelEventHandle,
CloseKernelEventHandle,
Is95,
KernelScsiCommand,
GetDvdVideoInfo
// FIXME: add equiv. to ConfigManager::GetDvdproxyDevnode
};
callbacks.Sprint = g_callbacks->Sprint;
callbacks.GetDvdsynthDirectory = g_callbacks->GetDvdsynthDirectory;
callbacks.GetTaskbarHWND = g_callbacks->GetTaskbarHWND;
DvsDeviceGlobal* plugin_functions = plugin_entry(&callbacks);
if (plugin_functions) {
if (plugin_functions->HookDockingBay != 0) {
for (int i=0; i<KernelThread::num_bays; ++i) {
hooked_bays[i] = plugin_functions->HookDockingBay(hooked_bays[i]);
}
}
plugins.push_back(plugin_functions);
}
}
void LoadPlugins() {
// Add external plugins from DLLs in program directory
WIN32_FIND_DATA wfd;
HANDLE h = FindFirstFile("*.dll", &wfd);
if (h != INVALID_HANDLE_VALUE) {
do {
HMODULE hmod = LoadLibrary(wfd.cFileName);
if (hmod != NULL) {
DDPE_func* plugin_entry = (DDPE_func*)GetProcAddress(hmod, "DvdsynthDevicePluginEntry");
if (plugin_entry) {
AddPlugin(plugin_entry);
} else {
FreeLibrary(hmod);
}
}
} while (FindNextFile(h, &wfd));
FindClose(h);
}
}
/*******************************************************************\
\*******************************************************************/
// 1. QueryUnplug() on all
// 2. QueryAndRemove() on all
// 3. detach
// 4. Delete() all
int QueryExit() {
bool asked_for_confirmation = false;
for (int i=0; i<31; ++i) {
if (original_bays[i]->Occupied()) {
if (!asked_for_confirmation) {
if (IDYES != MessageBox(NULL, "If you quit DVDSynth, all virtual devices will be unplugged. "/*"They will be restored when you next start DVDSynth."*/ "Are you sure you want to quit?", "DVDSynth", MB_YESNO)) {
return -1;
}
asked_for_confirmation = true;
}
if (!original_bays[i]->RequestUnplug()) {
return -1;
}
}
}
return 0;
}
void NotifyExit() {}
/*******************************************************************\
\*******************************************************************/
void UnplugDevice(void*, int index) {
original_bays[index]->RequestUnplug();
}
void AddMainMenuItems(DvsMenu* menu) {
menu->vtable->AddSeparator(menu);
menu->vtable->BeginSubmenu(menu, "&New...", false);
{
for (int i=0; i<plugins.size(); ++i) {
plugins[i].AddNewMenuItems(menu);
}
}
menu->vtable->EndSubmenu(menu);
menu->vtable->AddSeparator(menu);
for (int i=0; i<KernelThread::num_bays; ++i) {
if (original_bays[i]->Occupied()) {
unsigned letters = original_bays[i]->GetDriveLetters();
char letter;
if (letters) {
letter = 'A';
while (!(letters&1)) {
letters >>= 1;
++letter;
}
}
char buf[256];
g_callbacks->Sprint(buf, 256, letters ? "Device #&%1 (%2:)" : "Device #&%1",
"ic", original_bays[i]->GetScsiID(), letter);
menu->vtable->BeginSubmenu(menu, buf, false);
{
original_bays[i]->AddDeviceMenuItems(menu);
menu->vtable->AddSeparator(menu);
menu->vtable->AddItem(menu, "Unplug this device", false, UnplugDevice, 0, i);
}
menu->vtable->EndSubmenu(menu);
}
}
menu->vtable->AddSeparator(menu);
for (int j=0; j<plugins.size(); ++j) {
plugins[j].AddMainMenuItems(menu);
}
}
/*******************************************************************\
\*******************************************************************/
void OpenNTDiskManager(void*, int) {
// This only works on Win2000 and above.
ShellExecute(NULL, NULL, "diskmgmt.msc", NULL, NULL, 0);
}
void AddOptionsMenuItems(DvsMenu* menu) {
menu->vtable->AddItem(menu, "NT &Disk Manager (change drive letters)", false, OpenNTDiskManager, 0, 0);
}
/*******************************************************************\
\*******************************************************************/
void AddAboutMenuItems(DvsMenu* menu) {
}
/*******************************************************************\
\*******************************************************************/
DvsBasePluginFunctions plugin_functions = {
AddMainMenuItems,
AddOptionsMenuItems,
AddAboutMenuItems,
QueryExit,
NotifyExit
};
DvsBasePluginFunctions* __cdecl VDevice_DvdsynthBasePluginEntry(DvsBasePluginCallbacks* callbacks) {
g_callbacks = callbacks;
if (!Miniport::Init()) {
printf("Miniport/SPTI init failed!\n");
return 0;
}
if (!ConfigManager::Init()) {
return 0;
}
SubclassTrayWindow();
InitDockingBays();
LoadPlugins();
KernelThread::Spawn();
ListenerThread::Spawn();
return &plugin_functions;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -