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

📄 mirrordrive95.cpp

📁 DVD工具dvdsynth的源码
💻 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
#define _WIN32_IE 0x300
// winbase.h defines an unrelated struct called "DCB". Rather than rename
// the kernel one I'm hacking around the problem, at least for now.
#define DCB SOME_OTHER_DCB
#include <windows.h>
#undef DCB
#include <commctrl.h>
#include "resource.h"
#include "../include/dvdsynth-device.h"
#include "kernel-io.h"

#include <stdio.h>


HINSTANCE g_hinstance;
DvsDockingBayGlobal* g_callback;

dvs_driver_handle g_driver_handle;


struct AdapterInfo {
   DEVNODE devnode;
   int num_devices;
};
AdapterInfo g_adapters[16];
int g_num_adapters;

struct DeviceInfo {
   unsigned adapter, bus, target, lun;
   DCB* dcb;
   unsigned char drive_letter;
   unsigned char type;
   char model[27];
};

const int MAX_DEVICES = 64;
DeviceInfo g_device_info[MAX_DEVICES];
int g_num_devices;

HWND g_hlistview;


inline scsi_result_t SendScsiCommand(DCB* dcb, 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)g_callback->Driver_Call(g_driver_handle, "SendScsiCommand", "p>i>&i>i", dcb, cdb, cdblen, buffer, pbuflen, inout, sense, sizeof(SenseData));
}


inline DEVNODE GetDevnodeParent(DEVNODE dn) {
   DEVNODE result = 0;
   if (CR_SUCCESS == (CONFIGRET)g_callback->Driver_Call(g_driver_handle, "CONFIGMG_Get_Parent", "&pi", &result, dn, 0)) {
      return result;
   } else {
      return 0;
   }
}

inline DCB* GetNextDCB(DCB* dcb) {
   return (DCB*)g_callback->Driver_Call(g_driver_handle, "GetNextDCB", "p", dcb);
}


bool GetRegString(HKEY base, const char* subkey, const char* value, char* buf, ULONG* pbuflen) {
   HKEY hkey;
   if (ERROR_SUCCESS != RegOpenKeyEx(base, subkey, 0, KEY_READ, &hkey)) {
      return false;
   }
   long query_error = RegQueryValueEx(hkey, value, NULL, NULL, (unsigned char*)buf, pbuflen);
   RegCloseKey(hkey);
   return (query_error == ERROR_SUCCESS);
}

bool GetDevNodeHardwareKey(DEVNODE dn, char* buf, ULONG buflen) {
   char dyn_data_key[32];
   wsprintf(dyn_data_key, "Config Manager\\Enum\\%08X", dn);
   lstrcpy(buf, "Enum\\");
   ULONG len = buflen-6;
   if (!GetRegString(HKEY_DYN_DATA, dyn_data_key, "HardWareKey", buf+5, &len)) {
      return false;
   }
   buf[5+len] = 0;
   return true;
}

bool GetDevNodeRegString(DEVNODE dn, const char* name, char* buf, ULONG buflen) {
   char hardware_key[256];
   if (!GetDevNodeHardwareKey(dn, hardware_key, 256)) {
      return false;
   }
   ULONG len = buflen;
   if (!GetRegString(HKEY_LOCAL_MACHINE, hardware_key, name, buf, &len)) {
      return false;
   }
   buf[min(len,buflen-1)] = 0;
   return true;
}

char GetDevnodeDriveLetter(DEVNODE dn) {
   char buf[64];
   if (GetDevNodeRegString(dn, "CurrentDriveLetterAssignment", buf, 64)) {
      return buf[0];
   } else {
      return 0;
   }
}


void SetModelField(char* dst, const unsigned char* src) {
   // copy vendor ID field
   memcpy(dst, src, 8);
   char* p;

   // lop off trailing spaces
   p = dst+8;
   while (p > dst && p[-1] == ' ')
      --p;

   // copy product ID field, with delimiting space
   *p++ = ' ';
   memcpy(p, src+8, 16);

   // lop off trailing spaces
   p += 16;
   while (p > dst && p[-1] == ' ')
      --p;
   *p = 0;
}


void ScanForDevices() {
   DEVNODE dvdproxy_devnode = (DEVNODE)g_callback->GetDvdsynthDevicesID();
   DCB* dcb = 0;
   while ((dcb = GetNextDCB(dcb)) != 0 && g_num_devices < MAX_DEVICES) {
      printf("DCB = %08X\n", dcb);
      // skip logical devices
      if (!(dcb->DCB_cmn.DCB_device_flags & DCB_DEV_PHYSICAL)) {
         continue;
      }
      // only consider SCSI/IDE devices (is this wise?)
      if (dcb->DCB_bus_type != DCB_BUS_SCSI && dcb->DCB_bus_type != DCB_BUS_ESDI) {
         printf("A\n");
         continue;
      }

      // the parent devnode is the adapter controlling this device
      DEVNODE adapter_devnode = GetDevnodeParent(dcb->DCB_dev_node);
      printf("parent = %08X\n", adapter_devnode);
      if (adapter_devnode == 0 || adapter_devnode == dvdproxy_devnode) {
         printf("B\n");
         continue;
      }
      int adapter_number;
      for (adapter_number=0; adapter_number<g_num_adapters; ++adapter_number) {
         if (g_adapters[adapter_number].devnode == adapter_devnode)
            break;
      }
      if (adapter_number == sizeof(g_adapters)/sizeof(g_adapters[0])) {
         // out of space for adapter info; ignore this adapter
         printf("C\n");
         continue;
      }

      g_adapters[adapter_number].devnode = adapter_devnode;
      ++g_adapters[adapter_number].num_devices;
      if (adapter_number == g_num_adapters) {
         ++g_num_adapters;
      }

      int bus, target, lun;
      if (dcb->DCB_cmn.DCB_device_flags2 & DCB_DEV2_ATAPI_DEVICE) {
         // For ATAPI devices, count number of previous devices on this bus
         bus = 0;
         target = g_adapters[adapter_number].num_devices - 1;
         lun = 0;
      } else if (dcb->DCB_bus_type == DCB_BUS_SCSI) {
         // For SCSI devices, SCSI address is stored in the DCB.
         bus = dcb->DCB_bus_number;
         target = dcb->DCB_scsi_target_id;
         lun = dcb->DCB_scsi_lun;
      } else {
         // Don't consider IDE devices any further.
         printf("D\n");
         continue;
      }
/*
      static const unsigned char cdb_inquiry[6] = { 0x12, 0, 0, 0, 36, 0 };
      unsigned char inquiry_buf[36];
      memset(inquiry_buf, 0, sizeof(inquiry_buf));
      unsigned long buflen = 36;
      SenseData sense;
      if (SCSIRESULT_SUCCESS != SendScsiCommand(dcb, cdb_inquiry, 6, inquiry_buf, &buflen, 1, &sense)) {
         printf("E\n");
         continue;
      }
*/

      DeviceInfo& di = g_device_info[g_num_devices++];
      memset(&di, 0, sizeof(DeviceInfo));
      di.adapter = adapter_number;
      di.bus = bus;
      di.target = target;
      di.lun = lun;
      di.dcb = dcb;
      di.drive_letter = GetDevnodeDriveLetter(dcb->DCB_dev_node);
      di.type = dcb->DCB_inquiry_flags[0];
      SetModelField(di.model, dcb->DCB_vendor_id);
//      di.type = inquiry_buf[0];
//      SetModelField(di.model, inquiry_buf+8);
   }
}


void AddListViewColumn(HWND hlv, int index, const char* text, int width) {
   LVCOLUMN lvc;
   lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
   lvc.fmt = 0;
   lvc.cx = width;
   lvc.pszText = (LPTSTR)text;
   ListView_InsertColumn(hlv, index, &lvc);
}


BOOL NewInstanceDialog_InitDialog(HWND hdlg) {
   HWND hlist = GetDlgItem(hdlg, IDC_DEVICELIST);
   ListView_SetExtendedListViewStyle(hlist, LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP);
   // get the width of the list view and size its columns proportionally
   RECT r;
   GetClientRect(hlist, &r);
   unsigned width = r.right;
   unsigned divider1 = width*14/32;
   unsigned divider2 = width*21/32;
   unsigned divider3 = width*27/32;
   AddListViewColumn(hlist, 0, "Make and model", divider1);
   AddListViewColumn(hlist, 1, "Type", divider2-divider1);
   AddListViewColumn(hlist, 2, "Letter", divider3-divider2);
   AddListViewColumn(hlist, 3, "Address", width-divider3);
   g_hlistview = hlist;
   g_num_devices = 0;
   g_num_adapters = 0;
   ScanForDevices();

   // ListView_SetItemCount does not work!!!
   LVITEM new_item;
   memset(&new_item, 0, sizeof(new_item));
   for (int i=0; i<g_num_devices; ++i) {
      new_item.iItem = i;
      ListView_InsertItem(hlist, &new_item);
   }
   return TRUE;
}


int GetLVSelection(HWND hlv) {
   return ListView_GetNextItem(hlv, (unsigned)-1, LVNI_SELECTED);
}


const char* scsi_device_type[] = {
   "Disk drive",
   "Tape drive",
   "Printer",
   "Processor",
   "WORM drive",
   "CD/DVD drive",
   "Scanner",
   "Optical drive",
   "Medium changer",
   "Network device",
   "ASCIT8",
   "ASCIT8",
   "Array",
   "Enclosure",
   "RBC",
   "Card reader",
   "Bridge"
};


void GetDispInfo(LVITEM* plvi) {
   if (!(plvi->mask & LVIF_TEXT))
      return;
   int i = plvi->iItem, c = plvi->iSubItem;
   if (i < 0 || i >= g_num_devices || i >= MAX_DEVICES)
      return;

   char buf[32];
   const char* text;

   const DeviceInfo& di = g_device_info[i];

   switch (c) {
   case 0:
      text = di.model;
      break;
   case 1:
      if (di.type <= sizeof(scsi_device_type)/sizeof(scsi_device_type[0])) {
         text = scsi_device_type[di.type];
      } else {
         wsprintf(buf, "unknown (0x%02X)", di.type);
         text = buf;
      }
      break;
   case 2:
      wsprintf(buf, "%c:", di.drive_letter);
      text = buf;
      break;
   case 3:
      if (di.bus) {
         wsprintf(buf, "%d.%d:%d:%d", di.adapter, di.bus, di.target, di.lun);
      } else {
         wsprintf(buf, "%d:%d:%d", di.adapter, di.target, di.lun);
      }
      text = buf;
      break;
   default:
      return;
   }

   lstrcpyn(plvi->pszText, text, plvi->cchTextMax);
   plvi->pszText[plvi->cchTextMax-1] = 0;
}

BOOL CALLBACK NewInstanceDialogProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) {
//   printf("NewInstanceDialogProc(%X, %d, %d, %d)\n", hdlg, msg, wparam, lparam);
   switch (msg) {
   case WM_INITDIALOG:
      return NewInstanceDialog_InitDialog(hdlg);
   case WM_COMMAND:
      switch (LOWORD(wparam)) {
      case IDOK:
         EndDialog(hdlg, GetLVSelection(GetDlgItem(hdlg, IDC_DEVICELIST)));
         return TRUE;
      case IDCANCEL:
         EndDialog(hdlg, -1);
         return TRUE;
      }
      break;
   case WM_NOTIFY:
      if (wparam == IDC_DEVICELIST) {
         LPNMHDR pnmh = (LPNMHDR)lparam;
//         printf("code = %d\n", pnmh->code);
         if (pnmh->code == LVN_GETDISPINFO) {
            GetDispInfo(&((LV_DISPINFO*)pnmh)->item);
            return TRUE;
         } else if (pnmh->code == LVN_ITEMCHANGED) {
            EnableWindow(GetDlgItem(hdlg, IDOK), ListView_GetSelectedCount(pnmh->hwndFrom));
            return TRUE;
         } else if (pnmh->code == LVN_ITEMACTIVATE) {
            EndDialog(hdlg, GetLVSelection(GetDlgItem(hdlg, IDC_DEVICELIST)));
            return TRUE;
         }
      }
      break;
   }
   return FALSE;
}


DvsDeviceUser_vtable mirror_drive_user_vtable = {
   0, // AddDeviceMenuItems
   0, // QueryUnplug
   0, // Delete
};

DvsDeviceUser mirror_drive_user = { &mirror_drive_user_vtable };


void CreateNewInstance(void*, int) {
   DvsDockingBay* bay = g_callback->ReserveDockingBay();
   if (!bay) return;
   int selection = DialogBox(g_hinstance, MAKEINTRESOURCE(IDD_CHOOSEDEVICE), NULL, NewInstanceDialogProc);
   if (selection >= 0 && selection < g_num_devices) {
      MirrorDriveKernel* k = (MirrorDriveKernel*)bay->vtable->SharedPool_Alloc(bay, sizeof(MirrorDriveKernel));
      k->ScsiCommand = (dvs_scsi_func*)g_callback->Driver_Call(g_driver_handle, "GetDispatchFunc", "");
      k->dcb = g_device_info[selection].dcb;
      bay->vtable->SetHandlers(bay, &mirror_drive_user, k);
   }
}


void AddNewMenuItems(DvsMenu* menu) {
   menu->vtable->AddItem(menu, "Mirror Drive", false, CreateNewInstance, 0, 0);
}

void AddAboutMenuItems(DvsMenu* menu) {}


DvsDeviceGlobal global_funcs = {
   AddNewMenuItems,
   AddAboutMenuItems,
   0,//AddMainMenuItems,
   0
};


extern "C"
DvsDeviceGlobal* DvdsynthDevicePluginEntry(DvsDockingBayGlobal* bays) {
   if (!bays->Is95())
      return 0;
   g_callback = bays;
   if (g_driver_handle == 0) {
      g_driver_handle = g_callback->Driver_Load("MirrorDrive95.kll");
   }
   return g_driver_handle ? &global_funcs : 0;
}


extern "C"
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID) {
   g_hinstance = hinst;
   // don't ever unload the driver because we registered with IOS
/*
   if (dwReason == DLL_PROCESS_DETACH && g_driver_handle != 0 && g_callback != 0) {
      g_callback->Driver_Unload(g_driver_handle);
      g_driver_handle = 0;
   }
*/
   return TRUE;
}

⌨️ 快捷键说明

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