⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdevice.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
 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 + -