/*********************************************************************** 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 . ***********************************************************************/ #define WIN32_LEAN_AND_MEAN #define STRICT #include #include "miniport.h" #include "ConfigMgr.h" #include typedef void* DEVNODE; typedef unsigned long ULONG; typedef ULONG CONFIGRET; typedef enum { PNP_VetoTypeUnknown, PNP_VetoLegacyDevice, PNP_VetoPendingClose, PNP_VetoWindowsApp, PNP_VetoWindowsService, PNP_VetoOutstandingOpen, PNP_VetoDevice, PNP_VetoDriver, PNP_VetoIllegalDeviceRequest, PNP_VetoInsufficientPower, PNP_VetoNonDisableable, PNP_VetoLegacyDriver, } PNP_VETO_TYPE, *PPNP_VETO_TYPE; #define CR_SUCCESS 0 #define CM_REENUMERATE_SYNCHRONOUS 1 #define CM_QUERY_REMOVE_UI_NOT_OK 1 #define CM_REMOVE_UI_NOT_OK 1 #define CM_DRP_DEVICEDESC 1 #define CM_DRP_LOCATION_INFORMATION 14 extern "C" { __declspec(dllimport) CONFIGRET WINAPI CM_Locate_DevNodeW(DEVNODE* pdn, void* device_id = 0, ULONG flags = 0); __declspec(dllimport) CONFIGRET WINAPI CM_Get_Child(DEVNODE* pdn, DEVNODE dn, ULONG flags = 0); __declspec(dllimport) CONFIGRET WINAPI CM_Get_Sibling(DEVNODE* pdn, DEVNODE dn, ULONG flags = 0); __declspec(dllimport) CONFIGRET WINAPI CM_Get_DevNode_Registry_PropertyA(DEVNODE dn, ULONG property, ULONG* pulRegDataType, void* buffer, ULONG* pulLength, ULONG ulFlags); __declspec(dllimport) CONFIGRET WINAPI CM_Query_And_Remove_SubTreeW(DEVNODE, PPNP_VETO_TYPE, LPWSTR, ULONG, ULONG); } //typedef CONFIGRET (WINAPI*QARSTW)(DEVNODE,PPNP_VETO_TYPE,LPWSTR,ULONG,ULONG); //QARSTW _CM_Query_And_Remove_SubTreeW; namespace ConfigManager { DEVNODE dvdproxy_devnode; /* HMODULE hCfgMgr = LoadLibrary("cfgmgr32.dll"); if (hCfgMgr == NULL) return false; _CM_Query_And_Remove_SubTreeW = (QARSTW)GetCfgMgrFunc("CM_Query_And_Remove_SubTreeW"); if (_CM_Query_And_Remove_SubTreeW == 0) { MessageBox(NULL, "Could not find CM_Query_And_Remove_SubTreeW in cfgmgr32.dll.", "DVDSynth", NULL); return false; } */ bool Init() { DEVNODE i; if (CR_SUCCESS == CM_Locate_DevNodeW(&i, NULL, 0) && CR_SUCCESS == CM_Get_Child(&i, i, 0)) { do { char buf[256]; ULONG length = 256; if (CR_SUCCESS == CM_Get_DevNode_Registry_PropertyA(i, CM_DRP_DEVICEDESC, NULL, buf, &length, 0)) { static const char dvdproxy_desc[] = "DVDSynth virtual SCSI card"; if (length == sizeof(dvdproxy_desc) && 0 == memcmp(buf, dvdproxy_desc, sizeof(dvdproxy_desc))) { dvdproxy_devnode = i; return true; } } } while (CR_SUCCESS == CM_Get_Sibling(&i, i, 0)); MessageBox(NULL, "Could not find the DVDSynth virtual SCSI controller.", "DVDSynth", MB_OK); } else { MessageBox(NULL, "Could not enumerate the Configuration Manager's device tree.", "DVDSynth", MB_OK); } return false; } int GetDevnodeTargetID(DEVNODE node) { char buf[128]; char* id_string = 0; // Under NT, the "LocationInformation" registry value contains a // string that looks like "Bus Number 0, Target ID 0, LUN 0". ULONG length = 128; if (CR_SUCCESS == CM_Get_DevNode_Registry_PropertyA(node, CM_DRP_LOCATION_INFORMATION, NULL, buf, &length, 0)) { char* target_id = strstr(buf, "Target ID "); if (target_id != 0) { id_string = target_id + 10; } } if (id_string && unsigned(*id_string - '0') <= 9) { int id = 0; do { id = id*10 + (*id_string - '0'); ++id_string; } while (unsigned(*id_string - '0') <= 9); return id; } else { return -1; } } DEVNODE GetTargetDevnode(int target_id) { printf("GetTargetDevnode(%d)\n", target_id); DEVNODE i; printf("dvdproxy_devnode = %X\n", dvdproxy_devnode); if (CR_SUCCESS == CM_Get_Child(&i, dvdproxy_devnode, 0)) { do { printf("Devnode %X targetid = %d\n", i, GetDevnodeTargetID(i)); if (GetDevnodeTargetID(i) == target_id) { return i; } } while (CR_SUCCESS == CM_Get_Sibling(&i, i, 0)); } return 0; } bool QueryAndRemoveTarget(int target) { DEVNODE dn = GetTargetDevnode(target); if (dn == 0) { // if we can't find the devnode, assume that // Windows doesn't even know about this device return true; } PNP_VETO_TYPE veto_type; return CR_SUCCESS == CM_Query_And_Remove_SubTreeW(dn, &veto_type, 0, 0, 0); } }