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

📄 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 <windowsx.h>

#include "myvector.h"

#include "resource.h"
#include "aspi.h"
#include "../dvdproxy95/dvdproxy95.h"
#include "../include/dvdsynth-device.h"
#include "miniport.h"
#include "ConfigMgr.h"
#include "SharedPool.h"
#include "udfrecognize.h"

#include <stdio.h>


/*******************************************************************\
\*******************************************************************/


DvsBasePluginCallbacks* g_callbacks;


/*******************************************************************\
\*******************************************************************/


class Device {
   DvsDeviceUser* d;
public:
   Device() { d = 0; }
   Device(DvsDeviceUser* device) { d = device; }
   void operator=(DvsDeviceUser* device) { d = device; }
   void operator=(const Device& device) { d = device.d; }

   DvsDeviceUser* GetPtr() { return d; }

   void AddDeviceMenuItems(DvsMenu* menu) {
      if (d->vtable->AddDeviceMenuItems) {
         d->vtable->AddDeviceMenuItems(d, menu);
      }
   }

   int QueryUnplug() {
      if (d->vtable->QueryUnplug != 0) {
         return d->vtable->QueryUnplug(d);
      } else {
         return 0;
      }
   }

   void Delete() {
      d->vtable->Delete(d);
      d = 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 1; }


/*******************************************************************\
\*******************************************************************/


int SystemQueryUnplug(int target) {
//   if (ConfigManager::QueryRemoveTarget(target)) {
//      return 0;
//   }
//   return (IDYES != MessageBox(NULL, "Windows has indicated that it is not safe to unplug this device. There may be a file or folder still open on it.\n\nYou can unplug the device anyway, but this may cause applications to crash or make your system unstable.\n\nDo you want to forcibly unplug the device?", "DVDSynth", MB_YESNO|MB_DEFBUTTON2));

   return 0;
}

inline void SystemUnplug(int target) {
//   ConfigManager::RemoveTarget(target);
   ConfigManager::Reenumerate(false);
}

inline void SystemRescanBus() {
   ConfigManager::Reenumerate(false);
}


/*******************************************************************\
\*******************************************************************/


class DockingBay : public DvsDockingBay {
   int scsi_id;
   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;
      device = 0;
      pool = 0;
   }

   bool Occupied() { return device.GetPtr() != 0; }

   unsigned GetDriveLetters() const { return ConfigManager::GetDriveLetters(scsi_id); }

   void AddDeviceMenuItems(DvsMenu* menu) { device.AddDeviceMenuItems(menu); }

   void SetHandlers(DvsDeviceUser* user_handler, DvsDeviceKernel* kernel_handler) {
      device = user_handler;
      Miniport::DriverCall(miniport_handle, (char*)mpdfunc_SetHandler, "ip", GetScsiID(), kernel_handler);
      SystemRescanBus();
   }

   void ForceUnplug() {
      SystemUnplug(GetScsiID());
      Miniport::DriverCall(miniport_handle, (char*)mpdfunc_SetHandler, "ip", GetScsiID(), 0);
      device.Delete();
      if (pool)
         SharedPool_Clear(pool);
   }

   int QueryUnplug() {
      return (SystemQueryUnplug(GetScsiID()) || device.QueryUnplug());
   }

   void RequestUnplug() {
      if (QueryUnplug() == 0)
         ForceUnplug();
   }

   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();
   }
};


/*******************************************************************\
\*******************************************************************/


enum { num_bays = 31 };

DockingBay* original_bays[num_bays];
DvsDockingBay* hooked_bays[num_bays];


void InitDockingBays() {
   for (int i=0; i<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<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;
}


/*******************************************************************\
\*******************************************************************/

#define PELDR_ERR_NOERROR        0
#define PELDR_ERR_INVALIDHANDLE  -1


const char* PELDR_LoadModule(dvs_driver_handle* ph, const char* filename) {
   char full_pathname[MAX_PATH];
   if (g_callbacks->Sprint(full_pathname, MAX_PATH, "%1%2", 0,
      g_callbacks->GetDvdsynthDirectory(), filename) < 0)
   {
      return "Pathname too long";
   }
   char short_pathname[MAX_PATH];
   DWORD short_len = GetShortPathName(full_pathname, short_pathname, MAX_PATH);
   if (short_len == 0 || short_len > MAX_PATH) {
      printf("full_pathname = %s\n", full_pathname);
      return "GetShortPathName failed (file not found?)";
   }
   int result = (int)Miniport::DriverCall(miniport_handle, (char*)mpdfunc__PELDR_LoadModule, "&sp", ph, short_pathname, 0);
   if (result == PELDR_ERR_NOERROR) {
      return 0;
   } else {
      static const char* peldr_errors[] = {
         "Invalid handle",
         "Out of memory",
         "Unable to open the file",
         "Error reading the file",
         "Invalid image size",
         "Invalid image format",
         "Unknown fixup in image",
         "Invalid fixup in image",
         "Undefined import in image",
         "Duplicate export in image",
         "Init was completed",
         "Undefined DLL in image"
      };
      if (result < 0 && result >= -12) {
         return peldr_errors[~(unsigned)result];
      } else {
         static char buf[64];
         g_callbacks->Sprint(buf, 64, "Unknown PELDR error #%1", "d", result);
         return buf;
      }
   }
}


dvs_driver_handle Driver_Load(const char* filename) {
   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;
   }
   dvs_driver_handle h = 0;
   const char* error_string = PELDR_LoadModule(&h, filename);
   if (error_string == 0) {
      Miniport::DriverCall(miniport_handle, (char*)mpdfunc_CallDriverInitFunc, "p", h);
      return h;
   } else {
      char buf[256];
      g_callbacks->Sprint(buf, 256, "INTERNAL ERROR: There was an error loading the driver file \"%1\":\n\n%2.", 0, filename, error_string);
      MessageBox(NULL, buf, "DVDSynth", MB_OK);
      return 0;
   }
}


void Driver_Unload(dvs_driver_handle handle) {
   int result = (int)Miniport::DriverCall(miniport_handle, (char*)mpdfunc__PELDR_FreeModule, "pp", handle, 0);
   if (result == PELDR_ERR_INVALIDHANDLE) {
      MessageBox(NULL, "INTERNAL ERROR: An invalid handle was passed to UnloadDriver. This is almost certainly a plugin bug.", "DVDSynth", MB_OK);
   }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -