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.
[This message has been edited by Pierre Bellisle (edited August 19, 2007).]
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 '______________________________________________________________________________