This program use the undocumented NtQuerySystemInformation
and NtQueryObject to get a list of PID and information about them.
Information like the handle id, granted access, object name,
PID flags, filename and object type.

It mimic some function of the HandleEx.exe and
ProceXP.exe from Mark Russinovich at Sysinternals.

A search engine is incorporated to find string like "Serial0"
or "COM2" or "\Device\Tcp" to find whitch program is using what port.

Thanks to Semen Matusovski, Nathan Evans and Cliff Nichols.
As usual, use at your own risk.

Have fun.

Pierre

Discussion: here

Note that the use of NtQueryObject with certain PID
is problematic, so some care must be taken about this.
No real satisfactory solution yet, work in progress.

Code:
#COMPILE EXE '#Win 8.03#
#INCLUDE "win32api.inc" '#2005-01-27#
#OPTION VERSION5
 
GLOBAL hDlg     AS DWORD
GLOBAL hList    AS DWORD
GLOBAL sObjName AS STRING
 
$Title = "QuerySystemInformation"
 
%Grip         = 101
%Listbox      = 201
%Checkbox     = 301
%Combobox     = 401
%ButtonSearch = 501
%ButtonQuery  = 502
%ButtonQuit   = 503
 
%ObjectNameInformation       = &h01
%SystemHandleInformation     = &h10
 
%STATUS_SUCCESS              = &h00000000
%STATUS_MORE_ENTRIES         = &h00000105
%STATUS_INFO_LENGTH_MISMATCH = &hC0000004
%STATUS_BUFFER_OVERFLOW      = &h80000005
%STATUS_SEVERITY_ERROR       = &h00000003
 
TYPE SYSTEM_HANDLE_INFORMATION 'Information Class is &h10
  ProcessID        AS DWORD
  ObjectTypeNumber AS BYTE
  Flags            AS BYTE
  Handle           AS WORD
  Object           AS DWORD
  GrantedAccess    AS DWORD
END TYPE
 
TYPE SYSTEM_HANDLE_TABLE_ENTRY_INFO
  NumberOfHandles AS DWORD
  HANDLES(0 TO 0) AS SYSTEM_HANDLE_INFORMATION
END TYPE
 
TYPE UNICODE_STRING
  Length        AS WORD  'Length in bytes of string in Buffer
  MaximumLength AS WORD  'Maximum length in bytes of Buffer
  pBuffer       AS DWORD 'Pointer to unicode string
END TYPE
 
DECLARE FUNCTION NtQuerySystemInformation LIB "NtDLL.DLL" ALIAS "NtQuerySystemInformation"( _
  BYVAL SystemInformationClass  AS DWORD, _
  BYVAL SystemInformation       AS DWORD, _
  BYVAL SystemInformationLength AS DWORD, _
  BYREF ReturnLength            AS DWORD) AS LONG
 
DECLARE FUNCTION NtQueryObject LIB "NtDLL.DLL" ALIAS "NtQueryObject"( _
  BYVAL hndl                    AS DWORD, _
  BYVAL ObjectInformationClass  AS DWORD, _
  BYVAL ObjectInformation       AS DWORD, _
  BYVAL ObjectInformationLength AS DWORD, _
  BYREF ReturnLength            AS DWORD) AS LONG
 
'NtClose issuperseded by CloseHandle
'DECLARE FUNCTION NtClose LIB "NtDLL.DLL" ALIAS "NtClose"( _
'  BYVAL hndl AS DWORD) AS LONG  'STATUS_SUCCESS if handle was closed.
 
DECLARE FUNCTION EnumProcessModules LIB "PsApi.DLL" ALIAS "EnumProcessModules"( _
  BYVAL hProcess  AS DWORD, _
  BYVAL lphModule AS DWORD, _
  BYVAL cb        AS DWORD, _
  BYREF cbNeeded  AS DWORD) AS LONG
 
DECLARE FUNCTION GetModuleFileNameEx LIB "PsApi.DLL" ALIAS "GetModuleFileNameExA"( _
  BYVAL hProcess AS DWORD, _
  BYVAL hModule  AS DWORD, _
  lpFilename     AS ASCIIZ, _
  BYVAL nSize    AS DWORD) AS LONG
 
DECLARE FUNCTION ListAdd(AddToList AS STRING) AS LONG
'______________________________________________________________________________
 
FUNCTION ObjectTypeName(BYVAL ObjectType AS LONG) AS STRING
 STATIC NtVer AS DWORD
 LOCAL  os AS OSVERSIONINFO
 
 IF NtVer = 0 THEN
   os.dwOSVersionInfoSize = SIZEOF(os)
   GetVersionEx os
   IF os.dwPlatformId = %VER_PLATFORM_WIN32_NT THEN
     IF os.dwMajorVersion = 4 THEN
       NtVer = 4  'Window NT 4
     ELSEIF (os.dwMajorVersion = 5) AND (os.dwMinorVersion = 0) THEN
       NtVer = 50 'Windows 2000
     ELSE
       NtVer = 51 'Windows XP 5.1, probably 2003 5.2 and Vista 6.x
     END IF
   END IF
 END IF
 
 SELECT CASE NtVer
   CASE 4 'Window NT 4
     SELECT CASE ObjectType
       CASE 01 : FUNCTION =  "1: Type"
       CASE 02 : FUNCTION =  "2: Directory"
       CASE 03 : FUNCTION =  "3: SymbolicLink"
       CASE 04 : FUNCTION =  "4: Token"
       CASE 05 : FUNCTION =  "5: Process"
       CASE 06 : FUNCTION =  "6: Thread"
       CASE 07 : FUNCTION =  "7: Event"
       CASE 08 : FUNCTION =  "8: EventPair"
       CASE 09 : FUNCTION =  "9: Mutant"
       CASE 10 : FUNCTION = "10: Semaphore"
       CASE 11 : FUNCTION = "11: Timer"
       CASE 12 : FUNCTION = "12: Profile"
       CASE 13 : FUNCTION = "13: WindowStation"
       CASE 14 : FUNCTION = "14: Desktop"
       CASE 15 : FUNCTION = "15: Section"
       CASE 16 : FUNCTION = "16: Key"
       CASE 17 : FUNCTION = "17: Port"
       CASE 18 : FUNCTION = "18: Adapter"
       CASE 19 : FUNCTION = "19: Controller"
       CASE 20 : FUNCTION = "20: Device"
       CASE 21 : FUNCTION = "21: Driver"
       CASE 22 : FUNCTION = "22: IoCompletion"
       CASE 23 : FUNCTION = "23: File"
       CASE ELSE : FUNCTION = FORMAT$(ObjectType) & ": Not defined"
     END SELECT
 
   CASE 50 'Windows 2000
     SELECT CASE ObjectType
       CASE 01 : FUNCTION =  "1: Type"
       CASE 02 : FUNCTION =  "2: Directory"
       CASE 03 : FUNCTION =  "3: SymbolicLink"
       CASE 04 : FUNCTION =  "4: Token"
       CASE 05 : FUNCTION =  "5: Process"
       CASE 06 : FUNCTION =  "6: Thread"
       CASE 07 : FUNCTION =  "7: Job"
       CASE 08 : FUNCTION =  "8: Event"
       CASE 09 : FUNCTION =  "9: EventPair"
       CASE 10 : FUNCTION = "10: Mutant"
       CASE 11 : FUNCTION = "11: Callback"
       CASE 12 : FUNCTION = "12: Semaphore"
       CASE 13 : FUNCTION = "13: Timer"
       CASE 14 : FUNCTION = "14: Profile"
       CASE 15 : FUNCTION = "15: WindowStation"
       CASE 16 : FUNCTION = "16: Desktop"
       CASE 17 : FUNCTION = "17: Section"
       CASE 18 : FUNCTION = "18: Key"
       CASE 19 : FUNCTION = "19: Port"
       CASE 20 : FUNCTION = "20: WaitablePort"
       CASE 21 : FUNCTION = "21: Adapter"
       CASE 22 : FUNCTION = "22: Controller"
       CASE 23 : FUNCTION = "23: Device"
       CASE 24 : FUNCTION = "24: Driver"
       CASE 25 : FUNCTION = "25: IoCompletion"
       CASE 26 : FUNCTION = "26: File"
       CASE 27 : FUNCTION = "27: WmiGuid"
       CASE ELSE : FUNCTION = FORMAT$(ObjectType) & ": Not defined"
     END SELECT
 
   CASE 51 'Windows XP, probably 2003 and Vista
     SELECT CASE ObjectType
       CASE 01 : FUNCTION =  "1: Type"
       CASE 02 : FUNCTION =  "2: Directory"
       CASE 03 : FUNCTION =  "3: SymbolicLink"
       CASE 04 : FUNCTION =  "4: Token"
       CASE 05 : FUNCTION =  "5: Process"
       CASE 06 : FUNCTION =  "6: Thread"
       CASE 07 : FUNCTION =  "7: Job"
       CASE 08 : FUNCTION =  "8: DebugObject"
       CASE 09 : FUNCTION =  "9: Event"
       CASE 10 : FUNCTION = "10: EventPair"
       CASE 11 : FUNCTION = "11: Mutant"
       CASE 12 : FUNCTION = "12: Callback"
       CASE 13 : FUNCTION = "13: Semaphore"
       CASE 14 : FUNCTION = "14: Timer"
       CASE 15 : FUNCTION = "15: Profile"
       CASE 16 : FUNCTION = "16: KeyedEvent"
       CASE 17 : FUNCTION = "17: WindowStation"
       CASE 18 : FUNCTION = "18: Desktop"
       CASE 19 : FUNCTION = "19: Section"
       CASE 20 : FUNCTION = "20: Key"
       CASE 21 : FUNCTION = "21: Port"
       CASE 22 : FUNCTION = "22: WaitablePort"
       CASE 23 : FUNCTION = "23: Adapter"
       CASE 24 : FUNCTION = "24: Controller"
       CASE 25 : FUNCTION = "25: Device"
       CASE 26 : FUNCTION = "26: Driver"
       CASE 27 : FUNCTION = "27: IoCompletion"
       CASE 28 : FUNCTION = "28: File"
       CASE 29 : FUNCTION = "29: WmiGuid"
       CASE ELSE : FUNCTION = FORMAT$(ObjectType) & ": Not defined"
     END SELECT
 
 END SELECT
 
 ' Windows NT 4          Window 2000            Window XP, probably 2003 and Vista
 ' -----------------     -------------------    -------------------
 '  1 - Type              1 - Type               1 - (Type)
 '  2 - Directory         2 - Directory          2 - Directory
 '  3 - SymbolicLink      3 - SymbolicLink       3 - SymbolicLink
 '  4 - Token             4 - Token              4 - Token
 '  5 - Process           5 - Process            5 - Process
 '  6 - Thread            6 - Thread             6 - Thread
 '  7 - Event             7 - Job                7 - Job
 '  8 - EventPair         8 - Event              8 - ((DebugObject))
 '  9 - Mutant            9 - EventPair          9 - Event
 ' 10 - Semaphore        10 - Mutant            10 - (EventPair)
 ' 11 - Timer            11 - Callback          11 - Mutant
 ' 12 - Profile          12 - Semaphore         12 - (Callback)
 ' 13 - WindowStation    13 - Timer             13 - Semaphore
 ' 14 - Desktop          14 - Profile           14 - Timer
 ' 15 - Section          15 - WindowsStation    15 - (Profile)
 ' 16 - Key              16 - Desktop           16 - KeyedEvent
 ' 17 - Port             17 - Section           17 - WindowStation
 ' 18 - Adapter          18 - Key               18 - Desktop
 ' 19 - Controller       19 - Port              19 - Section
 ' 20 - Device           20 - WaitablePort      20 - Key
 ' 21 - Driver           21 - Adapter           21 - Port
 ' 22 - IoCompletion     22 - Controller        22 - WaitablePort
 ' 23 - File             23 - Device            23 - (Adapter)
 '                       24 - Driver            24 - (Controller)
 '                       25 - IoCompletion      25 - (Device)
 '                       26 - File              26 - (Driver)
 '                       27 - WmiGuid           27 - IoCompletion
 '                                              28 - File
 '                                              29 - WmiGuid
END FUNCTION
'______________________________________________________________________________
 
FUNCTION pidGetFileName(PID AS DWORD) AS STRING
 LOCAL ModuleName  AS STRING
 LOCAL PidPath     AS STRING
 LOCAL sBuffer     AS STRING
 LOCAL pBuffer     AS DWORD PTR
 LOCAL LenBuffer   AS DWORD
 LOCAL hProcess    AS DWORD
 LOCAL ByteNeeded  AS DWORD
 LOCAL HandleCount AS DWORD
 LOCAL Looper      AS LONG
 LOCAL Retval      AS LONG
 
 hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ, 0, Pid)
 IF hProcess THEN
   ByteNeeded = 4 'SIZEOF(DWORD)
   FOR Looper = 1 TO 2
     LenBuffer = ByteNeeded
     sBuffer = NUL$(ByteNeeded)
     pBuffer = STRPTR(sBuffer)
     Retval = EnumProcessModules(hProcess, pBuffer, LenBuffer, ByteNeeded)
   NEXT
 
   IF Retval THEN
     HandleCount = LenBuffer \ 4
     DIM ModulesHandles(1 TO HandleCount) AS DWORD AT pBuffer
     ModuleName = "Unknown" & NUL$(%MAX_PATH)
     Retval = GetModuleFileNameEx(hProcess, ModulesHandles(1), BYVAL STRPTR(ModuleName), %MAX_PATH)
     PidPath = "FileName: " & LEFT$(ModuleName, Retval)
   ELSE
     'ListAdd  "Bad EnumProcessModules"
   END IF
   CloseHandle hProcess
 END IF
 
 IF PidPath = "" THEN PidPath = "FileName: SYSTEM"
 FUNCTION = PidPath
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION pidGetObjectNameThread(hPort AS DWORD) AS LONG
 LOCAL puString   AS UNICODE_STRING POINTER
 LOCAL sBuffer    AS STRING
 LOCAL pzBuffer   AS ASCIIZ POINTER
 LOCAL psBuffer   AS DWORD POINTER
 LOCAL LenBuffer  AS DWORD
 LOCAL ByteNeeded AS DWORD
 LOCAL ByteCount  AS DWORD
 LOCAL Looper     AS LONG
 LOCAL Retval     AS LONG
 
 ByteNeeded = SIZEOF(UNICODE_STRING)
 FOR Looper = 1 TO 2
   LenBuffer = ByteNeeded
   sBuffer = NUL$(ByteNeeded)
   psBuffer = STRPTR(sBuffer)
   Retval = NtQueryObject(hPort, %ObjectNameInformation, psBuffer, LenBuffer, ByteNeeded)
 NEXT
 
 IF Retval = %STATUS_SUCCESS THEN
   puString = psBuffer
   IF @puString.Length > 0 THEN
     sObjName = NUL$(@puString.Length \ 2)
     WideCharToMultiByte %CP_ACP, %NULL, BYVAL @puString.pBuffer, @puString.Length, _
                         BYVAL STRPTR(sObjName), LEN(sObjName), BYVAL %NULL, BYVAL %NULL
     sObjName = "ObjName: " & sObjName
   END IF
 END IF
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION pidGetObjectName(ProcessId AS DWORD, Hndl AS WORD) AS LONG
 LOCAL hPort      AS DWORD
 LOCAL hProc      AS DWORD
 LOCAL idThread   AS DWORD
 LOCAL hThread    AS DWORD
 LOCAL Retval     AS LONG
 
 sObjName = ""
 IF ProcessId THEN
   hProc = OpenProcess(%PROCESS_DUP_HANDLE, 0, ProcessId)
   IF (hProc <> %INVALID_HANDLE_VALUE) AND (hProc <> 0) THEN
     IF DuplicateHandle(hProc, BYVAL Hndl, -1, hPort, 0, _
                        %PROCESS_ALL_ACCESS, %DUPLICATE_SAME_ACCESS) THEN
 
       hThread = CreateThread(BYVAL %NULL, 0, CODEPTR(pidGetObjectNameThread), BYREF hPort, _
                              %THREAD_TERMINATE OR %THREAD_QUERY_INFORMATION, BYVAL VARPTR(idThread))
       Retval = WaitForSingleObject(hThread, 30) 'Wait 30 miliseconds maximum
 
       IF Retval = %WAIT_TIMEOUT THEN 'Failure
         Retval = TerminateThread(hThread, 13) '??? NtTerminateProcess NtTerminateThread
         CloseHandle hThread
         sObjName = "ObjName: Error"
       END IF
       CloseHandle hPort
 
     ELSE
       'FUNCTION = "No DuplicateHandle"
     END IF
     CloseHandle hProc
   ELSE
     'FUNCTION = "Bad OpenProcess"
   END IF
 END IF
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION pidEnum AS LONG
 LOCAL pInfoTable  AS SYSTEM_HANDLE_TABLE_ENTRY_INFO POINTER
 LOCAL sBuffer     AS STRING
 LOCAL sObjectType AS STRING
 LOCAL sFileName   AS STRING
 LOCAL pBuffer     AS DWORD PTR
 LOCAL LenBuffer   AS DWORD
 LOCAL ByteNeeded  AS DWORD
 LOCAL InfoCount   AS DWORD
 LOCAL Looper      AS DWORD
 LOCAL AllHandle   AS LONG
 LOCAL Retval      AS LONG
 
 ByteNeeded = SIZEOF(SYSTEM_HANDLE_TABLE_ENTRY_INFO) 'Minimum buffer size for a valid ByteNeeded
 FOR Looper = 1 TO 2
   LenBuffer = ByteNeeded
   sBuffer = NUL$(ByteNeeded)
   pBuffer = STRPTR(sBuffer)
   Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)
 NEXT
 
 pInfoTable = pBuffer
 InfoCount  = @pInfoTable.NumberOfHandles
 
 Retval = SendMessage(hList, %LB_INITSTORAGE, InfoCount * 4, InfoCount * 200) 'Faster listbox filling
 
 DIM Info(1 TO InfoCount) AS SYSTEM_HANDLE_INFORMATION AT pInfoTable + 4 '+ 4 to start just after .NumberOfHandles
 FOR Looper = 1 TO InfoCount
 
   sFileName = pidGetFileName(Info(Looper).ProcessID)
   pidGetObjectName(Info(Looper).ProcessID, Info(Looper).Handle)
 
   CONTROL GET CHECK hDlg, %Checkbox TO Retval
   AllHandle = (Retval = 0)
 
   IF (LEN(sObjName) OR AllHandle) THEN
     ListAdd "Number "    & FORMAT$(Looper)                               & _
             " - Pid "    & FORMAT$(Info(Looper).ProcessID)               & _
             " - Handle " & HEX$(Info(Looper).Handle, 4)                  & _
             " - Type "   & ObjectTypeName(Info(Looper).ObjectTypeNumber) & _
             " - Access " & HEX$(Info(Looper).GrantedAccess, 8)           & _
             " - Object " & HEX$(Info(Looper).Object, 8)                  & _
             " - Flag "   & HEX$(Info(Looper).Flags, 1)                   & _
             CHOOSE$(Info(Looper).Flags + 1, " (None)", " (Protect_from_close)", " (Inherit)")
 
     IF LEN(sFileName) THEN ListAdd "   " & sFileName
     'sFileName = UCASE$(sFileName)
     'IF (INSTR(sFileName, "FILENAME: SYSTEM"      ) = 0) AND _  'Those can freeze
     '   (INSTR(sFileName, "\SYSTEM32\SERVICES.EXE") = 0) AND _
     '   (INSTR(sFileName, "\SYSTEM32\LSASS.EXE"   ) = 0) AND _
     '   (INSTR(sFileName, "\SYSTEM32\SVCHOST.EXE" ) = 0) AND _
     '   (INSTR(sFileName, "\ZONELABS\VSMON.EXE"   ) = 0) THEN
          'pidGetObjectName(Info(Looper).ProcessID, Info(Looper).Handle)
          IF LEN(sObjName) THEN ListAdd "   " & sObjName
     'END IF
 
     ListAdd ""
   END IF
 
 NEXT
 DIALOG SET TEXT hDlg, $Title & " -" & STR$(InfoCount) & " handles found"
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION LoadPrivilege(BYVAL sPrivilege AS STRING) AS LONG
 LOCAL  TokenPrivilege   AS TOKEN_PRIVILEGES
 LOCAL  SEDebugNameValue AS LUID
 LOCAL  hToken           AS DWORD
 LOCAL  hProcessHandle   AS DWORD
 
 hProcessHandle = GetCurrentProcess()
 IF hProcessHandle THEN
   OpenProcessToken hProcessHandle, (%TOKEN_ADJUST_PRIVILEGES OR %TOKEN_QUERY), hToken
   IF hToken THEN
     IF LookupPrivilegeValue("", BYCOPY sPrivilege, SEDebugNameValue) THEN
       TokenPrivilege.PrivilegeCount = 1
       TokenPrivilege.Privileges(0).pLuid = SEDebugNameValue
       TokenPrivilege.Privileges(0).Attributes = %SE_PRIVILEGE_ENABLED
       IF AdjustTokenPrivileges(hToken, %False, TokenPrivilege, SIZEOF(TokenPrivilege), _
                                BYVAL 0, BYVAL 0) THEN
         FUNCTION = %TRUE
       ELSE
         MSGBOX "AdjustTokenPrivileges, Error: " & FORMAT$(GetLastError())
       END IF
     ELSE
       MSGBOX "LookupPrivilegeValue, Error: " & FORMAT$(GetLastError())
     END IF
   ELSE
     MSGBOX "OpenProcessToken, Error: " & FORMAT$(GetLastError())
   END IF
 ELSE
   MSGBOX "GetCurrentProcess, Error: " & FORMAT$(GetLastError())
 END IF
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION SetHorizontalListboxBar() AS LONG
 LOCAL  hFont     AS DWORD
 LOCAL  hDC       AS DWORD
 LOCAL  ListWidth AS LONG
 LOCAL  LastItem  AS LONG
 LOCAL  Counter   AS LONG
 LOCAL  sBuffer   AS STRING
 LOCAL  TextLen   AS LONG
 LOCAL  Si        AS apiSize
 LOCAL  Looper    AS LONG
 
 hFont = SendMessage(hList, %WM_GETFONT, 0, 0)
 hDC = GetDC(hList)
 IF hFont THEN hFont = SelectObject(hDC, hFont)
 LastItem = SendMessage(hList, %LB_GETCOUNT, 0, 0) - 1
 IF LastItem > 0 THEN
   FOR Looper = 0 TO LastItem
     TextLen = SendMessage(hList, %LB_GETTEXTLEN, Looper, 0)
     IF TextLen THEN
       sBuffer = NUL$(TextLen)
       SendMessage hList, %LB_GETTEXT, Looper, STRPTR(sBuffer)
       GetTextExtentPoint32 hDC, BYCOPY sBuffer + "W", TextLen + 1, Si
       ListWidth = MAX& (ListWidth, Si.cx)
     END IF
   NEXT
   SendMessage hList, %LB_SETHORIZONTALEXTENT, ListWidth, 0
 END IF
 IF hFont THEN SelectObject hDC, hFont
 ReleaseDC hList, hDC
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION ListAdd(AddToList AS STRING) AS LONG
 LOCAL LastItem AS LONG
 
 LastItem = SendMessage(hList, %LB_GETCOUNT,  0, 0) - 1
 LastItem = SendMessage(hList, %LB_ADDSTRING, LastItem, ByVal STRPTR(AddToList))
 
END FUNCTION
'______________________________________________________________________________
 
CALLBACK FUNCTION DlgProc
 LOCAL MinMaxInfoPtr AS MINMAXINFO POINTER
 LOCAL sBuffer       AS STRING
 LOCAL sTextbox      AS STRING
 LOCAL ListTabStop() AS LONG
 LOCAL Counter       AS LONG
 LOCAL Retval        AS LONG
 LOCAL LastItem      AS LONG
 LOCAL TextLen       AS LONG
 LOCAL Looper        AS LONG
 LOCAL Found         AS LONG
 STATIC Index        AS LONG
 
 SELECT CASE CBMSG
   CASE %WM_INITDIALOG
     CONTROL HANDLE hDlg, %Listbox TO hList
 
   CASE %WM_COMMAND
     SELECT CASE LOWRD(CBWPARAM)
 
       CASE %ButtonQuery
         IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
           CONTROL DISABLE hDlg, %Checkbox
           CONTROL DISABLE hDlg, %Combobox
           CONTROL DISABLE hDlg, %ButtonQuit
           CONTROL DISABLE hDlg, %ButtonQuery
           CONTROL DISABLE hDlg, %ButtonSearch
           LISTBOX RESET CBHNDL, %Listbox
           DIALOG SET TEXT CBHNDL, $Title & " - Please wait..."
           CONTROL REDRAW CBHNDL, %Listbox
           SLEEP 300
           pidEnum
           SetHorizontalListboxBar
           CONTROL ENABLE hDlg, %ButtonSearch
           CONTROL ENABLE hDlg, %ButtonQuery
           CONTROL ENABLE hDlg, %ButtonQuit
           CONTROL ENABLE hDlg, %Combobox
           CONTROL ENABLE hDlg, %Checkbox
         END IF
 
       CASE %ButtonSearch, %IDOK
         IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
           CONTROL GET TEXT CBHNDL, %Combobox TO sTextbox
           IF LEN(sTextbox) THEN
             sTextbox = UCASE$(sTextbox)
             LastItem = SendMessage(hList, %LB_GETCOUNT, 0, 0) - 1
             IF LastItem > 0 THEN
 
               IF Index = LastItem THEN Index = -1
               INCR Index
               FOR Looper = Index TO LastItem
                 TextLen = SendMessage(hList, %LB_GETTEXTLEN, Looper, 0)
                 IF TextLen THEN
                   sBuffer = NUL$(TextLen)
                   SendMessage hList, %LB_GETTEXT, Looper, STRPTR(sBuffer)
                   sBuffer = UCASE$(sBuffer)
                   IF INSTR(sBuffer, sTextbox) THEN
                     Index = Looper
                     Found = %TRUE
                     SendMessage hList, %LB_SETCURSEL, Index, 0
                     EXIT FOR
                   END IF
                 END IF
               NEXT
 
               IF Found = %FALSE THEN
                 FOR Looper = 0 TO Index
                   TextLen = SendMessage(hList, %LB_GETTEXTLEN, Looper, 0)
                   IF TextLen THEN
                     sBuffer = NUL$(TextLen)
                     SendMessage hList, %LB_GETTEXT, Looper, STRPTR(sBuffer)
                     sBuffer = UCASE$(sBuffer)
                     IF INSTR(sBuffer, sTextbox) THEN
                       Index = Looper
                       Found = %TRUE
                       SendMessage hList, %LB_SETCURSEL, Index, 0
                       EXIT FOR
                     END IF
                   END IF
                 NEXT
               END IF
 
               IF Found = %FALSE THEN
                 BEEP
               END IF
             END IF
           END IF
         END IF
 
       CASE %ButtonQuit, %IDCANCEL
         IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
           DIALOG END CBHNDL
         END IF
 
       CASE %Listbox
         IF CBCTLMSG = %LBN_SELCHANGE THEN
           Retval = SendMessage(hList, %LB_GETCURSEL, 0, 0)
           IF Retval > -1 THEN
             Index = Retval
           END IF
         END IF
 
     END SELECT
 
   CASE %WM_SIZE 'Resize and repos controls if parent is resized
     MoveWindow hList, 10, 10, LOWRD(CBLPARAM) - 20, HIWRD(CBLPARAM) - 50, %TRUE
     MoveWindow GetDlgItem(CBHNDL, %Checkbox), LOWRD(CBLPARAM) - 490, _      'Hor,
                           HIWRD(CBLPARAM) - 34, 115, 24, %TRUE              'Vert, W, H
     MoveWindow GetDlgItem(CBHNDL, %Combobox), LOWRD(CBLPARAM) - 365, _      'Hor,
                           HIWRD(CBLPARAM) - 33, 120, 225, %TRUE             'Vert, W, H
     MoveWindow GetDlgItem(CBHNDL, %ButtonSearch), LOWRD(CBLPARAM) - 230, _  'Hor,
                           HIWRD(CBLPARAM) - 33, 60, 24, %TRUE               'Vert, W, H
     MoveWindow GetDlgItem(CBHNDL, %ButtonQuery), LOWRD(CBLPARAM) - 155, _   'Hor,
                           HIWRD(CBLPARAM) - 33, 60, 24, %TRUE               'Vert, W, H
     MoveWindow GetDlgItem(CBHNDL, %ButtonQuit), LOWRD(CBLPARAM) - 80, _     'Hor,
                           HIWRD(CBLPARAM) - 33, 60, 24, %TRUE               'Vert, W, H
     MoveWindow GetDlgItem(CBHNDL, %Grip), LOWRD(CBLPARAM) - 15, _           'Hor,
                           HIWRD(CBLPARAM) - 15, 15, 15, %TRUE               'Vert, W, H
     SetHorizontalListboxBar
     DIALOG REDRAW hDlg
     FUNCTION = 0
     EXIT FUNCTION
 
   CASE %WM_GETMINMAXINFO
     MinMaxInfoPtr = CBLPARAM
     @MinMaxInfoPtr.ptMinTrackSize.x = 402
     @MinMaxInfoPtr.ptMinTrackSize.y = 180
 
 END SELECT
 
END FUNCTION
'______________________________________________________________________________
 
FUNCTION PBMAIN AS LONG
 LOCAL PrivilegeOk AS LONG
 'PrivilegeOk = LoadPrivilege($SE_DEBUG_NAME) 'Debug privileges
 'PrivilegeOk = LoadPrivilege($SE_LOAD_DRIVER_NAME) 'Load driver privileges
 
 DIALOG NEW %HWND_DESKTOP, "QuerySystemInformation", , , 600, 300, _
   %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN OR %WS_CAPTION OR _
   %WS_SYSMENU OR %WS_THICKFRAME OR %WS_MINIMIZEBOX OR _
   %WS_MAXIMIZEBOX, %WS_EX_WINDOWEDGE TO hDlg
 
 CONTROL ADD LISTBOX, hdlg, %Listbox , , 10, 10, 580, 280, _
   %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_VSCROLL OR %WS_HSCROLL OR _
   %LBS_NOTIFY OR %WS_TABSTOP OR %LBS_USETABSTOPS, %WS_EX_CLIENTEDGE
 
 CONTROL ADD CHECKBOX, hDlg, %Checkbox, "Only with ObjName", 270, 281, 75, 12, _
   %BS_LEFT OR %BS_VCENTER OR %WS_TABSTOP, %WS_EX_RIGHT
 CONTROL SET CHECK hDlg, %Checkbox, %TRUE
 
 CONTROL ADD COMBOBOX, hDlg, %Combobox, , 338, 281, 100, 50,%CBS_DROPDOWN OR _
   %WS_TABSTOP OR %CBS_HASSTRINGS OR %CBS_AUTOHSCROLL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT
 COMBOBOX ADD hDlg, %Combobox, "Serial"
 COMBOBOX ADD hDlg, %Combobox, "Serial0"
 COMBOBOX ADD hDlg, %Combobox, "\Device\Tcp"
 COMBOBOX ADD hDlg, %Combobox, "\Device\Udp"
 COMBOBOX ADD hDlg, %Combobox, "COM"
 COMBOBOX ADD hDlg, %Combobox, "COM1"
 COMBOBOX ADD hDlg, %Combobox, "UltraEdit"
 COMBOBOX ADD hDlg, %Combobox, "PbEdit"
 COMBOBOX ADD hDlg, %Combobox, "Registry"
 COMBOBOX ADD hDlg, %Combobox, "Type 2:"
 COMBOBOX SELECT hDlg, %Combobox, 3
 
 CONTROL ADD BUTTON, hDlg, %ButtonSearch, "&Search", 418, 280, 45, 15, _
   %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_TEXT OR %BS_PUSHBUTTON OR _
   %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR %WS_EX_LTRREADING
 CONTROL DISABLE hDlg, %ButtonSearch
 
 CONTROL ADD BUTTON, hDlg, %ButtonQuery, "&Query", 478, 280, 45, 15, _
   %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_TEXT OR %BS_PUSHBUTTON OR _
   %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR %WS_EX_LTRREADING
 
 CONTROL ADD BUTTON, hDlg, %ButtonQuit, "Quit", 538, 280, 45, 15, _
   %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_TEXT OR %BS_PUSHBUTTON OR _
   %BS_CENTER OR %BS_VCENTER, %WS_EX_LEFT OR %WS_EX_LTRREADING
 
 CONTROL ADD SCROLLBAR, hDlg, %Grip, "", 590, 290, 10, 10, %WS_CHILD OR %WS_VISIBLE OR _
   %SBS_SIZEGRIP OR %SBS_SIZEBOXBOTTOMRIGHTALIGN 'Class: ScrollBar
 
 SetClassLong hDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION)
 
 DIALOG SHOW MODAL hDlg CALL DlgProc
END FUNCTION
'______________________________________________________________________________
[This message has been edited by Pierre Bellisle (edited August 19, 2007).]