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

📄 vdevice.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************\
\*******************************************************************/


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 + -