Announcement

Collapse
No announcement yet.

Process Handles? via NtDll or PsApi?

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

  • Michael Mattias
    replied
    >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

    Leave a comment:


  • Wayne Diamond
    replied
    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.

    Leave a comment:


  • Paul Purvis
    replied
    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.

    Leave a comment:


  • Cliff Nichols
    replied
    <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.

    Leave a comment:


  • Aleksandr Dobrev
    replied
    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.

    Leave a comment:


  • Cliff Nichols
    replied
    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
    '______________________________________________________________________________

    Leave a comment:


  • Michael Mattias
    replied
    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).]

    Leave a comment:


  • Cliff Nichols
    replied
    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)

    ------------------

    Leave a comment:


  • Cliff Nichols
    replied
    Thank you Ken and Pierre,

    Ken's code runs into the same trap I found a while back of if the
    app loses focus, then it will crash when it regains focus, but it
    does resolve the issue of being stuck in memory when I close the program
    (I think anyways, because I skipped the problem points just for testing purposes)

    Pierre's code optimizes and fixes some key points of my code that I found troubling

    I will try to blend the best points for a working example, and see how it goes.

    Right now time is no problem, proof-of-concept is the sole point for the time being.
    Hope to have something soon.
    Thanx again guys.

    ------------------

    Leave a comment:


  • Ken Myers
    replied
    This code should probably be re-written to not take so long to run
    as I suspect it could be very possible that the processes being
    searched are not valid by the time they are checked. Could be all
    kinds of other problems as well which I don't really have the time
    today to look into. Maybe someone else can help Cliff on this one.
    Basically, I just saw that his ProcessEnum was hanging his GUI and
    slapped that in a thread so that his GUI wouldn't be frozen. 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).

    -Ken

    ------------------

    Leave a comment:


  • Ken Myers
    replied
    Pierre,

    The GPF has nothing to do with what I posted. It has to do with
    something in the ProcessEnum function that Cliff still needs to
    work on. I was just showing him how to exit out cleanly before it
    is done.

    -Ken

    ------------------

    Leave a comment:


  • Pierre Bellisle
    replied
    cliff,

       i updated the code at http://www.powerbasic.com/support/pb...ad.php?t=25170
    to add a thread with waitforsingleobject and terminatethread
    in concern of ntqueryobject.

    this version have no problem with explorer.exe

    i did also created a objecttype function to return
    names under nt4, 2000 and xp.

    pierre


    added later: ken, the code you posted gpf after a while on my pc




    [this message has been edited by pierre bellisle (edited august 19, 2007).]

    Leave a comment:


  • Ken Myers
    replied
    I think there is quite a bit of room for improvement/cleaning up
    of the code, but I know I have several programs that could use some
    tidying up as well. The main problem you are having is that you
    are tying up the main thread of your dialog and it is causing the
    application to be non-responsive (thus the hard kill, etc.). I
    merged your includes together and made the code even a bit messier
    adding some things that I currently don't think are necessary, but
    the app behaves a little better and you will get the point and can
    clean it up from there.

    Code:
    #Compile Exe             '#Win 8.03#
    #Option Version5         'Windows 2K and up only
    
    '----------------------------------------------------------------
    ' DIALOG GLOBALS
    '----------------------------------------------------------------
    Global hDlg    As Dword  'Handle for Dialog
    Global hList   As Dword  'Handle for Listbox
    Global killMe As Long
    Global idThread As Long
    Global stopMe As Long
    Global stopThread As Long
    '----------------------------------------------------------------
    
    '----------------------------------------------------------------
    ' DIALOG FUNCTIONS DECLARES
    '----------------------------------------------------------------
    Declare CallBack Function DlgProc() As Long
    Declare Function PBMain As Long
    Declare Function ListAdd(AddToList As String) As Long
    Declare Function SetHorizontalListboxBar() As Long
    Declare Function KillThread (ByVal x As Long) As Long 
    Declare Sub startKiller()
    Declare Function EnumThread (ByVal x As Long) As Long 
    Declare Sub startSearching()
    Declare Sub stopSearching()
    '----------------------------------------------------------------
    ' INCLUDES
    '----------------------------------------------------------------
    #Include "WIN32API.INC"  '#2005-01-27#
    
    '----------------------------------------------------------------
    ' Supporting Includes Here
    '----------------------------------------------------------------
    
    '----------------------------------------------------------------
    ' SYSTEM HANDLE INFORMATION CONSTANTS
    '----------------------------------------------------------------
    %SystemHandleInformation     = &H10
    %ObjectNameInformation       = &H1
    
    %STATUS_SUCCESS              = &H0
    %STATUS_MORE_ENTRIES         = &H105
    %STATUS_INFO_LENGTH_MISMATCH = &HC0000004
    %STATUS_BUFFER_OVERFLOW      = &H80000005
    %STATUS_SEVERITY_ERROR       = &H00000003
    
    '----------------------------------------------------------------
    ' SYSTEM HANDLE INFORMATION USER DEFINED TYPES
    '----------------------------------------------------------------
    Type SYSTEM_HANDLE_INFORMATION                         'Information Class is &h10    (I do not know why)
         ProcessID           As Dword                      'Process Id
         ObjectTypeNumber    As Byte                       'Object type number
         Flags               As Byte                       'Flags    (I do not know what the possible values are)
         SysHandle           As Word                       'Original was HANDLE, but that is a keyword (undocumented why?)
         SysObject           As Dword                      'Original was OBJECT, but that is a keyword for COM interaction in PB
         GrantedAccess       As Dword                      'Access granted (I do not know what the possible values are)
    End Type
    
    Type SYSTEM_OBJECT_INFORMATION                         'Added to patch into SYSTEM_HANDLE_INFORMATION
         sPidPath            As Asciiz * %MAX_PATH         'Object path
         sObjectName         As Asciiz * %MAX_PATH         'Object name
    End Type
    
    Type SYSTEM_HANDLE_TABLE_ENTRY_INFO                    'Internal lookup table to system information
         NumberOfHandles     As Dword                      'Number of handles in the system
         Handles(0 To 0)     As SYSTEM_HANDLE_INFORMATION  'Array of System Handle Information, (dimensions?)
    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
    
    '----------------------------------------------------------------
    ' SYSTEM PRIVILEGE GLOBALS
    '----------------------------------------------------------------
    Global Privilege As Long
    $SE_DEBUG_NAME = "SeDebugPrivilege"
    
    '----------------------------------------------------------------
    ' SYSTEM PRIVILEGE CONSTANTS
    '----------------------------------------------------------------
    %TOKEN_ADJUST_PRIVILEGES = &H20
    %TOKEN_QUERY = &H8
    %SE_PRIVILEGE_ENABLED = &H2
    %PROCESS_VM_READ = &H10
    %PROCESS_DUP_HANDLE = &H40
    %PROCESS_QUERY_INFORMATION = &H400
    %STANDARD_RIGHTS_ALL = &H1F0000
    %GENERIC_ALL = &H10000000
    
    '----------------------------------------------------------------
    ' NTDLL API FUNCTIONS
    '----------------------------------------------------------------
    '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
    
    '----------------------------------------------------------------
    ' NTDLL API FUNCTIONS CALLED VIA LOADLIBRARY
    '----------------------------------------------------------------
    Declare Function PbQuerySystemInformation Alias "PbQuerySystemInformation"( _
                        ByVal SystemInformationClass  As Dword, _
                        ByVal SystemInformation       As Dword, _
                        ByVal SystemInformationLength As Dword, _
                        ByRef ReturnLength            As Dword) As Long
    
    Declare Function PbQueryObject Alias "PbQueryObject"( _
                        ByVal hndl                    As Dword, _
                        ByVal ObjectInformationClass  As Dword, _
                        ByVal ObjectInformation       As Dword, _
                        ByVal ObjectInformationLength As Dword, _
                        ByRef ReturnLength            As Dword) As Long
    
    '----------------------------------------------------------------
    ' WRAPPER GLOBALS
    '----------------------------------------------------------------
    'GLOBAL ObjNameRet             AS DWORD                 'Object Name returned from NtQueryObject
    Global NtDllHandle            As Dword                 'NtDll Handle to process
    Global PbQuerySysInfoHandle   As Dword                 'Pb Handle to NtDll - NtQuerySysInfoHandle via loadlibrary
    Global PbQueryObjName         As Dword                 'Pb Handle to NtDll - NtQueryObjName via loadlibrary
    
    Global Info()                 As SYSTEM_HANDLE_INFORMATION       'Array of System Handles Info
    Global ObjectInfo()           As SYSTEM_OBJECT_INFORMATION       'Array of System Objects Info
    Global ObjNameRet             As Dword                 'Return of threaded get object
    
    Global hProc      As Dword
    Global hThread As Dword
    
    Global sBuffer    As String
    Global puString   As UNICODE_STRING Pointer
    Global pBuffer    As Dword Ptr
    Global LenBuffer  As Dword
    Global hPort      As Dword
    Global ByteNeeded As Dword
    Global sObjName   As String
    '----------------------------------------------------------------
    ' WRAPPER FUNCTIONS
    '----------------------------------------------------------------
    Declare Function ProcessEnum As Long
    Declare Function FindHandleInformation(ProcessId As Dword, InfoCount As Dword, ProcSysHandleInfo As SYSTEM_HANDLE_INFORMATION) As Long
    Declare Function ThreadGetObjectName(ByVal x As Long) As Long
    Declare Function GetObjectName(ProcessId As Dword, Hndl As Word) As String
    Declare Function GetPidPath(PID As Dword) As String
    
    '------------------------------------------------------------------------------------------------------------------
    ' THE BELOW WILL BE MOVED TO PSAPI.H BUT LEFT IN NTDLL.H FOR DEMO PURPOSES (UNTIL PROBLEMS SOLVED)
    '------------------------------------------------------------------------------------------------------------------
    '----------------------------------------------------------------
    ' PSAPI API FUNCTIONS
    '----------------------------------------------------------------
    Declare Function EnumProcessModules Lib "PsApi.DLL" Alias "EnumProcessModules"( _
                        ByVal hProcess  As Dword, _        'Handle to Process
                        ByVal lphModule As Dword, _        'Handle to Module in Process
                        ByVal cb        As Dword, _        'Bytes to get
                        ByRef cbNeeded  As Dword) As Long  'Bytes really needed
    
    Declare Function GetModuleFileNameEx Lib "PsApi.DLL" Alias "GetModuleFileNameExA"( _
                        ByVal hProcess As Dword, _         'Handle to Process
                        ByVal hModule  As Dword, _         'Handle to Module in Process
                        lpFilename     As Asciiz, _        'Name of Module returned from call
                        ByVal nSize    As Dword) As Long   'Size of Name of Module (I use %MAX_PATH to get full name)
    
    '----------------------------------------------------------------
    ' PSAPI API WRAPPER FUNCTIONS
    '----------------------------------------------------------------
    Declare Function ProcessEnum As Long
    Declare Function GetPidPath(PID As Dword) As String
    
    '*** MOVE TO PSAPI.INC AFTER DEMO (when Problems are fixed)
    Function ProcessEnum As Long
         
         On Error GoTo errtrap:
         
         Local pInfoTable  As SYSTEM_HANDLE_TABLE_ENTRY_INFO Pointer
         Local sBuffer     As String
         Local sObjectType As String
         Local sObjectName As String
         Local sPidPath    As String
         Local pBuffer     As Dword Ptr
         Local LenBuffer   As Dword
         Local ByteNeeded  As Dword
         Local InfoCount   As Dword
         Local Looper      As Dword
         Local Retval      As Long
         Local ObjectFlags As String
    '*** Set Initial Parameters
         LenBuffer = SizeOf(SYSTEM_HANDLE_TABLE_ENTRY_INFO) 'Minimum buffer size for a valid ByteNeeded
         sBuffer = Nul$(LenBuffer)                          'Fill buffer with nulls
         pBuffer = StrPtr(sBuffer)                          'Set pointer to buffer
    '*** Get needed number of bytes
    '     Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)   'Hardcoded
         Call Dword PbQuerySysInfoHandle Using PbQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded) To Retval     'via loadlibrary
    '*** Set to needed number of bytes
         If ByteNeeded > LenBuffer Then
              LenBuffer = ByteNeeded
              sBuffer = Nul$(LenBuffer)
              pBuffer = StrPtr(sBuffer)
    '          Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)   'Hardcoded
              Call Dword PbQuerySysInfoHandle Using PbQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded) To Retval     'via loadlibrary
         End If
    '*** Get Number of Handles in the system
         pInfoTable = pBuffer
         InfoCount  = @pInfoTable.NumberOfHandles
    '*** Listbox Display Only
         Retval = SendMessage(hList, %LB_INITSTORAGE, InfoCount * 4, InfoCount * 200) 'Faster listbox filling
    '*** Set Array to store Handle Information
    '     DIM Info(1 TO InfoCount) AS SYSTEM_HANDLE_INFORMATION AT pInfoTable + 4 '+ 4 to start just after .NumberOfHandles
         ReDim Info(1 To InfoCount) As SYSTEM_HANDLE_INFORMATION At pInfoTable + 4 '+ 4 to start just after .NumberOfHandles
         ReDim ObjectInfo(1 To InfoCount)   'Dimension Object Info to same size as System Info
    MsgBox "System Info Gathered with " + Str$(InfoCount) + " items to sort"
    '*** Sort the Object Type of each element
         For Looper = 1 To InfoCount        'For each handle in the system
                        If killMe=1 Then Exit For
    '          Select Case WindowsOs         'Dependin on Operating System Object types are different (add into code later)
    '               case 0    'Win95
    '               CASE 1    'Win98
    '               CASE 2    'WinME
    '               CASE 3    'WinNT
    '               CASE 4    'Win2k
    '               CASE 5    'WinXP
                        Select Case Info(Looper).ObjectTypeNumber
                             Case 02 : sObjectType = " Directory"
                             Case 03 : sObjectType = " SymbolicLink"
                             Case 04 : sObjectType = " Token"             'Added from SysInternals
                             Case 05 : sObjectType = " Process"
                             Case 06 : sObjectType = " Thread"
                             Case 07 : sObjectType = " Job"               'Added from SysInternals
                             Case 09 : sObjectType = " Event"
                             Case 11 : sObjectType = " Mutant"
                             Case 13 : sObjectType = " Semaphore"
                             Case 14 : sObjectType = " Timer"             'Added from SysInternals
                             Case 16 : sObjectType = " KeyedEvent"
                             Case 17 : sObjectType = " WindowStation"     'Added from SysInternals
                             Case 18 : sObjectType = " Desktop"           'Added from SysInternals
                             Case 19 : sObjectType = " Section"           'Added from SysInternals
                             Case 20 : sObjectType = " Key"               'Added from SysInternals
                             Case 21 : sObjectType = " Port"              'Added from SysInternals
                             Case 22 : sObjectType = " WaitablePort"      'Added from SysInternals
                             Case 27 : sObjectType = " IoCompletion"      'Added from SysInternals
                             Case 28 : sObjectType = " File"              'Added from SysInternals
                             Case 29 : sObjectType = " WmiGuid"           'Added from SysInternals
                             Case Else : sObjectType = " UnKnown " + $Tab + $Tab + Str$(Info(Looper).ObjectTypeNumber)
                        End Select
    '               CASE 6    'WinVista
    '          end select
    '*** Re-Enable if you want to see the list
              ObjectFlags = Hex$(Info(Looper).Flags, 1)
              Select Case ObjectFlags            '0x00 = NONE, 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                   Case "0"
                        ObjectFlags = ObjectFlags + " - NONE"
                   Case "1"
                        ObjectFlags = ObjectFlags + " - PROTECT_FROM_CLOSE"
                   Case "2"
                        ObjectFlags = ObjectFlags + " - INHERIT"
              End Select
    ''*** Get path to the process
         ObjectInfo(Looper).sPidPath = GetPidPath(Info(Looper).ProcessID)
    '*** Get the Object Name
    '*** WARNING ... Named Pipes are known to hang the code but unable to know if ObjectType is a pipe
    '***                and not a file without asking the name ... so its a catch-22
         Dim SkipFile As Long
         If InStr(ObjectInfo(Looper).sPidPath, "Explorer.exe") Then SkipFile = %True
         If InStr(ObjectInfo(Looper).sPidPath, "EnumProcessObjectHandles") Then SkipFile = %True
         If SkipFile = %False Then ObjectInfo(Looper).sObjectName = GetObjectName(Info(Looper).ProcessID, Info(Looper).SysHandle)
    '          ObjectInfo(Looper).sObjectName = GetObjectName(Info(Looper).ProcessID, Info(Looper).SysHandle)
    '          SELECT CASE ObjectInfo(Looper).sObjectName
    '               CASE "", "No DuplicateHandle"
    '               CASE ELSE
                        ListAdd   "Number "        & Format$(Looper)                        & _
                                  " - Pid "        & Format$(Info(Looper).ProcessID)        & _
                                  " - HandleId "   & Hex$(Info(Looper).SysHandle, 4)           & _
                                  " - Object "     & Hex$(Info(Looper).SysObject, 8)           & _
                                  " - Access "     & Hex$(Info(Looper).GrantedAccess, 8)    & _
                                  " - Flags "      & ObjectFlags                            & _
                                  " - HandleType"  & Str$(Info(Looper).ObjectTypeNumber)    & _
                                  sObjectType
                        ListAdd "Pid Path = " & ObjectInfo(Looper).sPidPath
                        ListAdd "Object Name = " & ObjectInfo(Looper).sObjectName
                        ListAdd ""
    '          end select
    '*** Block to check for certain device types open (demo purposes Only)
              If InStr(ObjectInfo(Looper).sObjectName, "\Device\Serial") _
                   Or InStr(ObjectInfo(Looper).sObjectName, "\Device\EdgeSer") _
                   Or InStr(ObjectInfo(Looper).sObjectName, "\Device\USBPDO") _
                   Then MsgBox  ObjectInfo(Looper).sObjectName + " open in " + ObjectInfo(Looper).sPidPath
    '*** Just to refresh the dialog
         Next Looper
    'MSGBOX "All Done with " + STR$(UBOUND(SortProcess)) + " and " + STR$(UBOUND(Info)) 
         Exit Function
    errtrap:
         Exit Function
    End Function
    
    Function GetObjectName(ProcessId As Dword, Hndl As Word) As String
         Local Retval     As Long
         Local hCurrent As Dword
         Local hResult As Dword
         Local hExitCode As Dword
         Local Arg      As Long
         Local idThread As Dword
    
         hCurrent = GetCurrentProcess
         If ProcessId Then
              hProc = OpenProcess(%PROCESS_DUP_HANDLE, 0, ProcessId)
    '          hProc = OpenProcess(%PROCESS_ALL_ACCESS, %False, ProcessId)
              If hProc <> %INVALID_HANDLE_VALUE Then
                   If DuplicateHandle(hProc, ByVal Hndl, -1, hPort, (%GENERIC_READ Or %KEY_READ), _
                                                 %PROCESS_ALL_ACCESS, %DUPLICATE_SAME_ACCESS) Then
                        LenBuffer = SizeOf(UNICODE_STRING)
                        sBuffer = Nul$(LenBuffer)
                        pBuffer = StrPtr(sBuffer)
    '*** Thread the calls to check object name since named pipes are known to "Hang" rather than return
                        hThread = CreateThread(ByVal %Null, 0, CodePtr(ThreadGetObjectName), ByRef Arg, _
                                                 %THREAD_TERMINATE Or %THREAD_QUERY_INFORMATION, _
                                                 ByVal VarPtr(idThread))
    
                        If hThread <> %INVALID_HANDLE_VALUE Then
                             Do
                                  Select Case WaitForSingleObject(hThread, 50) 'Try with 3500 and 7500
                                       Case %WAIT_ABANDONED     'Mutex Object not released
    '                                        ObjNameRet = %STATUS_SEVERITY_ERROR
                                            hThread = %INVALID_HANDLE_VALUE
                                       Case %WAIT_OBJECT_0      'The state of the specified object is signaled
                                            GetExitCodeThread(hThread, Retval)
    '                                        TerminateThread BYVAL hThread, Retval
                                            CloseHandle hThread
    '                                        ObjNameRet = %STATUS_SEVERITY_ERROR
                                            hThread = %INVALID_HANDLE_VALUE
                                            Exit Do
                                       Case %WAIT_TIMEOUT       'The time-out interval elapsed, and the object's state is nonsignaled.
                                            TerminateThread ByVal hThread, ByVal 0
                                            CloseHandle hThread 'CloseHandle after TerminateThread
    '                                        ObjNameRet = %STATUS_SEVERITY_ERROR
                                            hThread = %INVALID_HANDLE_VALUE
                                            Exit Do
                                  End Select
                             Loop
    'MSGBOX STR$(hPort) + $TAB + STR$(@pbuffer) + $TAB + STR$(lenBuffer) + $TAB + STR$(ByteNeeded) + $TAB + STR$(ObjNameRet)
    '                              IF ObjNameRet = %STATUS_SUCCESS THEN
    '                                   puString = pBuffer
    '                                   IF @puString.Length > 0 THEN
    '                                        sObjName = NUL$(@puString.Length \ 2)
    ''                                        sObjName = @puString.pBuffer
    '                                        WideCharToMultiByte %CP_ACP, %NULL, BYVAL @puString.pBuffer, @puString.Length, _
    '                                                       BYVAL STRPTR(sObjName), LEN(sObjName), BYVAL %NULL, BYVAL %NULL
    '                                        FUNCTION = "ObjName: " & sObjName
    '                                   END IF
    '                              ELSE
    '                                   FUNCTION = "Bad NtQueryObject"
    '                              END IF
                                  Function = "ObjName: " & sObjName
                                  CloseHandle hPort
                        End If
                   Else
                        Function = "No DuplicateHandle"
                   End If
                   CloseHandle hProc
              Else
                   Function = "Bad OpenProcess"
              End If
         End If
    'hProc = OpenProcess(BYVAL %PROCESS_TERMINATE, BYVAL 0, BYVAL hProc)
    End Function
    
    Function ThreadGetObjectName(ByVal x As Long) As Long
    '     ObjNameRet = NtQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded)
         Call Dword PbQueryObjName Using PbQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded) To ObjNameRet
         If ByteNeeded > LenBuffer Then
              LenBuffer = ByteNeeded
    '          ObjNameRet = NtQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded)
              Call Dword PbQueryObjName Using PbQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded) To ObjNameRet
         End If
                                  If ObjNameRet = %STATUS_SUCCESS Then
                                       puString = pBuffer
                                       If @puString.Length > 0 Then
                                            sObjName = Nul$(@puString.Length \ 2)
    '                                        sObjName = @puString.pBuffer
                                            WideCharToMultiByte %CP_ACP, %Null, ByVal @puString.pBuffer, @puString.Length, _
                                                           ByVal StrPtr(sObjName), Len(sObjName), ByVal %Null, ByVal %Null
    '                                        FUNCTION = "ObjName: " & sObjName
                                       End If
                                  Else
    '                                   FUNCTION = "Bad NtQueryObject"
                                       sObjName = "Bad NtQueryObject"
                                  End If
    
    End Function
    
    Function GetPidPath(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 Retval      As Long
         Local HandleSize  As Dword
    
         hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION Or %PROCESS_VM_READ, 0, Pid)
         If hProcess Then
              LenBuffer = 4 'SIZEOF(DWORD)
              sBuffer = Nul$(LenBuffer)
              pBuffer = StrPtr(sBuffer)
              Retval = EnumProcessModules(hProcess, pBuffer, LenBuffer, ByteNeeded)
              If ByteNeeded > LenBuffer Then
                   LenBuffer = ByteNeeded
                   sBuffer = Nul$(LenBuffer)
                   pBuffer = StrPtr(sBuffer)
                   Retval = EnumProcessModules(hProcess, pBuffer, LenBuffer, ByteNeeded)
              End If
              If Retval Then
    '               HandleCount = LenBuffer \ 4
                   HandleCount = LenBuffer \ SizeOf(HandleSize)
                   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 = Left$(ModuleName, Retval)
              Else
                   'ListAdd  "Bad EnumProcessModules"
              End If
              CloseHandle hProcess
         End If
         If PidPath = "" Then PidPath = "SYSTEM"
         Function = PidPath
    'hProcess = OpenProcess(BYVAL %PROCESS_TERMINATE, BYVAL 0, BYVAL hProcess)
    End Function
    '----------------------------------------------------------------
    
    '----------------------------------------------------------------
    ' DIALOG OBJECTS
    '----------------------------------------------------------------
    %ButtonQuery  = 101      'Query Button
    %ButtonSearch = 102      'Search Button
    %ButtonQuit   = 103      'Quit Button
    %ListBox      = 201      'Listbox
    %ComboBox     = 301      'Combobox
    %Grip         = 401      'SizeGrip
    
    Sub startSearching()
        Thread Create EnumThread(0) To stopThread 
    End Sub
    
    Sub stopSearching()
        Local stopper As Long
        Thread Close stopThread To stopper 
    End Sub
    
    Function EnumThread (ByVal x As Long) As Long
        ProcessEnum
        SetHorizontalListboxBar
        Control Enable hDlg, %ButtonSearch
        Control Enable hDlg, %ButtonQuery
        Control Enable hDlg, %ButtonQuit    
    End Function
    
    '----------------------------------------------------------------
    ' DIALOG FUNCTIONS
    '----------------------------------------------------------------
    CallBack Function DlgProc() As Long
         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
    '*** LoadLibrary and get functions
              Case %WM_COMMAND
                   Select Case LoWrd(CbWParam)
                        Case %ButtonQuery
                             If CbCtlMsg = %BN_CLICKED Or CbCtlMsg = 1 Then
                                  Control Disable hDlg, %ButtonQuit
                                  Control Disable hDlg, %ButtonQuery
                                  Control Disable hDlg, %ButtonSearch
                                  ListBox Reset CbHndl, %ListBox
                                  Control ReDraw CbHndl, %ListBox
                                  Sleep 200
                                  startSearching                              
                             End If
                        Case %ButtonSearch
                             If CbCtlMsg = %BN_CLICKED Or CbCtlMsg = 1 Then
                                  Control Get Text CbHndl, %ComboBox To sTextbox
                                  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
                             If CbCtlMsg = %BN_CLICKED Or CbCtlMsg = 1 Then
                                  Dialog End CbHndl
                                  killMe=1
                             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, %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 = 385
                   @MinMaxInfoPtr.ptMinTrackSize.y = 180
              Case %WM_CLOSE
    '               CloseHandle hProc        'Added in case 1 open
    '               CloseHandle hThread      'Added in case 1 open
    '               PostQuitMessage 0
                    killMe=1
         End Select
    End Function
    
    Function PBMain As Long
         killMe=0
         startKiller
         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 ComboBox, hDlg, %ComboBox, , 338, 281, 100, 50, _
                        %CBS_DROPDOWN Or %CBS_HASSTRINGS Or %WS_TABSTOP, %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, "Registry"
         ComboBox Add hDlg, %ComboBox, "HandleType 4 Key"
         ComboBox Select hDlg, %ComboBox, 2
    
         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
    
         'SetClassLong hDlg, %GCL_HICON, LoadIcon(ByVal %Null, ByVal %IDI_INFORMATION)
         Control Set Focus hDlg, %ButtonQuery
         
         NtDllHandle = LoadLibrary("ntdll.dll")       'If exists then map into this process
         PbQuerySysInfoHandle = GetProcAddress(NtDllHandle, "NtQuerySystemInformation")       'If exists then map into this process
         PbQueryObjName = GetProcAddress(NtDllHandle, "NtQueryObject")         'If exists then map into this process
         'MSGBOX "LoadLibrary = " + STR$(NtDllHandle) + $CR + "Query System = " + STR$(PbQuerySysInfoHandle) + $CR + "Query Object = " + STR$(PbQueryObjName)
         Dialog Show Modal hDlg Call DlgProc
         If stopMe<>1 Then 
            stopMe=1
            stopSearching()
         End If
         FreeLibrary NtDllHandle       'Free the Library once the above is mapped into this process
    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))
    '     Retval = SendMessage(hList, %LB_GETCURSEL, 0, 0)
         SendMessage hList, %LB_SETCURSEL, LastItem, 0
    End Function
    
    Function SetHorizontalListboxBar() As Long
         Local  Si        As apiSize
         Local  sBuffer   As String
         Local  hFont     As Dword
         Local  hDC       As Dword
         Local  ListWidth As Long
         Local  LastItem  As Long
         Local  Counter   As Long
         Local  TextLen   As Long
         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
    
    '------------------------------------------------------------------------------
    '   ** Killer Thread Start This One Early In PBMAIN() **
    '------------------------------------------------------------------------------
    Sub startKiller()
        Thread Create KillThread(0) To idThread 
    End Sub
    
    Function KillThread (ByVal x As Long) As Long
        On Error Resume Next
        Do Until killMe=1
            Sleep 1000
        Loop    
        Local ProcID As Long
        Local hProc As Long
        ProcID=GetCurrentProcessId()
        hProc = OpenProcess(ByVal %PROCESS_TERMINATE, ByVal 0, ByVal ProcID)
        If hProc <> %Null Then TerminateProcess ByVal hProc, ByVal %Null
        CloseHandle hProc    
    End Function
    '------------------------------------------------------------------------------
    ------------------

    Leave a comment:


  • Pierre Bellisle
    replied
    Cliff,
       Next stuff is probably right, names in parentesis are deduction
    and have to be confirmed, DebugObject was the one hard to find...

    Pierre

    Code:
    ' Windows NT 4          Window 2000            Window XP
    ' -----------------     -------------------    -------------------
    '  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
    Reference:
    defendion.com
    vchelp.net
    book. itzero.com





    [This message has been edited by Pierre Bellisle (edited August 18, 2007).]

    Leave a comment:


  • Michael Mattias
    replied
    A little hard to find because you use GLOBALs which are defined in the #INCLUDE but...


    Code:
    [b]     NtDllHandle = LoadLibrary("ntdll.dll")       'If exists then map into this process[/b]
         PbQuerySysInfoHandle = GetProcAddress(NtDllHandle, "NtQuerySystemInformation")       'If exists then map into this process
         [b]PbQueryObjName[/b] = GetProcAddress(NtDllHandle, "NtQueryObject")         'If exists then map into this process
        'MSGBOX "LoadLibrary = " + STR$(NtDllHandle) + $CR + "Query System = " + STR$(PbQuerySysInfoHandle) + $CR + "Query Object = " + STR$(PbQueryObjName)
    [b]     FreeLibrary NtDllHandle       'Free the Library once the above is mapped into this process[/b]
    
    
    ....
    
        [b]CALL DWORD PbQueryObjName [/b]
    Once you free the library, PBQueryObjectName* is no longer valid.

    Better still, eschew the GLOBAL, just reload the library, get the proc address, make the call and free the library each time you need to call a function in that library.

    *This is an ADDRESS , not an object name; so a variable name something like "PbQueryAddress" would be more appropos.

    Leave a comment:


  • Cliff Nichols
    replied
    I have things partially working. I say partially because still some bugs to fix
    that I just can not live with.

    Bugs I have:[list=1][*] I can not enum explorer.exe (this may be due to some security issue?)[*] On closing the program I either get a JIT error, or a error about reading a memory location, or closes fine, but Windows Task Manager (and SysInternals) shows my program still in use, and I can not end the process?[*] I still have to rely on my best guess as to what is happening since then concept is mostly "Undocumented"[/list=a]

    Below I am going to show my code as it stands (in 3 files) as cleanly as I could get them, and based from
    Pierre's assistance on different troublesome concepts (Thank you Pierre)
    The rest is what I could piece together from snippets, and what I "THINK" a line of code is supposed to be doing.

    Maybe this will help someone, or someone can help point out mistakes I have made.

    Anyways, let me know anything good bad or otherwise....
    (I commented as much as possible up to this point of key things I do not understand yet)

    Cliff

    The Demo.exe to show results
    Code:
    #COMPILE EXE             '#Win 8.03#
    #OPTION VERSION5         'Windows 2K and up only
    
    '----------------------------------------------------------------
    ' DIALOG GLOBALS
    '----------------------------------------------------------------
    GLOBAL hDlg    AS DWORD  'Handle for Dialog
    GLOBAL hList   AS DWORD  'Handle for Listbox
    '----------------------------------------------------------------
    
    '----------------------------------------------------------------
    ' DIALOG FUNCTIONS DECLARES
    '----------------------------------------------------------------
    DECLARE CALLBACK FUNCTION DlgProc() AS LONG
    DECLARE FUNCTION PBMAIN AS LONG
    DECLARE FUNCTION ListAdd(AddToList AS STRING) AS LONG
    DECLARE FUNCTION SetHorizontalListboxBar() AS LONG
    
    '----------------------------------------------------------------
    ' INCLUDES
    '----------------------------------------------------------------
    #INCLUDE "WIN32API.INC"  '#2005-01-27#
    #INCLUDE "NTDLL.h"
    #INCLUDE "NTDLL.INC"
    
    '----------------------------------------------------------------
    ' DIALOG OBJECTS
    '----------------------------------------------------------------
    %ButtonQuery  = 101      'Query Button
    %ButtonSearch = 102      'Search Button
    %ButtonQuit   = 103      'Quit Button
    %Listbox      = 201      'Listbox
    %Combobox     = 301      'Combobox
    %Grip         = 401      'SizeGrip
    
    
    '----------------------------------------------------------------
    ' DIALOG FUNCTIONS
    '----------------------------------------------------------------
    CALLBACK FUNCTION DlgProc() AS LONG
         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
    '*** LoadLibrary and get functions
                   NtDllHandle = LoadLibrary("ntdll.dll")       'If exists then map into this process
                   PbQuerySysInfoHandle = GetProcAddress(NtDllHandle, "NtQuerySystemInformation")       'If exists then map into this process
                   PbQueryObjName = GetProcAddress(NtDllHandle, "NtQueryObject")         'If exists then map into this process
    'MSGBOX "LoadLibrary = " + STR$(NtDllHandle) + $CR + "Query System = " + STR$(PbQuerySysInfoHandle) + $CR + "Query Object = " + STR$(PbQueryObjName)
                   FreeLibrary NtDllHandle       'Free the Library once the above is mapped into this process
              CASE %WM_COMMAND
                   SELECT CASE LOWRD(CBWPARAM)
                        CASE %ButtonQuery
                             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                  CONTROL DISABLE hDlg, %ButtonQuit
                                  CONTROL DISABLE hDlg, %ButtonQuery
                                  CONTROL DISABLE hDlg, %ButtonSearch
                                  LISTBOX RESET CBHNDL, %Listbox
                                  CONTROL REDRAW CBHNDL, %Listbox
                                  SLEEP 200
                                  ProcessEnum
                                  SetHorizontalListboxBar
                                  CONTROL ENABLE hDlg, %ButtonSearch
                                  CONTROL ENABLE hDlg, %ButtonQuery
                                  CONTROL ENABLE hDlg, %ButtonQuit
                             END IF
                        CASE %ButtonSearch
                             IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                  CONTROL GET TEXT CBHNDL, %Combobox TO sTextbox
                                  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
                             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, %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 = 385
                   @MinMaxInfoPtr.ptMinTrackSize.y = 180
              CASE %WM_CLOSE
    '               CloseHandle hProc        'Added in case 1 open
    '               CloseHandle hThread      'Added in case 1 open
    '               PostQuitMessage 0
         END SELECT
    END FUNCTION
    
    FUNCTION PBMAIN AS LONG
         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 COMBOBOX, hDlg, %Combobox, , 338, 281, 100, 50, _
                        %CBS_DROPDOWN OR %CBS_HASSTRINGS OR %WS_TABSTOP, %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, "Registry"
         COMBOBOX ADD hDlg, %Combobox, "HandleType 4 Key"
         COMBOBOX SELECT hDlg, %Combobox, 2
    
         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
    
         SetClassLong hDlg, %GCL_HICON, LoadIcon(BYVAL %NULL, BYVAL %IDI_INFORMATION)
         CONTROL SET FOCUS hDlg, %ButtonQuery
         DIALOG SHOW MODAL hDlg CALL DlgProc
    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))
    '     Retval = SendMessage(hList, %LB_GETCURSEL, 0, 0)
         SendMessage hList, %LB_SETCURSEL, LastItem, 0
    END FUNCTION
    
    FUNCTION SetHorizontalListboxBar() AS LONG
         LOCAL  Si        AS apiSize
         LOCAL  sBuffer   AS STRING
         LOCAL  hFont     AS DWORD
         LOCAL  hDC       AS DWORD
         LOCAL  ListWidth AS LONG
         LOCAL  LastItem  AS LONG
         LOCAL  Counter   AS LONG
         LOCAL  TextLen   AS LONG
         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
    The NtDll.H file
    Code:
    '----------------------------------------------------------------
    ' SYSTEM HANDLE INFORMATION CONSTANTS
    '----------------------------------------------------------------
    %SystemHandleInformation     = &H10
    %ObjectNameInformation       = &H1
    
    %STATUS_SUCCESS              = &H0
    %STATUS_MORE_ENTRIES         = &H105
    %STATUS_INFO_LENGTH_MISMATCH = &HC0000004
    %STATUS_BUFFER_OVERFLOW      = &H80000005
    %STATUS_SEVERITY_ERROR       = &H00000003
    
    '----------------------------------------------------------------
    ' SYSTEM HANDLE INFORMATION USER DEFINED TYPES
    '----------------------------------------------------------------
    TYPE SYSTEM_HANDLE_INFORMATION                         'Information Class is &h10    (I do not know why)
         ProcessID           AS DWORD                      'Process Id
         ObjectTypeNumber    AS BYTE                       'Object type number
         Flags               AS BYTE                       'Flags    (I do not know what the possible values are)
         SysHandle           AS WORD                       'Original was HANDLE, but that is a keyword (undocumented why?)
         SysObject           AS DWORD                      'Original was OBJECT, but that is a keyword for COM interaction in PB
         GrantedAccess       AS DWORD                      'Access granted (I do not know what the possible values are)
    END TYPE
    
    TYPE SYSTEM_OBJECT_INFORMATION                         'Added to patch into SYSTEM_HANDLE_INFORMATION
         sPidPath            AS ASCIIZ * %MAX_PATH         'Object path
         sObjectName         AS ASCIIZ * %MAX_PATH         'Object name
    END TYPE
    
    TYPE SYSTEM_HANDLE_TABLE_ENTRY_INFO                    'Internal lookup table to system information
         NumberOfHandles     AS DWORD                      'Number of handles in the system
         HANDLES(0 TO 0)     AS SYSTEM_HANDLE_INFORMATION  'Array of System Handle Information, (dimensions?)
    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
    
    '----------------------------------------------------------------
    ' SYSTEM PRIVILEGE GLOBALS
    '----------------------------------------------------------------
    GLOBAL Privilege AS LONG
    $SE_DEBUG_NAME = "SeDebugPrivilege"
    
    '----------------------------------------------------------------
    ' SYSTEM PRIVILEGE CONSTANTS
    '----------------------------------------------------------------
    %TOKEN_ADJUST_PRIVILEGES = &H20
    %TOKEN_QUERY = &H8
    %SE_PRIVILEGE_ENABLED = &H2
    %PROCESS_VM_READ = &H10
    %PROCESS_DUP_HANDLE = &H40
    %PROCESS_QUERY_INFORMATION = &H400
    %STANDARD_RIGHTS_ALL = &H1F0000
    %GENERIC_ALL = &H10000000
    
    '----------------------------------------------------------------
    ' NTDLL API FUNCTIONS
    '----------------------------------------------------------------
    '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
    
    '----------------------------------------------------------------
    ' NTDLL API FUNCTIONS CALLED VIA LOADLIBRARY
    '----------------------------------------------------------------
    DECLARE FUNCTION PbQuerySystemInformation ALIAS "PbQuerySystemInformation"( _
                        BYVAL SystemInformationClass  AS DWORD, _
                        BYVAL SystemInformation       AS DWORD, _
                        BYVAL SystemInformationLength AS DWORD, _
                        BYREF ReturnLength            AS DWORD) AS LONG
    
    DECLARE FUNCTION PbQueryObject ALIAS "PbQueryObject"( _
                        BYVAL hndl                    AS DWORD, _
                        BYVAL ObjectInformationClass  AS DWORD, _
                        BYVAL ObjectInformation       AS DWORD, _
                        BYVAL ObjectInformationLength AS DWORD, _
                        BYREF ReturnLength            AS DWORD) AS LONG
    
    '----------------------------------------------------------------
    ' WRAPPER GLOBALS
    '----------------------------------------------------------------
    'GLOBAL ObjNameRet             AS DWORD                 'Object Name returned from NtQueryObject
    GLOBAL NtDllHandle            AS DWORD                 'NtDll Handle to process
    GLOBAL PbQuerySysInfoHandle   AS DWORD                 'Pb Handle to NtDll - NtQuerySysInfoHandle via loadlibrary
    GLOBAL PbQueryObjName         AS DWORD                 'Pb Handle to NtDll - NtQueryObjName via loadlibrary
    
    GLOBAL Info()                 AS SYSTEM_HANDLE_INFORMATION       'Array of System Handles Info
    GLOBAL ObjectInfo()           AS SYSTEM_OBJECT_INFORMATION       'Array of System Objects Info
    GLOBAL ObjNameRet             AS DWORD                 'Return of threaded get object
    
    GLOBAL hProc      AS DWORD
    GLOBAL hThread AS DWORD
    
    GLOBAL sBuffer    AS STRING
    GLOBAL puString   AS UNICODE_STRING POINTER
    GLOBAL pBuffer    AS DWORD PTR
    GLOBAL LenBuffer  AS DWORD
    GLOBAL hPort      AS DWORD
    GLOBAL ByteNeeded AS DWORD
    GLOBAL sObjName   AS STRING
    '----------------------------------------------------------------
    ' WRAPPER FUNCTIONS
    '----------------------------------------------------------------
    DECLARE FUNCTION ProcessEnum AS LONG
    DECLARE FUNCTION FindHandleInformation(ProcessId AS DWORD, InfoCount AS DWORD, ProcSysHandleInfo AS SYSTEM_HANDLE_INFORMATION) AS LONG
    DECLARE FUNCTION ThreadGetObjectName(BYVAL x AS LONG) AS LONG
    DECLARE FUNCTION GetObjectName(ProcessId AS DWORD, Hndl AS WORD) AS STRING
    DECLARE FUNCTION GetPidPath(PID AS DWORD) AS STRING
    
    '------------------------------------------------------------------------------------------------------------------
    ' THE BELOW WILL BE MOVED TO PSAPI.H BUT LEFT IN NTDLL.H FOR DEMO PURPOSES (UNTIL PROBLEMS SOLVED)
    '------------------------------------------------------------------------------------------------------------------
    '----------------------------------------------------------------
    ' PSAPI API FUNCTIONS
    '----------------------------------------------------------------
    DECLARE FUNCTION EnumProcessModules LIB "PsApi.DLL" ALIAS "EnumProcessModules"( _
                        BYVAL hProcess  AS DWORD, _        'Handle to Process
                        BYVAL lphModule AS DWORD, _        'Handle to Module in Process
                        BYVAL cb        AS DWORD, _        'Bytes to get
                        BYREF cbNeeded  AS DWORD) AS LONG  'Bytes really needed
    
    DECLARE FUNCTION GetModuleFileNameEx LIB "PsApi.DLL" ALIAS "GetModuleFileNameExA"( _
                        BYVAL hProcess AS DWORD, _         'Handle to Process
                        BYVAL hModule  AS DWORD, _         'Handle to Module in Process
                        lpFilename     AS ASCIIZ, _        'Name of Module returned from call
                        BYVAL nSize    AS DWORD) AS LONG   'Size of Name of Module (I use %MAX_PATH to get full name)
    
    '----------------------------------------------------------------
    ' PSAPI API WRAPPER FUNCTIONS
    '----------------------------------------------------------------
    DECLARE FUNCTION ProcessEnum AS LONG
    DECLARE FUNCTION GetPidPath(PID AS DWORD) AS STRING
    The NtDll.INC file
    Code:
    '*** MOVE TO PSAPI.INC AFTER DEMO (when Problems are fixed)
    FUNCTION ProcessEnum AS LONG
         LOCAL pInfoTable  AS SYSTEM_HANDLE_TABLE_ENTRY_INFO POINTER
         LOCAL sBuffer     AS STRING
         LOCAL sObjectType AS STRING
         LOCAL sObjectName AS STRING
         LOCAL sPidPath    AS STRING
         LOCAL pBuffer     AS DWORD PTR
         LOCAL LenBuffer   AS DWORD
         LOCAL ByteNeeded  AS DWORD
         LOCAL InfoCount   AS DWORD
         LOCAL Looper      AS DWORD
         LOCAL Retval      AS LONG
         LOCAL ObjectFlags AS STRING
    '*** Set Initial Parameters
         LenBuffer = SIZEOF(SYSTEM_HANDLE_TABLE_ENTRY_INFO) 'Minimum buffer size for a valid ByteNeeded
         sBuffer = NUL$(LenBuffer)                          'Fill buffer with nulls
         pBuffer = STRPTR(sBuffer)                          'Set pointer to buffer
    '*** Get needed number of bytes
    '     Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)   'Hardcoded
         CALL DWORD PbQuerySysInfoHandle USING PbQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded) TO Retval     'via loadlibrary
    '*** Set to needed number of bytes
         IF ByteNeeded > LenBuffer THEN
              LenBuffer = ByteNeeded
              sBuffer = NUL$(LenBuffer)
              pBuffer = STRPTR(sBuffer)
    '          Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)   'Hardcoded
              CALL DWORD PbQuerySysInfoHandle USING PbQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded) TO Retval     'via loadlibrary
         END IF
    '*** Get Number of Handles in the system
         pInfoTable = pBuffer
         InfoCount  = @pInfoTable.NumberOfHandles
    '*** Listbox Display Only
         Retval = SendMessage(hList, %LB_INITSTORAGE, InfoCount * 4, InfoCount * 200) 'Faster listbox filling
    '*** Set Array to store Handle Information
    '     DIM Info(1 TO InfoCount) AS SYSTEM_HANDLE_INFORMATION AT pInfoTable + 4 '+ 4 to start just after .NumberOfHandles
         REDIM Info(1 TO InfoCount) AS SYSTEM_HANDLE_INFORMATION AT pInfoTable + 4 '+ 4 to start just after .NumberOfHandles
         REDIM ObjectInfo(1 TO InfoCount)   'Dimension Object Info to same size as System Info
    MSGBOX "System Info Gathered with " + STR$(InfoCount) + " items to sort"
    '*** Sort the Object Type of each element
         FOR Looper = 1 TO InfoCount        'For each handle in the system
    '          Select Case WindowsOs         'Dependin on Operating System Object types are different (add into code later)
    '               case 0    'Win95
    '               CASE 1    'Win98
    '               CASE 2    'WinME
    '               CASE 3    'WinNT
    '               CASE 4    'Win2k
    '               CASE 5    'WinXP
                        SELECT CASE Info(Looper).ObjectTypeNumber
                             CASE 02 : sObjectType = " Directory"
                             CASE 03 : sObjectType = " SymbolicLink"
                             CASE 04 : sObjectType = " Token"             'Added from SysInternals
                             CASE 05 : sObjectType = " Process"
                             CASE 06 : sObjectType = " Thread"
                             CASE 07 : sObjectType = " Job"               'Added from SysInternals
                             CASE 09 : sObjectType = " Event"
                             CASE 11 : sObjectType = " Mutant"
                             CASE 13 : sObjectType = " Semaphore"
                             CASE 14 : sObjectType = " Timer"             'Added from SysInternals
                             CASE 16 : sObjectType = " KeyedEvent"
                             CASE 17 : sObjectType = " WindowStation"     'Added from SysInternals
                             CASE 18 : sObjectType = " Desktop"           'Added from SysInternals
                             CASE 19 : sObjectType = " Section"           'Added from SysInternals
                             CASE 20 : sObjectType = " Key"               'Added from SysInternals
                             CASE 21 : sObjectType = " Port"              'Added from SysInternals
                             CASE 22 : sObjectType = " WaitablePort"      'Added from SysInternals
                             CASE 27 : sObjectType = " IoCompletion"      'Added from SysInternals
                             CASE 28 : sObjectType = " File"              'Added from SysInternals
                             CASE 29 : sObjectType = " WmiGuid"           'Added from SysInternals
                             CASE ELSE : sObjectType = " UnKnown " + $TAB + $TAB + STR$(Info(Looper).ObjectTypeNumber)
                        END SELECT
    '               CASE 6    'WinVista
    '          end select
    '*** Re-Enable if you want to see the list
              ObjectFlags = HEX$(Info(Looper).Flags, 1)
              SELECT CASE ObjectFlags            '0x00 = NONE, 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                   CASE "0"
                        ObjectFlags = ObjectFlags + " - NONE"
                   CASE "1"
                        ObjectFlags = ObjectFlags + " - PROTECT_FROM_CLOSE"
                   CASE "2"
                        ObjectFlags = ObjectFlags + " - INHERIT"
              END SELECT
    ''*** Get path to the process
         ObjectInfo(Looper).sPidPath = GetPidPath(Info(Looper).ProcessID)
    '*** Get the Object Name
    '*** WARNING ... Named Pipes are known to hang the code but unable to know if ObjectType is a pipe
    '***                and not a file without asking the name ... so its a catch-22
         DIM SkipFile AS LONG
         IF INSTR(ObjectInfo(Looper).sPidPath, "Explorer.exe") THEN SkipFile = %True
         IF INSTR(ObjectInfo(Looper).sPidPath, "EnumProcessObjectHandles") THEN SkipFile = %True
         IF SkipFile = %False THEN ObjectInfo(Looper).sObjectName = GetObjectName(Info(Looper).ProcessID, Info(Looper).SysHandle)
    '          ObjectInfo(Looper).sObjectName = GetObjectName(Info(Looper).ProcessID, Info(Looper).SysHandle)
    '          SELECT CASE ObjectInfo(Looper).sObjectName
    '               CASE "", "No DuplicateHandle"
    '               CASE ELSE
                        ListAdd   "Number "        & FORMAT$(Looper)                        & _
                                  " - Pid "        & FORMAT$(Info(Looper).ProcessID)        & _
                                  " - HandleId "   & HEX$(Info(Looper).SysHandle, 4)           & _
                                  " - Object "     & HEX$(Info(Looper).SysObject, 8)           & _
                                  " - Access "     & HEX$(Info(Looper).GrantedAccess, 8)    & _
                                  " - Flags "      & ObjectFlags                            & _
                                  " - HandleType"  & STR$(Info(Looper).ObjectTypeNumber)    & _
                                  sObjectType
                        ListAdd "Pid Path = " & ObjectInfo(Looper).sPidPath
                        ListAdd "Object Name = " & ObjectInfo(Looper).sObjectName
                        ListAdd ""
    '          end select
    '*** Block to check for certain device types open (demo purposes Only)
              IF INSTR(ObjectInfo(Looper).sObjectName, "\Device\Serial") _
                   OR INSTR(ObjectInfo(Looper).sObjectName, "\Device\EdgeSer") _
                   OR INSTR(ObjectInfo(Looper).sObjectName, "\Device\USBPDO") _
                   THEN MSGBOX  ObjectInfo(Looper).sObjectName + " open in " + ObjectInfo(Looper).sPidPath
    '*** Just to refresh the dialog
         NEXT Looper
    'MSGBOX "All Done with " + STR$(UBOUND(SortProcess)) + " and " + STR$(UBOUND(Info))
    END FUNCTION
    
    FUNCTION GetObjectName(ProcessId AS DWORD, Hndl AS WORD) AS STRING
         LOCAL Retval     AS LONG
         LOCAL hCurrent AS DWORD
         LOCAL hResult AS DWORD
         LOCAL hExitCode AS DWORD
         LOCAL Arg      AS LONG
         LOCAL idThread AS DWORD
    
         hCurrent = GetCurrentProcess
         IF ProcessId THEN
              hProc = OpenProcess(%PROCESS_DUP_HANDLE, 0, ProcessId)
    '          hProc = OpenProcess(%PROCESS_ALL_ACCESS, %False, ProcessId)
              IF hProc <> %INVALID_HANDLE_VALUE THEN
                   IF DuplicateHandle(hProc, BYVAL Hndl, -1, hPort, (%GENERIC_READ OR %KEY_READ), _
                                                 %PROCESS_ALL_ACCESS, %DUPLICATE_SAME_ACCESS) THEN
                        LenBuffer = SIZEOF(UNICODE_STRING)
                        sBuffer = NUL$(LenBuffer)
                        pBuffer = STRPTR(sBuffer)
    '*** Thread the calls to check object name since named pipes are known to "Hang" rather than return
                        hThread = CreateThread(BYVAL %NULL, 0, CODEPTR(ThreadGetObjectName), BYREF Arg, _
                                                 %THREAD_TERMINATE OR %THREAD_QUERY_INFORMATION, _
                                                 BYVAL VARPTR(idThread))
    
                        IF hThread <> %INVALID_HANDLE_VALUE THEN
                             DO
                                  SELECT CASE WaitForSingleObject(hThread, 50) 'Try with 3500 and 7500
                                       CASE %WAIT_ABANDONED     'Mutex Object not released
    '                                        ObjNameRet = %STATUS_SEVERITY_ERROR
                                            hThread = %INVALID_HANDLE_VALUE
                                       CASE %WAIT_OBJECT_0      'The state of the specified object is signaled
                                            GetExitCodeThread(hThread, Retval)
    '                                        TerminateThread BYVAL hThread, Retval
                                            CloseHandle hThread
    '                                        ObjNameRet = %STATUS_SEVERITY_ERROR
                                            hThread = %INVALID_HANDLE_VALUE
                                            EXIT DO
                                       CASE %WAIT_TIMEOUT       'The time-out interval elapsed, and the object's state is nonsignaled.
                                            TerminateThread BYVAL hThread, BYVAL 0
                                            CloseHandle hThread 'CloseHandle after TerminateThread
    '                                        ObjNameRet = %STATUS_SEVERITY_ERROR
                                            hThread = %INVALID_HANDLE_VALUE
                                            EXIT DO
                                  END SELECT
                             LOOP
    'MSGBOX STR$(hPort) + $TAB + STR$(@pbuffer) + $TAB + STR$(lenBuffer) + $TAB + STR$(ByteNeeded) + $TAB + STR$(ObjNameRet)
    '                              IF ObjNameRet = %STATUS_SUCCESS THEN
    '                                   puString = pBuffer
    '                                   IF @puString.Length > 0 THEN
    '                                        sObjName = NUL$(@puString.Length \ 2)
    ''                                        sObjName = @puString.pBuffer
    '                                        WideCharToMultiByte %CP_ACP, %NULL, BYVAL @puString.pBuffer, @puString.Length, _
    '                                                       BYVAL STRPTR(sObjName), LEN(sObjName), BYVAL %NULL, BYVAL %NULL
    '                                        FUNCTION = "ObjName: " & sObjName
    '                                   END IF
    '                              ELSE
    '                                   FUNCTION = "Bad NtQueryObject"
    '                              END IF
                                  FUNCTION = "ObjName: " & sObjName
                                  CloseHandle hPort
                        END IF
                   ELSE
                        FUNCTION = "No DuplicateHandle"
                   END IF
                   CloseHandle hProc
              ELSE
                   FUNCTION = "Bad OpenProcess"
              END IF
         END IF
    'hProc = OpenProcess(BYVAL %PROCESS_TERMINATE, BYVAL 0, BYVAL hProc)
    END FUNCTION
    
    FUNCTION ThreadGetObjectName(BYVAL x AS LONG) AS LONG
    '     ObjNameRet = NtQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded)
         CALL DWORD PbQueryObjName USING PbQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded) TO ObjNameRet
         IF ByteNeeded > LenBuffer THEN
              LenBuffer = ByteNeeded
    '          ObjNameRet = NtQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded)
              CALL DWORD PbQueryObjName USING PbQueryObject(hPort, %ObjectNameInformation, pBuffer, LenBuffer, ByteNeeded) TO ObjNameRet
         END IF
                                  IF ObjNameRet = %STATUS_SUCCESS THEN
                                       puString = pBuffer
                                       IF @puString.Length > 0 THEN
                                            sObjName = NUL$(@puString.Length \ 2)
    '                                        sObjName = @puString.pBuffer
                                            WideCharToMultiByte %CP_ACP, %NULL, BYVAL @puString.pBuffer, @puString.Length, _
                                                           BYVAL STRPTR(sObjName), LEN(sObjName), BYVAL %NULL, BYVAL %NULL
    '                                        FUNCTION = "ObjName: " & sObjName
                                       END IF
                                  ELSE
    '                                   FUNCTION = "Bad NtQueryObject"
                                       sObjName = "Bad NtQueryObject"
                                  END IF
    
    END FUNCTION
    
    FUNCTION GetPidPath(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 Retval      AS LONG
         LOCAL HandleSize  AS DWORD
    
         hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR %PROCESS_VM_READ, 0, Pid)
         IF hProcess THEN
              LenBuffer = 4 'SIZEOF(DWORD)
              sBuffer = NUL$(LenBuffer)
              pBuffer = STRPTR(sBuffer)
              Retval = EnumProcessModules(hProcess, pBuffer, LenBuffer, ByteNeeded)
              IF ByteNeeded > LenBuffer THEN
                   LenBuffer = ByteNeeded
                   sBuffer = NUL$(LenBuffer)
                   pBuffer = STRPTR(sBuffer)
                   Retval = EnumProcessModules(hProcess, pBuffer, LenBuffer, ByteNeeded)
              END IF
              IF Retval THEN
    '               HandleCount = LenBuffer \ 4
                   HandleCount = LenBuffer \ SIZEOF(HandleSize)
                   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 = LEFT$(ModuleName, Retval)
              ELSE
                   'ListAdd  "Bad EnumProcessModules"
              END IF
              CloseHandle hProcess
         END IF
         IF PidPath = "" THEN PidPath = "SYSTEM"
         FUNCTION = PidPath
    'hProcess = OpenProcess(BYVAL %PROCESS_TERMINATE, BYVAL 0, BYVAL hProcess)
    END FUNCTION
    ------------------

    Leave a comment:


  • Cliff Nichols
    replied
    Forget what I said about the code revealing more than that found in
    SysInternals Process Monitor. I found that the unknown Object types were
    what is revealed if you show all un-named process handles.

    Now I am back to figuring the lock-up which I believe is due to doing
    a "GetObjectName" on a Pipe(or other handle) that is either synched, or locked somehow
    so the code halts until a reply is found.

    Thanx for the test Pierre, your test revealed what I 1st thought that if a reply does not
    return from the query, then how would the code know to continue on to the WaitForSingleObject
    and time itself out?

    Since documentation says that you could use DuplicateHandle, I wonder how I would DuplicateHandle that is not synched or locked somehow?

    Just some thoughts, but I know I am close to figuring things out

    ------------------

    Leave a comment:


  • Cliff Nichols
    replied
    Note to self....One of the sites that mentions the difference between W2K and XP
    SysInternals Forums

    Pierre, I have been doing a ton of testing today and find the code reveals more that SysInternals.
    (which is a clue to me of why it does not lock, but my code does)
    Another clue is on the same page above (and others) is that GetObjectType will
    hang on a process with an "Open-Named-Pipe"

    ------------------

    Leave a comment:


  • Pierre Bellisle
    replied
       As a test, I did encapsulate NtQueryObject in a thread
    with %THREAD_TERMINATE OR %THREAD_QUERY_INFORMATION access
    and used WaitForSingleObject and TerminateThread
    to avoid program loosing control on non readable pid.
    No success, still NtQueryObject refuse to quit.

    Even if it is not the solution,
    to cease freezing, I did update the code to bypass
    the reading of SYSTEM's pid and those from
    "SERVICES", "LSASS", "SVCHOST" and "ZONELABS\VSMON"

    More digging have to be done...

    Pierre

    Leave a comment:


  • Cliff Nichols
    replied
    Heh....I should have read your post earlier today (would have saved some time)
    I found the same problem in the same place.

    My 1st initial thought for a work-around is to check for the GrantedAccess value?

    Stuff I have already tried in the GetObjectName are
    [list=1][*] Open the process, and immediately close after duplicating the ProcessHandle [*] Tried DuplicateHandle(hProc, BYVAL Hndl, -1, hPort, (%GENERIC_READ OR %KEY_READ), %PROCESS_ALL_ACCESS, %PROCESS_ALL_ACCESS) <---Do NOT!!!! do this one, it locked me out of the computer so hard I had to power off[/list=a]

    I tried something else too but forgot what it was at the moment.
    2 funny things I did notice were that each time at lock-up, you can not compile and run the same file name again (obvious because the 1st is still in use)
    the other was that even if I can get the process killed (both by taskmanager, and sysinternals) it is only gone momentarily (at best) and seems to re-create itself?)

    I am working on a few ideas, but think the granted access may be the key.

    ------------------

    Leave a comment:

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