// devnode.cpp0 #include "stdafx.h" #include "devnode.h" // globals from alcclass AutoListClass *pALCHead = NULL; AutoListClass *pALCTail = NULL; int AutoListClassCount = NULL; /******************************************************************* Constructiors *******************************************************************/ DevnodeClass::DevnodeClass(DEVNODE hDevice, DEVNODE l_hParent) { pDeviceID = NULL; hDevnode = hDevice; hParent = l_hParent; pszDescription = NULL; ulProblemCode = (ULONG) -1; ulStatus = 0; pszClass = NULL; bDNHasMark = (BOOL)-1; bCanDisable = FALSE; bCanTest = FALSE; bDidPass = FALSE; pHardwareID = NULL; pCompatID = NULL; pszGUID = NULL; pszLocation = NULL; pszPDO = NULL; pszFriendlyName = NULL; pszMFG = NULL; InterfaceBusType = InterfaceTypeUndefined; GetDeviceInformation(); } DevnodeClass::DevnodeClass(void) { pDeviceID = NULL; hDevnode = 0; hParent = 0; pszDescription = NULL; ulProblemCode = (ULONG) -1; ulStatus = 0; pszClass = NULL; bDNHasMark = (BOOL)-1; bCanDisable = FALSE; bCanTest = FALSE; bDidPass = FALSE; pHardwareID = NULL; pCompatID = NULL; pszGUID = NULL; pszLocation = NULL; pszPDO = NULL; pszFriendlyName = NULL; pszMFG = NULL; InterfaceBusType = InterfaceTypeUndefined; } DevnodeClass::~DevnodeClass() { hDevnode = -1; ulProblemCode = (ULONG) -1; ulStatus = (ULONG)-1; bDNHasMark = (BOOL)-1; InterfaceBusType = InterfaceTypeUndefined; bCanDisable = FALSE; bCanTest = FALSE; bDidPass = FALSE; if ( pDeviceID ) { delete pDeviceID; pDeviceID = NULL; } if ( pszClass ) { delete pszClass; pszClass = NULL; } if ( pszDescription ) { delete pszDescription; pszDescription = NULL; } if ( pszFriendlyName ) { delete pszFriendlyName; pszFriendlyName = NULL; } if ( pszGUID ) { delete pszGUID; pszGUID = NULL; } if ( pszLocation ) { delete pszLocation; pszLocation = NULL; } if ( pszPDO ) { delete pszPDO; pszPDO = NULL; } if ( pszMFG ) { delete pszMFG; pszMFG = NULL; } if ( pHardwareID ) { delete pHardwareID; pHardwareID = NULL; } if ( pCompatID ) { delete pCompatID; pCompatID = NULL; } } /******************************************************************* Member Functions *******************************************************************/ BOOL DevnodeClass::SetHandle(DEVNODE Devnode, DEVNODE Parent) { hDevnode = -1; ulProblemCode = (ULONG) -1; ulStatus = (ULONG)-1; bDNHasMark = (BOOL)-1; InterfaceBusType = InterfaceTypeUndefined; bCanDisable = FALSE; bCanTest = FALSE; bDidPass = FALSE; if ( pDeviceID ) { delete pDeviceID; pDeviceID = NULL; } if ( pszClass ) { delete pszClass; pszClass = NULL; } if ( pszDescription ) { delete pszDescription; pszDescription = NULL; } if ( pszFriendlyName ) { delete pszFriendlyName; pszFriendlyName = NULL; } if ( pszGUID ) { delete pszGUID; pszGUID = NULL; } if ( pszLocation ) { delete pszLocation; pszLocation = NULL; } if ( pszPDO ) { delete pszPDO; pszPDO = NULL; } if ( pszMFG ) { delete pszMFG; pszMFG = NULL; } if ( pHardwareID ) { delete pHardwareID; pHardwareID = NULL; } if ( pCompatID ) { delete pCompatID; pCompatID = NULL; } hDevnode = Devnode; hParent = Parent; return (GetDeviceInformation()); } /**************************************************************************** GetDeviceInformation find information about devnode modifies this, members in DevnodeClass *****************************************************************************/ CONFIGRET DevnodeClass::GetDeviceInformation (void) { CONFIGRET retval; ULONG ulSize; // check to see that we have a devnode handle if ( !hDevnode ) { return (CR_NO_SUCH_DEVNODE); } if ( !hParent ) { DEVNODE hParentDevnode; if ( !GetParent(&hParentDevnode) ) { hParent = hParentDevnode; } } /********** Get Device ID ***********/ retval = CM_Get_Device_ID_Size (&ulSize, hDevnode, 0L); if ( retval ) return(retval); pDeviceID = new TCHAR [++ulSize]; // add one for terminating NULL if ( !pDeviceID ) return(CR_OUT_OF_MEMORY); retval = CM_Get_Device_ID (hDevnode, pDeviceID, ulSize, //is null terminated?!? 0L); if ( retval ) return(retval); /********** Get device description/friendly name ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_DEVICEDESC, NULL, NULL, &ulSize, 0); if ( retval ) if ( (retval == CR_BUFFER_SMALL) ) { //if ( bVerbose ) // logprintf ("Still Having trouble with CM_Get_DevNode_Registry_Property returning CR_BUFFER_TOO_SMALL\r\n" // "When trying to get the size of the Device description\r\n"); ulSize = 511; } else return(retval); pszDescription = new TCHAR [ulSize+1]; if ( !pszDescription ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_DEVICEDESC, NULL, pszDescription, &ulSize, 0); if ( retval ) return(retval); /********** Get device description/friendly name ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_FRIENDLYNAME, NULL, NULL, &ulSize, 0); if ( ulSize ) { pszFriendlyName = new TCHAR [ulSize+1]; if ( !pszFriendlyName ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_FRIENDLYNAME, NULL, pszFriendlyName, &ulSize, 0); if ( retval ) return(retval); } /********** Get device class ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_CLASS, NULL, NULL, &ulSize, 0); if ( retval ) { if ( (retval == CR_BUFFER_SMALL) ) { //if ( bVerbose ) // logprintf ("Still Having trouble with CM_Get_DevNode_Registry_Property returning CR_BUFFER_TOO_SMALL\r\n" // "When trying to get the size of the class\r\n"); ulSize = 511; } else if ( retval == CR_NO_SUCH_VALUE ) { //if ( bVerbose ) //{ // logprintf("This device does not have a class associated with it\r\n"); //} ulSize = 511; } else ulSize = 0; } if (ulSize) { pszClass = new TCHAR [ulSize+1]; if ( !pszClass ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_CLASS, NULL, pszClass, &ulSize, 0); if ( retval ) { if (pszClass) delete pszClass; pszClass = NULL; } else _strupr(pszClass); } /********** Get Hardware ID information ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_HARDWAREID, NULL, NULL, &ulSize, 0); if ( retval && !ulSize ) if ( (retval == CR_BUFFER_SMALL) ) { //if ( bVerbose ) // logprintf ("Still Having trouble with CM_Get_DevNode_Registry_Property returning CR_BUFFER_TOO_SMALL\r\n" // "When trying to get the size of the Device description\r\n"); ulSize = 511; } else return(retval); pHardwareID = new TCHAR [++ulSize+1]; if ( !pHardwareID ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_HARDWAREID, NULL, pHardwareID, &ulSize, 0); if ( retval ) return(retval); /********** Get Compat ID information ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_COMPATIBLEIDS, NULL, NULL, &ulSize, 0); if ( retval && !ulSize ) if ( (retval == CR_BUFFER_SMALL) ) { //if ( bVerbose ) // logprintf ("Still Having trouble with CM_Get_DevNode_Registry_Property returning CR_BUFFER_TOO_SMALL\r\n" // "When trying to get the size of the Device description\r\n"); ulSize = 511; } else ulSize = 0; if (ulSize) { pCompatID = new TCHAR [++ulSize+1]; if ( !pCompatID ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_COMPATIBLEIDS, NULL, pCompatID, &ulSize, 0); if ( retval ) return(retval); } /********** Get ClassGUID ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_CLASSGUID, NULL, NULL, &ulSize, 0); if ( ulSize ) { pszGUID = new TCHAR [ulSize+1]; if ( !pszGUID ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_CLASSGUID, NULL, pszGUID, &ulSize, 0); } /********** Get PDO Name ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME, NULL, NULL, &ulSize, 0); if ( ulSize ) { pszPDO = new TCHAR [ulSize+1]; if ( !pszPDO ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME, NULL, pszPDO, &ulSize, 0); } /********** Get MFG Name ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_MFG, NULL, NULL, &ulSize, 0); if ( ulSize ) { pszMFG = new TCHAR [ulSize+1]; if ( !pszMFG ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_MFG, NULL, pszMFG, &ulSize, 0); } /********** Get LocationInformation ***********/ ulSize = 0; retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_LOCATION_INFORMATION, NULL, NULL, &ulSize, 0); if ( ulSize ) { pszLocation = new TCHAR [ulSize+1]; if ( !pszLocation ) return(CR_OUT_OF_MEMORY); //Now get value retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_LOCATION_INFORMATION, NULL, pszLocation, &ulSize, 0); } /********** Get interface/bus type ***********/ //Now get value ulSize = sizeof(INTERFACE_TYPE); retval = CM_Get_DevNode_Registry_Property (hDevnode, CM_DRP_LEGACYBUSTYPE, NULL, &InterfaceBusType, &ulSize, 0); // if (!retval) // { // InterfaceBusType= InterfaceTypeUndefined; // } /********** Get Problem and status code ***********/ retval = CM_Get_DevNode_Status (&ulStatus, &ulProblemCode, hDevnode, 0L); if ( retval ) return(retval); /********** set bCanDisable ***********/ // If we get here, let's assume that the device is testable, and filter from there bCanDisable = TRUE; bCanTest = TRUE; return(CR_SUCCESS); } /***************************************************************************** GetXxxx fuctions *****************************************************************************/ CONFIGRET DevnodeClass::GetChild(DEVNODE *pChildDevnode) { return (CM_Get_Child(pChildDevnode, hDevnode, 0l)); } CONFIGRET DevnodeClass::GetParent(DEVNODE *pParentDevnode) { return (CM_Get_Parent(pParentDevnode, hDevnode, 0l)); } CONFIGRET DevnodeClass::GetSibling(DEVNODE *pSiblingDevnode) { return (CM_Get_Sibling(pSiblingDevnode, hDevnode, 0l)); } /***************************************************************************** Disabler Funcitons *****************************************************************************/ /* CONFIGRET DevnodeClass::Remove(ULONG uFlags) { //return (CM_Query_And_Remove_SubTree(hDevnode, NULL, NULL, 0, uFlags)); return (CM_Remove_SubTree(hDevnode, uFlags)); } */ typedef CONFIGRET (WINAPI *pCM_Query_And_Remove_SubTree)(DEVNODE, PPNP_VETO_TYPE, LPSTR, ULONG, ULONG); CONFIGRET DevnodeClass::Remove(ULONG uFlags) { static pCM_Query_And_Remove_SubTree fpCM_Query_And_Remove_SubTree = NULL; if (!fpCM_Query_And_Remove_SubTree) { OSVERSIONINFO ver; memset(&ver, 0, sizeof(OSVERSIONINFO)); ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&ver); if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) { // is windows NT HINSTANCE hinst; hinst = LoadLibrary(_T("cfgmgr32.dll")); fpCM_Query_And_Remove_SubTree = (pCM_Query_And_Remove_SubTree)GetProcAddress(hinst, "CM_Query_And_Remove_SubTreeA"); //a-kjaw to fix prefix bug 259378. if(NULL == fpCM_Query_And_Remove_SubTree) return CR_FAILURE; } else { //else is not winnt fpCM_Query_And_Remove_SubTree = (pCM_Query_And_Remove_SubTree)-1; } } if (fpCM_Query_And_Remove_SubTree == (pCM_Query_And_Remove_SubTree)-1) { // is win9x return (CM_Remove_SubTree(hDevnode, uFlags)); } else { return (fpCM_Query_And_Remove_SubTree(hDevnode, NULL, NULL, 0, uFlags)); } } CONFIGRET DevnodeClass::Refresh(ULONG uFlags) { CONFIGRET retval; retval = CM_Reenumerate_DevNode(hParent, uFlags); if ( retval ) return (retval); retval = FindDevnode(); GetProblemCode(); return(retval); } CONFIGRET DevnodeClass::Disable(ULONG uFlags) { return (CM_Disable_DevNode(hDevnode, uFlags)); } CONFIGRET DevnodeClass::Enable(ULONG uFlags) { CONFIGRET retval; retval = CM_Enable_DevNode(hDevnode, uFlags); if ( retval ) return (retval); return (FindDevnode()); } CONFIGRET DevnodeClass::GetProblemCode(ULONG *Status, ULONG *Problem) { CONFIGRET retval; retval = CM_Get_DevNode_Status (&ulStatus, &ulProblemCode, hDevnode, 0L); if ( retval ) return(retval); if (Status) *Status = ulStatus; if (Problem) *Problem = ulProblemCode; return (retval); } /************** FindDevnode This function just updates the hDevnode, refreshed the device, and updates the status and problem code **************/ CONFIGRET DevnodeClass::FindDevnode(void) { CONFIGRET retval; retval = CM_Locate_DevNode (&hDevnode, pDeviceID, CM_LOCATE_DEVNODE_NORMAL); if ( retval ) { hDevnode = NULL; ulProblemCode = (ULONG)-1; ulStatus = (ULONG)-1; return (retval); } return (CM_Reenumerate_DevNode (hDevnode, CM_REENUMERATE_SYNCHRONOUS)); } /*************** operator== *************/ int DevnodeClass::operator==(const DevnodeClass &OtherDevnode) { if ( strcmp(pDeviceID, OtherDevnode.pDeviceID) ) return (FALSE); if ( ulProblemCode != OtherDevnode.ulProblemCode ) { return (FALSE); } if ( (ulStatus ^ OtherDevnode.ulStatus) & ~IGNORE_ME_BITS ) { return (FALSE); } return (TRUE); } ULONG ReadRegKeyInformationSZ (HKEY RootKey, TCHAR *KeyName, TCHAR **Value) { TCHAR * szBuffer; LONG retval; DWORD dwSize = 0; DWORD dwType = 0; // make sure the buffer is clear //assert (Value); // make sure that we actually got a value //assert (!*Value); // and also make sure that the buffer is already empty // for non debug versions *Value = NULL; //a-kjaw. Prefix bug no. 259379. if dwSize if not NULL &lpData is Null // func returns the size reqd to store the string which helps string allocation. retval = RegQueryValueEx(RootKey, KeyName, 0, // reserved &dwType, NULL, &dwSize); if ( retval != ERROR_SUCCESS ) { return (retval); // cant continue } if ( (dwType != REG_SZ) || !dwSize ) { return (ERROR_FILE_NOT_FOUND); } szBuffer = new TCHAR[++dwSize]; if ( !szBuffer ) { return (ERROR_NOT_ENOUGH_MEMORY); } retval = RegQueryValueEx(RootKey, KeyName, 0, // reserved &dwType, (UCHAR *)szBuffer, &dwSize); if ( retval ) { delete szBuffer; return (retval); } *Value = szBuffer; return (ERROR_SUCCESS); } BOOL Enumerate_WalkTree_Devnode(DEVNODE hDevnode, DEVNODE hParent) { CONFIGRET retval; DevnodeClass *pNewDevice; DEVNODE hSib; pNewDevice = new DevnodeClass(hDevnode, hParent); retval = pNewDevice->GetChild(&hSib); if ( !retval ) { Enumerate_WalkTree_Devnode(hSib, hDevnode); } retval = pNewDevice->GetSibling(&hSib); if ( !retval ) { Enumerate_WalkTree_Devnode(hSib, hParent); } return (retval); } ULONG EnumerateTree_Devnode(void) { DEVNODE hDevnode; CM_Locate_DevNode(&hDevnode, NULL, CM_LOCATE_DEVNODE_NORMAL); Enumerate_WalkTree_Devnode(hDevnode, NULL); return (DevnodeClass::ALCCount()); }