static void PrintDevinstChildren(uint parent, uint indent, ushort deviceAddress, StringBuilder output) { uint next = 0; uint current = parent; uint level = indent; Stack <ushort> nodeStack = new Stack <ushort>(); ushort parentNode = 0; uint sanityCounter = 0; ushort nextNode = 1; CONFIGRET cr = SafeMethods.CM_Get_Child(ref next, current, 0); if (cr == CONFIGRET.CR_SUCCESS) { current = next; level++; nodeStack.Push(parentNode); } while (level > indent) { if ((++sanityCounter) > SafeMethods.LOOP_SANITY_LIMIT) { output.AppendLine("Sanity check failed in PrintDevinstChildren()"); return; } byte[] buf = new byte[SafeMethods.MAX_DEVICE_ID_LEN]; GCHandle gcHandle = GCHandle.Alloc(buf, GCHandleType.Pinned); uint len = (uint)buf.Length; try { cr = SafeMethods.CM_Get_DevNode_Registry_Property(current, (uint)CM_DRP.CM_DRP_FRIENDLYNAME, out _, gcHandle.AddrOfPinnedObject(), ref len, 0); if (cr != CONFIGRET.CR_SUCCESS) { len = (uint)buf.Length; /* Failed to get friendly name, * display device description instead */ cr = SafeMethods.CM_Get_DevNode_Registry_Property(current, (uint)CM_DRP.CM_DRP_DEVICEDESC, out _, gcHandle.AddrOfPinnedObject(), ref len, 0); } if (cr == CONFIGRET.CR_SUCCESS) { string deviceDesc = Marshal.PtrToStringAnsi(gcHandle.AddrOfPinnedObject()); if (string.IsNullOrEmpty(deviceDesc) == false) { if (nodeStack.TryPeek(out parentNode) == false) { parentNode = 0; } } print_usbpcapcmd(level, 0, deviceDesc, deviceAddress, deviceAddress, nextNode, parentNode, output); } // Go down a level to the first next. cr = SafeMethods.CM_Get_Child(ref next, current, 0); if (cr == CONFIGRET.CR_SUCCESS) { current = next; level++; nodeStack.Push(nextNode); nextNode++; continue; } } finally { gcHandle.Free(); } // Can't go down any further, go across to the next sibling. If // there are no more siblings, go back up until there is a sibling. // If we can't go up any further, we're back at the root and we're // done. for (; ;) { cr = SafeMethods.CM_Get_Sibling(ref next, current, 0); if (cr == CONFIGRET.CR_SUCCESS) { current = next; nextNode++; break; } else if (cr == CONFIGRET.CR_NO_SUCH_DEVNODE) { cr = SafeMethods.CM_Get_Parent(out next, current, 0); if (cr == CONFIGRET.CR_SUCCESS) { current = next; level--; parentNode = nodeStack.Pop(); if (current == parent || level == indent) { /* We went back to the parent, explicitly return here */ return; } } else { while (true == nodeStack.TryPop(out parentNode)) { ; } /* Nothing left to do */ return; } } else { output.AppendLine($"CM_Get_Sibling() returned {cr}"); return; } } } }
static void PrintDeviceDesc(string DriverName, uint index, uint Level, bool printAllChildren, ushort deviceAddress, ushort parentAddress, StringBuilder output) { uint devInst = 0; uint devInstNext = 0; CONFIGRET cr = SafeMethods.CM_Locate_DevNodeA(ref devInst, null, 0); if (cr != CONFIGRET.CR_SUCCESS) { return; } uint sanityOuter = 0; uint sanityInner = 0; uint walkDone = 0; while (walkDone == 0) { if ((++sanityOuter) > SafeMethods.LOOP_SANITY_LIMIT) { output.AppendLine("Sanity check failed in PrintDeviceDesc() outer loop!"); return; } byte[] buf = new byte[SafeMethods.MAX_DEVICE_ID_LEN]; GCHandle gcHandle = GCHandle.Alloc(buf, GCHandleType.Pinned); uint len = (uint)buf.Length; try { cr = SafeMethods.CM_Get_DevNode_Registry_Property(devInst, (uint)CM_DRP.CM_DRP_DRIVER, out _, gcHandle.AddrOfPinnedObject(), ref len, 0); if (cr == CONFIGRET.CR_SUCCESS) { string devNodeName = Marshal.PtrToStringAnsi(gcHandle.AddrOfPinnedObject()); if (DriverName.StartsWith(devNodeName, StringComparison.OrdinalIgnoreCase) == true) { len = (uint)buf.Length; cr = SafeMethods.CM_Get_DevNode_Registry_Property(devInst, (uint)CM_DRP.CM_DRP_DEVICEDESC, out _, gcHandle.AddrOfPinnedObject(), ref len, 0); if (cr == CONFIGRET.CR_SUCCESS) { string deviceDesc = Marshal.PtrToStringAnsi(gcHandle.AddrOfPinnedObject()); print_usbpcapcmd(Level, index, deviceDesc, deviceAddress, parentAddress, 0, 0, output); if (printAllChildren == true) { PrintDevinstChildren(devInst, Level, deviceAddress, output); } } } } else if (cr == CONFIGRET.CR_NO_SUCH_VALUE) { // No Driver name, it's ok } else { output.AppendLine($"Failed to get CM_DRP_DRIVER: {cr}"); return; } cr = SafeMethods.CM_Get_Child(ref devInstNext, devInst, 0); if (cr == CONFIGRET.CR_SUCCESS) { devInst = devInstNext; continue; } sanityInner = 0; for (; ;) { if ((++sanityInner) > SafeMethods.LOOP_SANITY_LIMIT) { output.AppendLine("Sanity check failed in PrintDeviceDesc() inner loop!"); return; } cr = SafeMethods.CM_Get_Sibling(ref devInstNext, devInst, 0); if (cr == CONFIGRET.CR_SUCCESS) { devInst = devInstNext; break; } else if (cr == CONFIGRET.CR_NO_SUCH_DEVNODE) { // Device doesn't have siblings, go up and try again cr = SafeMethods.CM_Get_Parent(out devInstNext, devInst, 0); if (cr == CONFIGRET.CR_SUCCESS) { devInst = devInstNext; } else { walkDone = 1; break; } } else { output.AppendLine($"CM_Get_Sibling() returned {cr}"); return; } } } finally { gcHandle.Free(); } } }