Announcement

Collapse
No announcement yet.

Process Handles? via NtDll or PsApi?

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

    #21
    Well it seems that I am back to the drawing board of sorts.

    What I think I need to do is go back to basics and verify that EVERY
    variable declared matches the final API call? Because no matter what I do,
    I can NOT get the program to totally end...(I start out with about 2,485K at start (before enum)
    and build up from there, and when done, I drop to 3,048 or so...but never totally release and
    can not kill from Task Manager, nor SysInternals, but can die out if I reboot)

    The other problem is that it is accumulative, each new copy can and will enum alllll the handles
    from the previous copy (I have to rename each new copy to compile again obviously)

    An odd side effect (which I think has inadvertently been solved since, was that
    earlier tries would crash if the app lost focus, but by checking if the PID was
    less or greater than 32767 and compensate, would get rid of the error, so I think
    somewhere along the lines must have something to do with a LoByte Vs HiByte value in a DWORD?)

    Now if I can just figure out what is holding the program in memory, then I KNOWWWWWwwwww I can get a
    working concept running. Unfortunately I can not find a way to log errors, when the error is that there is
    no error, just the idea someone hasn't replied yet (with and without threads)

    ------------------
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

    Comment


      #22
      If I start the exe and walk away (don't kill or add any processes, it
      seems to run fine for what it is worth).
      I had the same experience with your (Mr Myers') version of the code.

      I browsed Mr. Nichols' version on line, and when I saw the terminateprocess code in separate thread of execution, all the GLOBAL vars and the use of undocumented/subject-to-change-without-notice WinAPI calls, I decided that any detailed debugging would have to be a fee-for-service project, and a project in which I am not interested.

      But.. for something which may actually help ....

      Instead of enumerating processes and possibly encountering add/kill of same during the enumeration, you might look at the ToolHelp32xxxx functions - specifically CreateToolHelp32Snapshot - to grab a 'snapshot' of all the processes and do the detail queries versus that snapshot.




      [This message has been edited by Michael Mattias (edited August 22, 2007).]
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


        #23
        Like a dog with an old bone, I can NOT let go...

        Below is my code mixed with Pierre's code for what I believe is close (but just not there yet)

        Problems I am having:
        • Processes not being enumerated...(Somewhere near a value of 10,000 but PID is a dword and should be able to enumerate well beyond this range)
        • What I believe are Named-Pipes, hanging up code (even in a thread) so a memory leak remains after closure
        • Apparently Named pipes and other files have the same access flags, so I need to find another way to find out if a named pipe without asking the name (hence the catch-22) by asking I fall into the trap


        Any help with pipes will be GREATLY appreciated.

        Anyways here is my current version of the code (I think Pierre will like some of the routines I built in)

        Code:
        #COMPILE EXE                       '#Win 8.03#
        #INCLUDE "win32api.inc"            '#2005-01-27#
        #OPTION VERSION5                   'Windows 2000 or higher
        '---------------------------------------------------------------------------
        ' GLOBALS
        '---------------------------------------------------------------------------
        GLOBAL hDlg     AS DWORD           'Handle for the dialog
        GLOBAL hList    AS DWORD           'Handle for the listbox to show results
        GLOBAL sObjName AS STRING          'Object name <-- Core Point of demo to find the correct results without lockup or memory leaks
        '---------------------------------------------------------------------------
        ' APPLICATION TITLE
        '---------------------------------------------------------------------------
        $Title = "Enum Processes, Get Handles, Get Object Names"
        '---------------------------------------------------------------------------
        ' DIALOG CONSTANTS
        '---------------------------------------------------------------------------
        %Grip         = 101
        %Listbox      = 201
        %Checkbox     = 301
        %Combobox     = 401
        %ButtonSearch = 501
        %ButtonQuery  = 502
        %ButtonQuit   = 503
        '---------------------------------------------------------------------------
        ' UN-DOCUMENTED CONSTANTS FOR NTDLL
        '---------------------------------------------------------------------------
        %ObjectNameInformation       = &h01
        %SystemHandleInformation     = &h10          '<--- Change to Unsigned once program is debugged
        %STATUS_SUCCESS              = &h00000000
        %STATUS_MORE_ENTRIES         = &h00000105
        %STATUS_INFO_LENGTH_MISMATCH = &hC0000004    '<--- Change to Unsigned once program is debugged
        %STATUS_BUFFER_OVERFLOW      = &h80000005    '<--- Change to Unsigned once program is debugged
        %STATUS_SEVERITY_ERROR       = &h00000003
        '---------------------------------------------------------------------------
        ' UN-DOCUMENTED USER DEFINED TYPES (UDT's) FOR NTDLL
        '---------------------------------------------------------------------------
        TYPE SYSTEM_HANDLE_INFORMATION          'System Handle Information Class is &h10     <--- If my guess is right Object Information is &h01
             ProcessID        AS DWORD          'ID of the Process
             ObjectTypeNumber AS BYTE           'Number to indicate the type of Object
             Flags            AS BYTE           'Flags (0x00 = None, 0x01 = Protect_from_close, 0x02 = Inherit)
        '     HANDLE           AS WORD          '<--- HANDLE is a PB reserved word (but not documented in WinHelp2000) use another variable
        '     OBJECT           AS DWORD         '<--- OBJECT is a PB reserved word (WinHelp2000 says for COM (activex) use), use another variable
             SysHandle        AS WORD           '<--- To replace HANDLE above
             SysObjectAddr    AS DWORD          '<--- To replace OBJECT above
             GrantedAccess    AS DWORD          'User Permissions
        END TYPE
        
        TYPE SYSTEM_HANDLE_TABLE_ENTRY_INFO
             NumberOfHandles AS DWORD                          'Number of Handles in the system (the WHOLE SYSTEM)
        '     HANDLES(0 TO 0) AS SYSTEM_HANDLE_INFORMATION     'HANDLES is a PB reserved word, use another (see PB Help-File for SHELL commands)
             SysHandles(0 TO 0) AS SYSTEM_HANDLE_INFORMATION   'To replace HANDLES above
        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
        
        '---------------------------------------------------------------------------
        ' UN-DOCUMENTED NTDLL FUNCTION CALLS
        '---------------------------------------------------------------------------
        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.
        
        '---------------------------------------------------------------------------
        ' PSAPI FUNCTION CALLS
        '---------------------------------------------------------------------------
        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
        
        '---------------------------------------------------------------------------
        ' WRAPPER FUNCTIONS
        '---------------------------------------------------------------------------
        DECLARE FUNCTION CancelIo LIB "KERNEL32.DLL" ALIAS "CancelIo" (BYVAL hFile AS DWORD) AS LONG
        DECLARE FUNCTION pidEnum AS LONG                                                'Main function to get data
        DECLARE FUNCTION pidGetFileName(PID AS DWORD) AS STRING
        DECLARE FUNCTION pidGetObjectNameThread(hPort AS DWORD) AS LONG
        DECLARE FUNCTION pidGetObjectName(ProcessId AS DWORD, Hndl AS WORD) AS LONG
        '*** Re-Enable if needed later               <--- Starting to get indications that this may be a mute point with VISTA
        'DECLARE FUNCTION LoadPrivilege(BYVAL sPrivilege AS STRING) AS LONG
        DECLARE FUNCTION SetHorizontalListboxBar() AS LONG
        DECLARE FUNCTION ListAdd(AddToList AS STRING) AS LONG
        DECLARE CALLBACK FUNCTION DlgProc
        DECLARE FUNCTION PBMAIN AS LONG
        '---------------------------------------------------------------------------
        ' EXTRA WRAPPER FUNCTIONS (MOSTLY FOR SORTING DATA)
        '---------------------------------------------------------------------------
        DECLARE FUNCTION GetProcessID(ProcessId AS DWORD) AS STRING
        DECLARE FUNCTION GetProcessHandle(ProcessHandle AS WORD) AS STRING
        
        DECLARE FUNCTION GetProcessAccess(ProcessAccess AS DWORD) AS STRING
        DECLARE FUNCTION SortAccessGranted(GrantedAccessValue AS LONG) AS STRING
        
        DECLARE FUNCTION GetProcessObjAddress(ProcessObjAddress AS DWORD) AS STRING
        
        DECLARE FUNCTION GetProcessObjFlags(ProcessObjFlags AS BYTE) AS STRING
        DECLARE FUNCTION SortObjectFlags(ObjectFlags AS BYTE) AS STRING
        
        DECLARE FUNCTION GetProcessObjType(ProcessObjType AS BYTE) AS STRING
        DECLARE FUNCTION SortObjectTypeName(BYVAL ObjectType AS LONG) AS STRING
        
        FUNCTION pidEnum AS LONG                                                        'Main function to get data
             LOCAL pInfoTable  AS SYSTEM_HANDLE_TABLE_ENTRY_INFO POINTER                'System holds a table of each process and whats involved in that process
             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
        
             LOCAL ProcNumber         AS STRING
             LOCAL ProcId             AS STRING
             LOCAL ProcHandle         AS STRING
             LOCAL ProcAccess         AS STRING
             LOCAL ProcObjAddress     AS STRING
             LOCAL ProcObjFlags       AS STRING
             LOCAL ProcObjTypeName    AS STRING
             LOCAL ProcObjAttrib      AS STRING
             LOCAL ProcObjName        AS STRING
        
             LOCAL ShowPort AS LONG
        
             ByteNeeded = SIZEOF(SYSTEM_HANDLE_TABLE_ENTRY_INFO)                        'Minimum buffer size for a valid ByteNeeded
             FOR Looper = 1 TO 2                                                        'Call once to get the bytes needed, call again to get actual info
                  LenBuffer = ByteNeeded
                  sBuffer = NUL$(ByteNeeded)
                  pBuffer = STRPTR(sBuffer)
                  Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)
             NEXT
        '*** Get needed info
             pInfoTable = pBuffer                                                       'Fill my table with the info in the pointer to the real table
             InfoCount  = @pInfoTable.NumberOfHandles                                   'Get the Number of handles in the system
        '*** Display purposes
             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 <--- Not sure what the AT part means yet (unless a pointer offset?)
             FOR Looper = 1 TO InfoCount                                                'For each Handle found in the system
                  sFileName = pidGetFileName(Info(Looper).ProcessID)                    'Get the file name of what owns the handle
        '          IF Info(Looper).ProcessID = GetModuleHandle(BYVAL %NULL) THEN ITERATE 'Dont enum yourself
                  IF INSTR(UCASE$(sFileName), UCASE$("Process")) THEN ITERATE        '<--- Do NOT iterate any copies of this program (exponentially grows each copy)
        
        '          IF INSTR(UCASE$(sFileName), UCASE$("SYSTEM")) THEN ITERATE            '<--- Nothing returns from System anyways when getting object name
        '          IF INSTR(UCASE$(sFileName), UCASE$("WINLOGON")) THEN ITERATE          '<--- Nothing returns from WinLogon anyways when getting object name
        '          IF INSTR(UCASE$(sFileName), UCASE$("SERVICES")) THEN ITERATE          '<--- Nothing returns from Services anyways when getting object name
        '          IF INSTR(UCASE$(sFileName), UCASE$("LSASS")) THEN ITERATE             '<--- Nothing returns from Lsass anyways when getting object name
        '          IF INSTR(UCASE$(sFileName), UCASE$("SVCHOST")) THEN ITERATE           '<--- Nothing returns from SvcHost anyways when getting object name
        ''
        '          IF INSTR(UCASE$(sFileName), UCASE$("TASKMGR")) THEN ITERATE           '<--- Why get handles from Windows Task Manager?
        
        '          IF INSTR(UCASE$(sFileName), UCASE$("Cosmos")) THEN
        '               'Do Nothing
        '          else
        '               ITERATE        '<--- Do NOT iterate any copies of this program (exponentially grows each copy)
        '          end if
        '*** My Version
        '*** Process Info
                  ProcNumber = "Number: "    & FORMAT$(Looper)
        'IF Info(Looper).ProcessID = 109996 THEN MSGBOX STR$(Info(Looper).ProcessID)
                  ProcId = GetProcessId(Info(Looper).ProcessID)
                  ProcHandle = GetProcessHandle(Info(Looper).SysHandle)
                  ProcAccess = GetProcessAccess(Info(Looper).GrantedAccess)
        '*** Object Info
                  ProcObjAddress = GetProcessObjAddress(Info(Looper).SysObjectAddr)
                  ProcObjFlags = GetProcessObjFlags(Info(Looper).Flags)                                        '0x00 = None, 0x01 = Protect_from_close, 0x02 = Inherit
                  ProcObjTypeName = GetProcessObjType(Info(Looper).ObjectTypeNumber)
        '*** Originally I thought one of the below commented cases was causing the memory leak
        '          IF INSTR(UCASE$(ProcObjTypeName), UCASE$("Semaphore")) THEN ITERATE
        '          IF INSTR(UCASE$(ProcObjTypeName), UCASE$("Thread")) THEN ITERATE
        '          IF INSTR(UCASE$(ProcObjTypeName), UCASE$("IoCompletion")) THEN ITERATE
        '          IF INSTR(UCASE$(ProcObjTypeName), UCASE$("Timer")) THEN ITERATE
        '          IF INSTR(UCASE$(ProcObjTypeName), UCASE$("Event")) THEN ITERATE
        '
        '
        '*** In My case I am only after what Windows reports as "Files" but may really be a Serial Port or a USB port
                  IF INSTR(UCASE$(ProcObjTypeName), UCASE$("File")) THEN
                       IF INSTR(UCASE$(ProcAccess), UCASE$("%SYNCHRONIZE")) THEN
                            IF INSTR(UCASE$(ProcAccess), UCASE$("%PROCESS_DUP_HANDLE")) THEN
                                 'Do Nothing
                            ELSE
                                 ITERATE
                            END IF
                       ELSEIF INSTR(UCASE$(ProcAccess), UCASE$("%PROCESS_ALL_ACCESS")) THEN
        '                    IF INSTR(UCASE$(ProcAccess), UCASE$("%PROCESS_DUP_HANDLE")) THEN
                            IF INSTR(UCASE$(ProcObjFlags), UCASE$("(Inherit)")) THEN
                                 'Do Nothing
                            ELSEIF INSTR(UCASE$(ProcAccess), UCASE$("%PROCESS_DUP_HANDLE")) THEN
                                 'Do Nothing
        '*** No memory leak if commented out, so currently I believe that the following holds true
        '*** 1.) Named pipes that lock-up just asking what the object name is due to one (or more) of the access flags except %PROCESS_DUP_HANDLE
        '*** 2.) Files that are Inherited do not seem to lock-up, so for the time being I have to assume named-pipes are not inherited
        '*** 3.) Odd how my own program can be no flags on one computer and inherited on another <--- Need to research this
        '*** 4.) Whatever named pipe(s) that are locking have the same access flags as files that do not lock <--- Need to find a workaround for this
        '                    ELSEIF INSTR(UCASE$(ProcAccess), UCASE$("%PROCESS_VM_READ")) THEN
                                 'Do Nothing
                            ELSE
                                 ITERATE        'If a possible lock-up file (like named-pipes) then skip gathering info on it
                            END IF
                       ELSE
                            ITERATE             'If a combination of access flags that I have not run into yet, then skip asking for info
                       END IF
                  ELSE
                       ITERATE                  'If not a "File" (only after files at the moment), then skip asking for info
                  END IF
        '*** Get the object name if passed the above checks if possibly a named-pipe that will lock just by asking if a named pipe
                  pidGetObjectName(Info(Looper).ProcessID, Info(Looper).SysHandle)      'Get the object name of each handle contained in each process'*** Display Results
        '*** Since I am after Serial Ports, USB Ports, and USB-RS232 Adapters I added the below filters
                  SELECT CASE INSTR(UCASE$(sObjName), UCASE$("SERIAL"))
                       CASE 0
                            ShowPort = %False
                            SELECT CASE INSTR(UCASE$(sObjName), UCASE$("edgeser"))
                                 CASE 0
                                      ShowPort = %False
                                      SELECT CASE INSTR(UCASE$(sObjName), UCASE$("USBPDO"))
                                           CASE 0
                                                ShowPort = %False
                                           CASE ELSE
                                                ShowPort = %True
                                      END SELECT
                                 CASE ELSE
                                      ShowPort = %True
                            END SELECT
                       CASE ELSE
                            ShowPort = %True
                  END SELECT
        '*** If it matches one of the above filters, then show the information
                  SELECT CASE ShowPort
                       CASE %False
                       CASE %True
        '*** Display Process Info
                            ListAdd   ProcNumber     & $TAB & _
                                      ProcId         & $TAB & _
                                      ProcHandle     & $TAB & _
                                      UCASE$(MID$(sFileName , INSTR(-1, sFileName, ANY ":/\") + 1))    'Process Name without path
        '*** Display Handle Object Info
                            ListAdd   $TAB & ProcAccess
                            ListAdd   $TAB & ProcObjAddress & $TAB & _
                                      ProcObjFlags   & $TAB & _
                                      ProcObjTypeName
                            IF LEN(sFileName) THEN ListAdd "   " & sFileName
                            IF LEN(sObjName) THEN ListAdd "   " & sObjName
                            ListAdd STRING$(255,"-")
                            ListAdd ""
                  END SELECT
             NEXT Looper
             DIALOG SET TEXT hDlg, $Title & " -" & STR$(InfoCount) & " handles found"
        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 = SIZEOF(ByteNeeded)              'SIZEOF(ByteNeeded) = 4 = SIZEOF(DWORD)
                  FOR Looper = 1 TO 2                          'Call once to get bytes needed, call again to get actual info
                       LenBuffer = ByteNeeded
                       sBuffer = NUL$(ByteNeeded)
                       pBuffer = STRPTR(sBuffer)
                       Retval = EnumProcessModules(hProcess, pBuffer, LenBuffer, ByteNeeded)      'Get number of modules contained in process
                  NEXT Looper
                  IF Retval THEN
                       HandleCount = LenBuffer \ SIZEOF(ByteNeeded)                'LenBuffer \ SIZEOF(ByteNeeded) = 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)
        '     CancelIo hPort
             FOR Looper = 1 TO 2                          'Call once to get bytes needed, call again to get actual info
                  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            '<--- Learn what this does, and do I need it? (1 char = 2 bytes instead of 1 byte)
                       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
        
             DIM lResult AS LONG
             DIM ErrorBuff AS ASCIIZ * %MAX_PATH
        
             sObjName = ""
             IF ProcessId THEN
                  hProc = OpenProcess(%PROCESS_DUP_HANDLE, 0, ProcessId)
        '          hProc = OpenProcess(%PROCESS_CREATE_THREAD Or %PROCESS_VM_OPERATION Or %PROCESS_VM_WRITE Or %PROCESS_VM_READ, 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
        '                    SetNamedPipeHandleState(Byval Hndl, %PIPE_NOWAIT, byval %NULL, byval %NULL)
        '               IF DuplicateHandle(hProc, BYVAL Hndl, -1, hPort, 0, %PROCESS_QUERY_INFORMATION XOR %SYNCHRONIZE, 0) THEN
                            hThread = CreateThread(BYVAL %NULL, 0, CODEPTR(pidGetObjectNameThread), BYREF hPort, _
                                      %THREAD_TERMINATE OR %THREAD_QUERY_INFORMATION, BYVAL VARPTR(idThread))
        '*** Left here just as a thought I had, but did not work, but I may not have understood well enough to do correctly ***
        'dim Security as SECURITY_ATTRIBUTES
        'dim StackSize as dword
        'StackSize = sizeof(hPort)
        '                    hThread = CreateRemoteThread(hProc, Security, StackSize, CODEPTR(pidGetObjectNameThread), BYREF hPort, _
        '                               %THREAD_TERMINATE OR %THREAD_QUERY_INFORMATION, BYVAL VARPTR(idThread))
        '**********************************************************************************************************************
        '                    Retval = WaitForSingleObjectEx(hThread, 30, %TRUE) 'Wait 30 miliseconds maximum
                            Retval = WaitForSingleObjectEx(hThread, 30, %TRUE)     '<--- Adjust TimeOut Time due to thread may not be completed within the timeout time
        '*** Failure Checks
                            SELECT CASE RetVal
                                 CASE %WAIT_FAILED, %WAIT_ABANDONED
                                      lResult = GetLastError()
                                      FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL
        MSGBOX ErrorBuff
                                 CASE %WAIT_OBJECT_0                          'Success I think?
                                 CASE %WAIT_TIMEOUT                           'Failure            <--- Check into the other timeout values
        '                              Retval = TerminateThread(hThread, 13)        '<--- Native API shows that TerminateProcess and TerminateThread in turn call NtTerminateProcess, NtTerminateThread ??? (Exitcode 13 = Just a code chosen?
                                      CloseHandle hThread                          'Close the thread
                                      sObjName = "ObjName: Error"                  'Return an error for the Object name
                                 CASE ELSE
                                      lResult = GetLastError()
                                      FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, lResult, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL
        MSGBOX ErrorBuff
                            END SELECT
                            Retval = TerminateThread(hThread, 0)              'Terminate the thread now that I am done with it
                            CloseHandle hPort                                 'Close the handle
                       ELSE
        '                    FUNCTION = "No DuplicateHandle"
                       END IF
                       CloseHandle hProc                                      'Close the process
                  ELSE
        '               FUNCTION = "Bad OpenProcess"
                  END IF
             END IF
        END FUNCTION
        '______________________________________________________________________________
        
        '*** Re-Enable if needed later
        '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
        ''______________________________________________________________________________
        
        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             'Start the process to enum all processes and handles
                                      SetHorizontalListboxBar  'Set the scrollbar when done
                                      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
                            CASE %ButtonQuit, %IDCANCEL
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN DIALOG END CBHNDL
                            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
             '     case %WM_CLOSE
             '          TerminateProcess GetModuleHandle(byval %NULL), 0       'Force my own process closed
             END SELECT
        END FUNCTION
        '______________________________________________________________________________
        
        FUNCTION PBMAIN AS LONG
        LOCAL PrivilegeOk AS LONG
        '*** Figure out what priviledges there are
        '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
        '______________________________________________________________________________
        FUNCTION GetProcessID(ProcessId AS DWORD) AS STRING
             FUNCTION = " - Pid: "    & FORMAT$(ProcessId)
        '     FUNCTION = " - Pid: "    & str$(ProcessId)
        END FUNCTION
        '______________________________________________________________________________
        
        FUNCTION GetProcessHandle(ProcessHandle AS WORD) AS STRING
             FUNCTION = " - Handle: " & HEX$(ProcessHandle, 16)
        END FUNCTION
        '______________________________________________________________________________
        
        FUNCTION GetProcessAccess(ProcessAccess AS DWORD) AS STRING
             FUNCTION = " - Access: " &  SortAccessGranted(ProcessAccess)
        END FUNCTION
        
        '______________________________________________________________________________
        FUNCTION GetProcessObjAddress(ProcessObjAddress AS DWORD) AS STRING
             FUNCTION = " - Object Address: " & HEX$(ProcessObjAddress, 8)
        END FUNCTION
        
        '______________________________________________________________________________
        FUNCTION GetProcessObjFlags(ProcessObjFlags AS BYTE) AS STRING
             FUNCTION = " - Flags "   & SortObjectFlags(ProcessObjFlags)
        END FUNCTION
        
        '______________________________________________________________________________
        FUNCTION GetProcessObjType(ProcessObjType AS BYTE) AS STRING
             FUNCTION = " - Type: "    &  SortObjectTypeName(ProcessObjType)
        END FUNCTION
        
        '______________________________________________________________________________
        
        FUNCTION SortAccessGranted(GrantedAccessValue AS DWORD) AS STRING
             LOCAL ProcessAccessVal AS DWORD
             LOCAL ProcessAccess AS STRING
             LOCAL TempProcessAccess AS STRING
             LOCAL i AS LONG
        '*** Below tables are a sample of the permissions in each Info(Looper).GrantedAccess
        '--------------------------------------------------
        '    Lo-Byte Lo-Word
        '--------------------------------------------------
        '*** Pos       8    7    6    5    4    3    2    1
        '*** Bit       7    6    5    4    3    2    1    0
        '*** Value     128  64   32   16   8    4    2    1
        '*** ----------------------------------------------
        '              0    0    0    0    0    0    0    1    = &H01 = 1 = %PROCESS_TERMINATE
        '              0    0    0    0    0    0    1    0    = &H02 = 2 = %PROCESS_CREATE_THREAD
        '              0    0    0    0    0    1    0    0    = &H04 = 4 = %PROCESS_SET_SESSIONID
        '              0    0    0    0    1    0    0    0    = &H08 = 8 = %PROCESS_VM_OPERATION
        '              0    0    0    1    0    0    0    0    = &H010 = 16 = %PROCESS_VM_READ
        '              0    0    1    0    0    0    0    0    = &H020 = 32 = %PROCESS_VM_WRITE
        '              0    1    0    0    0    0    0    0    = &H040 = 64 = %PROCESS_DUP_HANDLE
        '              1    0    0    0    0    0    0    0    = &H080 = 128 = %PROCESS_CREATE_PROCESS
        
        '              0    0    0    0    0    0    1    1    = &H03 = 3 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD
        '              0    0    0    0    0    1    1    1    = &H07 = 7 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD OR %PROCESS_SET_SESSIONID
        '              0    0    0    0    1    1    1    1    = &H0F = 15 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD OR %PROCESS_SET_SESSIONID OR %PROCESS_VM_OPERATION
        '              0    0    0    1    1    1    1    1    = &H1F = 31 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD OR %PROCESS_SET_SESSIONID OR %PROCESS_VM_OPERATION OR %PROCESS_VM_READ
        
        '              0    0    1    1    1    1    1    1    = &H3F = 63 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD OR %PROCESS_SET_SESSIONID OR %PROCESS_VM_OPERATION OR %PROCESS_VM_READ
        '                                                               OR %PROCESS_VM_WRITE
        '              0    1    1    1    1    1    1    1    = &H7F = 127 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD OR %PROCESS_SET_SESSIONID OR %PROCESS_VM_OPERATION OR %PROCESS_VM_READ
        '                                                               OR %PROCESS_VM_WRITE OR %PROCESS_DUP_HANDLE
        '              1    1    1    1    1    1    1    1    = &HFF = 255 = %PROCESS_TERMINATE OR %PROCESS_CREATE_THREAD OR %PROCESS_SET_SESSIONID OR %PROCESS_VM_OPERATION OR %PROCESS_VM_READ
        '                                                               OR %PROCESS_VM_WRITE OR %PROCESS_DUP_HANDLE OR %PROCESS_CREATE_PROCESS
        
        '----------------------------------------------------------------------------------------------------
        '    Hi-Byte Lo-Word
        '----------------------------------------------------------------------------------------------------
        '*** Pos       16        15        14        13        12        11        10        9
        '*** Bit       15        14        13        12        11        10        9         8
        '*** Value     32768     16384     8192      4096      2048      1024      512       256
        '*** --------------------------------------------------------------------------------------------
        '              0         0         0         0         0         0         0         1    = &H0100 = 256 = %PROCESS_SET_QUOTA
        '              0         0         0         0         0         0         1         0    = &H0200 = 512 = %PROCESS_SET_INFORMATION
        '*** MANY MORE COMBINATIONS TO FIGURE OUT
        '
        '
        '*** Default the variables used
             ProcessAccessVal = GrantedAccessValue
             ProcessAccess = ""
             TempProcessAccess = ""
        '*** Determine Granted Access
        '     ProcessAccess = BIN$(Info(Looper).GrantedAccess, 8)   '<--Not 8 but 32 bits in DWORD
             ProcessAccess = BIN$(ProcessAccessVal, 32)             '<--Not 8 but 32 bits in DWORD
             FOR i = 1 TO LEN(ProcessAccess)
                  SELECT CASE VAL((MID$(ProcessAccess, i, 1)))       '
                       CASE 0    'Bit Not Set
                       CASE 1    'Bit Set
                            SELECT CASE i
        '*** Hi Byte Hi Word
                                 CASE 1         'Bit 31
                                 CASE 2         'Bit 30
                                 CASE 3         'Bit 29
                                 CASE 4         'Bit 28
                                 CASE 5         'Bit 27
                                 CASE 6         'Bit 26
                                 CASE 7         'Bit 25
                                 CASE 8         'Bit 24
        '*** Lo Byte Hi Word
                                 CASE 9         'Bit 23
                                 CASE 10        'Bit 22
                                 CASE 11        'Bit 21
                                 CASE 12        'Bit 20 = &H00100000 = 1048576
                                      TempProcessAccess = TempProcessAccess + " %PROCESS_ALL_ACCESS, " '%PROCESS_ALL_ACCESS = %STANDARD_RIGHTS_REQUIRED OR %SYNCHRONIZE OR &H0FFF (4095) = 2035711 = &H01F0FFF
                                 CASE 13        'Bit 19 = &H000F0000 = 983040
                                      TempProcessAccess = TempProcessAccess + " %SYNCHRONIZE, " '%SYNCHRONIZE
                                 CASE 14        'Bit 18
                                 CASE 15        'Bit 17 = UNKNOWN
                                 CASE 16        'Bit 16 = UNKNOWN
        '*** Hi Byte Lo Word
                                 CASE 17        'Bit 15 = UNKNOWN
                                 CASE 18        'Bit 14 = UNKNOWN
                                 CASE 19        'Bit 13 = UNKNOWN
                                 CASE 20        'Bit 12 = UNKNOWN
                                 CASE 21        'Bit 11 = UNKNOWN
        '*** Do NOT look for whatever &H0FFF is because it could be a combo of below
                                 CASE 22        'Bit 10 = %PROCESS_QUERY_INFORMATION = &H0400 = 1024
                                      TempProcessAccess = TempProcessAccess + " %PROCESS_QUERY_INFORMATION, "
                                 CASE 23        'Bit 9 = %PROCESS_SET_INFORMATION = &H0200 = 512
                                      TempProcessAccess = TempProcessAccess + " %PROCESS_SET_INFORMATION, "
                                 CASE 24        'Bit 8 = %PROCESS_SET_QUOTA = &H0100 = 256
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_SET_QUOTA, "
        '*** Lo Byte Lo Word
                                 CASE 25        'Bit 7 = %PROCESS_CREATE_PROCESS = &H0080 = 128
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_CREATE_PROCESS, "
                                 CASE 26        'Bit 6 = %PROCESS_DUP_HANDLE = &H0040 = 64
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_DUP_HANDLE, "
                                 CASE 27        'Bit 5 = %PROCESS_VM_WRITE = &H0020 = 32
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_VM_WRITE, "
                                 CASE 28        'Bit 4 = %PROCESS_VM_READ = &H0010 = 16
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_VM_READ, "
                                 CASE 29        'Bit 3 = %PROCESS_VM_OPERATION = &H0008 = 8
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_VM_OPERATION, "
                                 CASE 30        'Bit 2 = %PROCESS_SET_SESSIONID = &H0004 = 4
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_SET_SESSIONID, "
                                 CASE 31        'Bit 1 = %PROCESS_CREATE_THREAD = &H0002 = 2
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_CREATE_THREAD, "
                                 CASE 32        'Bit 0 = %PROCESS_TERMINATE = &H0001 = 1
                                           TempProcessAccess = TempProcessAccess + " %PROCESS_TERMINATE, "
                            END SELECT
                  END SELECT
             NEXT i
             FUNCTION = "0x" + HEX$(ProcessAccessVal, 32) + " =" + TempProcessAccess    '<--- Cant remember what the signed symbol for hex is but 0x is unsigned
        END FUNCTION
        '______________________________________________________________________________
        
        FUNCTION SortObjectFlags(ObjectFlags AS BYTE) AS STRING
             SELECT CASE HEX$(ObjectFlags, 1)
                  CASE "0"         'None
                       FUNCTION = HEX$(ObjectFlags, 1) & " (None)"
                  CASE "1"         'Protect_from_close
                       FUNCTION = HEX$(ObjectFlags, 1) & " (Protect_from_close)"
                  CASE "2"         'Inherit
                       FUNCTION = HEX$(ObjectFlags, 1) & " (Inherit)"
             END SELECT
        END FUNCTION
        '______________________________________________________________________________
        FUNCTION SortObjectTypeName(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
        '______________________________________________________________________________
        
        '------------------------------------------------------------------------------------------------------------------
        ' DISPLAY FUNCTIONS SHOWN BELOW
        '------------------------------------------------------------------------------------------------------------------
        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
             STATIC LastItem AS LONG
             LastItem = SendMessage(hList, %LB_GETCOUNT,  0, 0) - 1
             LastItem = SendMessage(hList, %LB_ADDSTRING, LastItem, BYVAL STRPTR(AddToList))
             SELECT CASE LastItem MOD 4
                  CASE 0
                       SendMessage hList, %LB_SETCURSEL, LastItem, 0
                       DIALOG DOEVENTS
                  CASE ELSE
             END SELECT
        END FUNCTION
        '______________________________________________________________________________
        Engineer's Motto: If it aint broke take it apart and fix it

        "If at 1st you don't succeed... call it version 1.0"

        "Half of Programming is coding"....."The other 90% is DEBUGGING"

        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

        Comment


          #24
          Cliff,

          I don't want to disappoint you, but I'm afraid you don't have chance to enumerate all objects without jumping to ring 0. That mean you need a driver to do this job.

          Check this Delphi example for method how to jump over sync. locked pipes.
          Last edited by Aleksandr Dobrev; 5 Sep 2007, 11:36 AM.
          -=Alex=-

          Comment


            #25
            <UPDATED 7 Sept 2007>

            Thanx Aleksandr,

            I figured out a bit tricky work-around shortly before your post, and got things down to no memory leaks (meaning I can completely close my program)

            Your post helped confirm some ideas in my head (still threating those lil voices with the q-tip for getting me in this deep )

            After much debate, I have now posted the code as I have it in the source-code forum (under the Enum Handles with NtQuerySystemInformation (improved) for others to see and use.

            Some minor things still bug me (like Win2K not finding "\Device\Serial0" even though I know it is open) and I need to go back and clean up the code (change declares to loadlibrary and the like) and find my notes on which OS and servicepack is needed to use ntdll.dll (I think its all NT side of windows but not sure)
            Last edited by Cliff Nichols; 7 Sep 2007, 12:53 PM.
            Engineer's Motto: If it aint broke take it apart and fix it

            "If at 1st you don't succeed... call it version 1.0"

            "Half of Programming is coding"....."The other 90% is DEBUGGING"

            "Document my code????" .... "WHYYY??? do you think they call it CODE? "

            Comment


              #26
              This thread is old but still of value.
              During my testing of the various code from this thread and the source code section it points to, many of the handles do not close in the thread that includes the DuplicateHandle function.
              I am not a threads expert, but I have used another approach to closing threads by using global variables as flags. I will have to post that code later.

              This code show in this thread up to this point will also possibly hang. I am simply a newbie in this area.
              I used Nirsoft's openedfilesview.exe program to compare their results from what result I was seeing from this program.
              Basically, from what I am seeing, is that if the granted access is of certain values on object types. This program will hang on the call to the DuplicateHandle function.
              I am not a computer guy that knows much if any about granted access and security to files and certainly not keen on HEX.
              In the above thread, you can see coding and some definitions on the granted access byte.
              See the function "SortAccessGranted" in the above posting.

              I believe if this program is run from a service(with no display), then there is the high possibility that this program will not hang on any or all of the granted access codes.

              From viewing the Nirsoft sotware, the files listed never go above 0x001??????.
              See for yourself with the Nirsoft openedfilesview.exe program from their website, and sort the "Granted Access" column.
              I have not tried any of the Sysinternal's programs.
              Please see this website on this as well.
              In the DuplicateHandle MSDN documentation there is not a lot of information about the Access Mask that can be passed to DuplicateHandle. Wh...


              I had this program hang on mbam.exe(Malwarebytes) until the mbam.exe process was killed.

              During testing, it is good to display every processid, filename, and granted access before making the call the DuplicateHandle function to see what program and object type with granted access code is causing the hang.
              As from my memory, I do not think the granted access setting does not have any bearing on the handles not closing.

              I will have to post more on this later. I just wanted to through out there some observations because much of this I do not understand. All I know to do is observe and compare(on the granted access) and try another approach on managing threads(be it unorthodox or not).
              Last edited by Paul Purvis; 29 Oct 2014, 01:17 AM.
              p purvis

              Comment


                #27
                see also...



                And a little bit offtopic but icing on the related cake http://www.powerbasic.com/support/pb...d.php?t=055164
                Last edited by Wayne Diamond; 29 Oct 2014, 01:41 AM.
                -

                Comment


                  #28
                  >This thread is old but still of value

                  The value is diminished by advances in operating systems. Information about a process is much more readily available starting with Windows/XP and later; you don't have to use some of the tools you had to use with 9x/ME/2000.

                  It's diminished even more by advances in the PowerBASIC compiler, which now supports simplified access to portions of the Windows' API which offer only a COM interface.

                  MCM
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment

                  Working...
                  X
                  😀
                  🥰
                  🤢
                  😎
                  😡
                  👍
                  👎