📄 vdevice.cpp
字号:
/*******************************************************************\
\*******************************************************************/
static const char* GetFullPath(const char* pathname, char* buffer) {
buffer[0] = 0;
DWORD path_length = GetShortPathName(pathname, buffer, MAX_PATH);
if (path_length > 0 && path_length <= MAX_PATH) {
pathname = buffer;
}
return pathname;
}
int OpenFileRO(dvs_file_handle* phandle, const char* pathname) {
char buffer[MAX_PATH];
return (int)Miniport::DriverCall(miniport_handle, (char*)mpdfunc_OpenFileRO, "&s", phandle, GetFullPath(pathname, buffer));
}
int CreateOrOpenFileRW(dvs_file_handle* phandle, const char* pathname, int creation_disposition) {
char buffer[MAX_PATH];
return (int)Miniport::DriverCall(miniport_handle, (char*)mpdfunc_CreateOrOpenFileRW, "&si", phandle, GetFullPath(pathname, buffer), creation_disposition);
}
void CloseFile(dvs_file_handle handle) {
Miniport::DriverCall(miniport_handle, (char*)mpdfunc_CloseFile, "i", handle);
}
unsigned OpenKernelEventHandle(void* handle) {
static DWORD (WINAPI *_OpenVxDHandle)(void*) = (DWORD(WINAPI*)(void*))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenVxDHandle");
if (_OpenVxDHandle == 0) {
MessageBox(NULL, "Export KERNEL32.OpenVxDHandle not found!", "DVDSynth", MB_OK);
return 0;
}
return _OpenVxDHandle(handle);
}
void CloseKernelEventHandle(unsigned handle) {
Miniport::DriverCall(miniport_handle, (char*)mpdfunc_CloseEvent, "p", handle);
}
/*******************************************************************\
\*******************************************************************/
scsi_result_t KernelScsiCommand(DvsDeviceKernel* device, const unsigned char* cdb, int cdblen, unsigned char* buffer, unsigned long* pbuflen, int inout, SenseData* sense) {
// note the final dummy argument specifying the size of the SenseData buffer
return (scsi_result_t)Miniport::DriverCall(miniport_handle, (const char*)mpdfunc_ScsiDispatch, "p>i>&i>i", device, cdb, cdblen, buffer, pbuflen, inout, sense, sizeof(SenseData));
}
/*******************************************************************\
\*******************************************************************/
Vector<Plugin> plugins;
typedef DvsDeviceGlobal* __cdecl DDPE_func(DvsDockingBayGlobal*);
void AddPlugin(DDPE_func* plugin_entry) {
static DvsDockingBayGlobal callbacks = {
ReserveDockingBay,
Driver_Load,
Miniport::DriverCall,
Driver_Unload,
OpenFileRO,
CreateOrOpenFileRW,
CloseFile,
OpenKernelEventHandle,
CloseKernelEventHandle,
Is95,
KernelScsiCommand,
GetDvdVideoInfo,
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<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);
}
}
/*******************************************************************\
\*******************************************************************/
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]->QueryUnplug() != 0) {
return -1;
}
}
}
return 0;
}
void NotifyExit() {
for (int i=0; i<31; ++i) {
if (original_bays[i]->Occupied()) {
original_bays[i]->ForceUnplug();
}
}
}
/*******************************************************************\
\*******************************************************************/
void UnplugDevice(void*, int index) {
original_bays[index]->RequestUnplug();
}
BOOL CALLBACK ChangeDriveLetterDlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
static char* fromto = 0;
switch (msg) {
case WM_INITDIALOG:
{
fromto = (char*)lparam;
static char drivebuf[3] = "@:";
// set the "current drive letter" edit box
drivebuf[0] = fromto[0];
SetDlgItemText(hwnd, IDC_OLDLETTER, fromto[0] ? drivebuf : "none");
// fill in the "change to" drop-down list box
HWND hwndCombo = GetDlgItem(hwnd, IDC_NEWLETTER);
ComboBox_AddString(hwndCombo, "(no preference)");
for (char i = 'A'; i <= 'Z'; ++i) {
drivebuf[0] = i;
ComboBox_AddString(hwndCombo, drivebuf);
}
ComboBox_SetCurSel(hwndCombo, fromto[1] ? (fromto[1] - 'A' + 1) : 0);
return TRUE;
}
case WM_COMMAND:
switch (LOWORD(wparam)) {
case IDOK:
{
int selection = ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_NEWLETTER));
fromto[1] = (selection >= 1 && selection <= 26) ? selection + 'A' - 1 : 0;
}
// fall thru
case IDCANCEL:
EndDialog(hwnd, 0);
return TRUE;
}
default:
return FALSE;
}
}
void ChangeDriveLetter(void*, int scsi_id) {
char fromto[2] = {0,0};
char oldto = 0;
char buf[64];
if (ConfigManager::GetTargetRegString(scsi_id, "CurrentDriveLetterAssignment", buf, 64)) {
if (buf[0] >= 'A' && buf[0] <= 'Z')
fromto[0] = buf[0];
}
if (ConfigManager::GetTargetRegString(scsi_id, "UserDriveLetterAssignment", buf, 64)) {
if (buf[0] >= 'A' && buf[0] <= 'Z')
oldto = fromto[1] = buf[0];
}
DialogBoxParam(GetModuleHandle(0)/*careful!*/, MAKEINTRESOURCE(IDD_DRIVELETTER), NULL, ChangeDriveLetterDlgProc, (LPARAM)fromto);
if (fromto[1] != oldto) {
wsprintf(buf, "%c%c", fromto[1]);
if (!ConfigManager::SetTargetRegString(scsi_id, "UserDriveLetterAssignment", buf)) {
MessageBox(NULL, "Couldn't change the drive letter in the registry!", "DVDSynth", MB_OK);
}
}
}
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<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, "Change drive letter", false, ChangeDriveLetter, 0, original_bays[i]->GetScsiID());
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 AddOptionsMenuItems(DvsMenu* menu) {
}
/*******************************************************************\
\*******************************************************************/
void AddAboutMenuItems(DvsMenu* menu) {
}
/*******************************************************************\
\*******************************************************************/
struct AsyncCallRecord {
void (*f)(void*, int);
void* p;
int i;
};
struct AsyncCallQueue {
unsigned head,tail;
enum { queue_size = 16 };
AsyncCallRecord q[queue_size];
unsigned records_lost;
};
#define WM_APP_APC 0xA5FC
typedef LRESULT WINAPI WindowProcedure(HWND, UINT, WPARAM, LPARAM);
WindowProcedure* OldWndProc;
LRESULT WINAPI MyWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if (msg == WM_APP_APC) {
AsyncCallQueue* acq = (AsyncCallQueue*)lparam;
unsigned t = acq->tail;
while (t < acq->head) {
const AsyncCallRecord& acr = acq->q[t%AsyncCallQueue::queue_size];
acr.f(acr.p, acr.i);
++t;
}
acq->tail = t;
return 0;
} else {
return OldWndProc(hwnd, msg, wparam, lparam);
}
}
void SubclassTrayWindow(HWND hwnd) {
OldWndProc = (WindowProcedure*)GetWindowLong(hwnd, GWL_WNDPROC);
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)MyWndProc);
}
/*******************************************************************\
\*******************************************************************/
DvsBasePluginFunctions plugin_functions = {
AddMainMenuItems,
AddOptionsMenuItems,
AddAboutMenuItems,
QueryExit,
NotifyExit
};
DvsBasePluginFunctions* __cdecl VDevice_DvdsynthBasePluginEntry(DvsBasePluginCallbacks* callbacks) {
g_callbacks = callbacks;
if (Miniport::Init() != 0) {
printf("ASPI init failed!\n");
return 0;
}
if (!ConfigManager::Init()) {
return 0;
}
SubclassTrayWindow((HWND)g_callbacks->GetTaskbarHWND());
InitDockingBays();
LoadPlugins();
return &plugin_functions;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -