Announcement

Collapse
No announcement yet.

Process Handles? via NtDll or PsApi?

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

    Process Handles? via NtDll or PsApi?

    While researching ideas lately I discovered SysInternals Process Viewer can do EXACTLY what I would like to do.
    However to do it involves the ("UnDocumented" NtDll.dll) and PsApi.dll

    So far I have the parts of PsApi.dll working so that I understand them (basic enum processes, get the handles, names, get the modules (dll's) being used etc....)

    So far the drawbacks are the relying on dll's that may not have the needed dll's or functions that I need on some operating systems (I can live with that or loadlibrary to check first sort of thing)
    But I am wondering if maybe a better work-around is possible for all 32-bit OS'es?

    Beyond that I have more or less found 2 examples (one in C, and one in VB.NET) that do the same thing, but I am the 1st to omit that[list=1][*] I am VERY weak at both languages (I am a VB6 die-hard (turning PB)[*] The VB.NET was easier to understand, but had to port from French comments to English and my own guessing on what the code actually does[*] Neither example have I gotten working, but it must because the compiled exe works.[/list=a]

    What I would like to do...I thought should be simple...but here I am 10yrs later still trying to figure out why so hard, but at least I got a glimpse that "It CAN be done" is[list=1][*] Open a Serial Port (easy)[*] If the port is un-able to be opened, return the error that the port is in use (easy)[*] Rather than return "Port In Use" error, I would like to then go on to determine why or who? (hard, but I think PsApi and NtDll are my route to follow)[*] On error, then enumerate the processes, check each Module, or File Or other resource it has open and if matches, then change the error to "Because BLANK has it open"[/list=a]

    Any other ideas? or any help from others in porting would be GREATLY appreciated


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

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

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

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

    #2
       hi cliff,
    try this... http://www.powerbasic.com/support/pb...ad.php?t=25170

    pierre

    Comment


      #3
      Thanks Pierre,
      Exactly what I needed to stop my hair ripping habit. *LOL*

      A few drawbacks though is it will lock up (and I can not kill it from Task Manager)

      However if I use SysInternals to find the PID and then only "addlist" if the PID of your code matches
      then less chance of lockup, but still depending on what I am looking for, it may lock up so I think a value
      may be incorrect somewhere?

      Also under Win2K I get a ton of Unknown Handle Types....but I thought I had seen a
      posting somewhere that stated the values between the Operating systems is different (now if I can just
      find the document with the differences)

      Otherwise, your code has given me a MAJOR leap forward (and a renewed hope, that the task can be accomplished)

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

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

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

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

      Comment


        #4
        I found part of what i KNEWWWwww I had read somewhere
        NtD ll Warnings

        where part of the posting meantions
        NtQueryInformationFile() using class 9 (file name) to get the file name
        One thing to watch for is that NtQueryInformationFile will block forever if the access is denied to the file information. Thus you need to execute NtQueryInformationFile on another thread and wait for a timeout using a WaitHandle
        I am still looking into what is different about W2K vs XP though, so maybe I can shake out a few cobwebs

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

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

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

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

        Comment


          #5
          Posted code don't use NtQueryInformationFile
          but NtQuerySystemInformation, probably they
          behave the same and the use of a thread and
          a timeout will make program more robust.

          I will update code as soon as I can...

          Also if you find those handle type difference
          between 2000 and XP please let me know...

          Pierre

          Comment


            #6
            Thanx Pierre,
            I got home and tried a test or 2 and think they may be related (No lockups so far, just VERY long time)

            One thought I had, but not sure if possible is to thread the enum of handles (1 thread per process id?)
            but I am not sure its possible, since I still do not fully get the

            Code:
            Retval = NtQuerySystemInformation(%SystemHandleInformation, pBuffer, LenBuffer, ByteNeeded)
            what I would like to do is to NtQuerySystemInformation on just one process, but I think this line does ALL processes?

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

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

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

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

            Comment


              #7
                 Yes, NtQuerySystemInformation does it all in one call only.
              I'm not sure yet but I think that the problem may be caused
              by OpenProcess or DuplicateHandle in the GetObjectName function.
              Hard to say since the program is not freezing often on my side.
              In fact I must add the $SE_DEBUG_NAME privilege to make it freeze.

              One thing for shure is that GetPidPath and GetObjectName
              are in a FOR/NEXT loop, so if those are the one to be in a
              different thread, this is going to be easier...

              The very long time is mainly due to the time required to fill
              the listbox, even with %LB_INITSTORAGE wicht help to go faster.
              Many better solution are possible but I want to keep code simple.

              Pierre

              Comment


                #8
                   Problem is NtQueryObject in GetObjectName function.
                Found interesting stuff by Toby Opferman at http://www.codeproject.com/debug/cdb...select=1052011

                More work to do to find a clean solution.

                Pierre

                Comment


                  #9
                  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.

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

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

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

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

                  Comment


                    #10
                       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

                    Comment


                      #11
                      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"

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

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

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

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

                      Comment


                        #12
                        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

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

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

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

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

                        Comment


                          #13
                          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
                          ------------------
                          Engineer's Motto: If it aint broke take it apart and fix it

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

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

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

                          Comment


                            #14
                            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.

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

                            Comment


                              #15
                              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).]

                              Comment


                                #16
                                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
                                '------------------------------------------------------------------------------
                                ------------------
                                Mac Application Reviews and More

                                Comment


                                  #17
                                  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).]

                                  Comment


                                    #18
                                    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

                                    ------------------
                                    Mac Application Reviews and More

                                    Comment


                                      #19
                                      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

                                      ------------------
                                      Mac Application Reviews and More

                                      Comment


                                        #20
                                        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.

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

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

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

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

                                        Comment

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