Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

NtQuerySystemInformation with %SystemHandleInformation

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • NtQuerySystemInformation with %SystemHandleInformation

    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).]
Working...
X