📄 vdevice.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>.
***********************************************************************/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include "scsipt.h"
#include "myvector.h"
#include "resource.h"
#include "../include/dvdsynth-device.h"
#include "miniport.h"
#include "kernel.h"
#include "ConfigMgr.h"
#include "SharedPool.h"
#include "udfrecognize.h"
#include <stdio.h>
/*******************************************************************\
\*******************************************************************/
void AsyncUserModeCall(void (*f)(void*, int), void* p, int i);
/*******************************************************************\
\*******************************************************************/
DvsBasePluginCallbacks* g_callbacks;
/*******************************************************************\
\*******************************************************************/
class Device {
DvsDeviceUser* u;
public:
Device() { u = 0; }
void set(DvsDeviceUser* _u) { u = _u; }
Device(DvsDeviceUser* _u) { set(_u); }
bool Occupied() { return u != 0; }
void AddDeviceMenuItems(DvsMenu* menu) {
if (u->vtable->AddDeviceMenuItems) {
u->vtable->AddDeviceMenuItems(u, menu);
}
}
int QueryUnplug() {
if (u->vtable->QueryUnplug != 0) {
return u->vtable->QueryUnplug(u);
} else {
return 0;
}
}
void Delete() {
u->vtable->Delete(u);
u = 0;
}
};
class Plugin {
DvsDeviceGlobal* p;
public:
Plugin(DvsDeviceGlobal* plugin) { p = plugin; }
Plugin(const Plugin& plugin) { p = plugin.p; }
void operator=(DvsDeviceGlobal* plugin) { p = plugin; }
void operator=(const Plugin& plugin) { p = plugin.p; }
void AddNewMenuItems(DvsMenu* menu) {
if (p->AddNewMenuItems != 0)
p->AddNewMenuItems(menu);
}
void AddAboutMenuItems(DvsMenu* menu) {
if (p->AddAboutMenuItems != 0)
p->AddAboutMenuItems(menu);
}
void AddMainMenuItems(DvsMenu* menu) {
if (p->AddMainMenuItems != 0)
p->AddMainMenuItems(menu);
}
};
/*******************************************************************\
\*******************************************************************/
template<class T>
class Optional {
char space[sizeof(T)];
bool exists;
public:
Optional() { exists = false; }
void _Construct() { if (!exists) { exists = true; new ((void*)space) T(); } }
template<class A> void _Construct(A&a) { if (!exists) { exists = true; new ((void*)space) T(a); } }
template<class A,class B> void _Construct(A&a,B&b) { if (!exists) { exists = true; new ((void*)space) T(a,b); } }
template<class A,class B,class C> void _Construct(A&a,B&b,C&c) { if (!exists) { exists = true; new ((void*)space) T(a,b,c); } }
template<class A,class B,class C,class D> void _Construct(A&a,B&b,C&c,D&d) { if (!exists) { exists = true; new ((void*)space) T(a,b,c,d); } }
template<class A,class B,class C,class D,class E> void _Construct(A&a,B&b,C&c,D&d,E&e) { if (!exists) { exists = true; new ((void*)space) T(a,b,c,d,e); } }
T* operator->() { return (T*)space; }
void _Destruct() { if (exists) { ((T*)space)->~T(); exists = false; } }
~Optional() { if (exists) { ((T*)space)->~T(); } }
};
/*******************************************************************\
\*******************************************************************/
int Is95() { return 0; }
/*******************************************************************\
\*******************************************************************/
class DockingBay : public DvsDockingBay {
int scsi_id;
unsigned drive_letters;
Device device;
void* pool;
public:
DockingBay(int _scsi_id) {
static DvsDockingBay_vtable vt = {
StaticSetHandlers,
StaticRequestUnplug,
StaticSharedPool_Alloc,
StaticGetScsiID,
StaticGetDriveLetters
};
vtable = &vt;
scsi_id = _scsi_id;
drive_letters = 0;
pool = 0;
}
bool Occupied() { return device.Occupied(); }
unsigned GetDriveLetters() const { return drive_letters; }
void ClearDriveLetters() { drive_letters = 0; }
void AddDriveLetter(unsigned mask) { drive_letters |= mask; }
void AddDeviceMenuItems(DvsMenu* menu) { device.AddDeviceMenuItems(menu); }
void SetHandlers(DvsDeviceUser* user_handler, DvsDeviceKernel* kernel_handler) {
device.set(user_handler);
KernelThread::AsyncSetHandler(scsi_id, kernel_handler);
}
void Unplug() {
KernelThread::AsyncSetHandler(scsi_id, 0);
device.Delete();
if (pool)
SharedPool_Clear(pool);
}
void ForceUnplug() {
Unplug();
ListenerThread::AsyncRescanBus();
}
bool RequestUnplug() {
if (device.QueryUnplug() < 0)
return false;
if (!ConfigManager::QueryAndRemoveTarget(scsi_id))
return false;
Unplug();
return true;
}
void* SharedPool_Alloc(unsigned len) {
if (pool == 0)
pool = ::SharedPool_Create(true);
return ::SharedPool_Alloc(pool, len);
}
int GetScsiID() { return scsi_id; }
static void StaticSetHandlers(DvsDockingBay* self, DvsDeviceUser* user_handler, DvsDeviceKernel* kernel_handler) {
((DockingBay*)self)->SetHandlers(user_handler, kernel_handler);
}
static void StaticRequestUnplug(DvsDockingBay* self) {
((DockingBay*)self)->RequestUnplug();
}
static void* StaticSharedPool_Alloc(DvsDockingBay* self, unsigned len) {
return ((DockingBay*)self)->SharedPool_Alloc(len);
}
static int StaticGetScsiID(DvsDockingBay* self) {
return ((DockingBay*)self)->GetScsiID();
}
static unsigned StaticGetDriveLetters(DvsDockingBay* self) {
return ((DockingBay*)self)->GetDriveLetters();
}
};
/*******************************************************************\
\*******************************************************************/
DockingBay* original_bays[KernelThread::num_bays];
DvsDockingBay* hooked_bays[KernelThread::num_bays];
void InitDockingBays() {
for (int i=0; i<KernelThread::num_bays; ++i) {
hooked_bays[i] = original_bays[i] = new DockingBay(i+1);
}
}
void DisplayScsiIDWarning(int id) {
static bool displayed_8_warning=false, displayed_16_warning=false;
if (id >= 16 && !displayed_16_warning) {
MessageBox(NULL, "Old versions of ASPI cannot handle devices with ID numbers of 16 or greater. Be sure you are using a recent version of ASPI. In addition, some applications may have trouble using these devices.", "DVDSynth", MB_OK);
displayed_16_warning = displayed_8_warning = true;
} else if (id >= 8 && !displayed_8_warning) {
MessageBox(NULL, "Some old applications may have trouble using virtual devices with an ID number of 8 or greater.", "DVDSynth", MB_OK);
displayed_8_warning = true;
}
}
DvsDockingBay* ReserveDockingBay() {
for (int i=0; i<KernelThread::num_bays; ++i) {
if (!original_bays[i]->Occupied()) {
int scsi_id = original_bays[i]->GetScsiID();
DisplayScsiIDWarning(scsi_id);
return hooked_bays[i];
}
}
MessageBox(NULL, "no more devices available", "DVDSynth", MB_OK);
return 0;
}
/*******************************************************************\
\*******************************************************************/
namespace SPTI {
extern int scsi_port_number;
};
void ScanDriveLetters() {
for (int b=0; b<KernelThread::num_bays; ++b)
original_bays[b]->ClearDriveLetters();
DWORD drive_mask = GetLogicalDrives();
for (int l=2; l<26; ++l) {
if (!(drive_mask & (1<<l))) continue;
char buf[32];
wsprintf(buf, "%c:\\", l+65);
if (GetDriveType(buf) == DRIVE_REMOTE) continue;
wsprintf(buf, "\\\\.\\%c:", l+65);
HANDLE fh = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE) continue;
SCSI_ADDRESS sa;
ULONG returned;
memset(&sa, 0, sizeof(sa));
if (DeviceIoControl(fh, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &sa, sizeof(sa), &returned, NULL)) {
if (sa.PortNumber == SPTI::scsi_port_number && sa.TargetId > 0 && sa.TargetId <= KernelThread::num_bays) {
original_bays[sa.TargetId-1]->AddDriveLetter(1<<l);
}
}
CloseHandle(fh);
}
}
/*******************************************************************\
\*******************************************************************/
struct AsyncCallRecord {
void (*f)(void*, int);
void* p;
int i;
};
#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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -