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

📄 vdevice.cpp

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