Enumerate Win32 Handles, Handle Manager

Share your advanced PureBasic knowledge/code with the community.
DarkPlayer
Enthusiast
Enthusiast
Posts: 107
Joined: Thu May 06, 2010 11:36 pm

Enumerate Win32 Handles, Handle Manager

Post by DarkPlayer »

Hello,

in the last days, i wrote a little program called "Handle Manager". It is based on many undocumented stuctures, definitions and API calls, so there might be still some bugs inside it.

What is the sense of the program?
Handle Manager shows you all used Handles from all Processes in the System. So you can for example see which registry keys are opened, or which files are used by a programm. You can also kill the handle by double clicking on it.

Why should i use the program?
Did you ever had the problem, that you want delete a file, but you get the error message "The file is used by a process, you cannot delete it" ? Then this program is your solution. Just click on "Enumerate Handles" and after this on search and enter the filename. After you have found the file, just make a double click on it and you can delete the file.
This is also useful, if you want to unmount a disk/ usb stick.

What should i know before i use the program?
I coded it for 32 bit, so it can have unpredictable results on 64 bit!
[All 32 bit NT OS:]
It can be dangerous to kill handles from other processes. Normaly a process does not check everytime if the handle is valid and this can cause a crash. So NEVER kill a Handle from a System process unless you know what you a doing!
[XP:]
SOLVED XP PROBLEM!

I think it is possible to write many intressting programs based on this code, so you can use the source code for what ever you want, just mention somewhere in the source code (for open source projects) or in the documentation/about dialog (for closed source projects): "This program uses NT Handle code by DarkPlayer"

Here is the code:

Code: Select all

;Written by DarkPlayer

Global FILE_TYPE.i
Global Process_TYPE.i
Global Thread_TYPE.i

Structure TypeList
  Name.s
  Enabled.i
  Checkbox.i
EndStructure

Structure TypeListArray
  Count.i
  Element.TypeList[0]
EndStructure

Global *Types.TypeListArray


Select OSVersion()
  Case #PB_OS_Windows_NT_4
    FILE_TYPE = 23
  Case #PB_OS_Windows_2000
    FILE_TYPE = 26
  Case #PB_OS_Windows_XP, #PB_OS_Windows_Server_2003
    FILE_TYPE = 28
  Case #PB_OS_Windows_Vista
    FILE_TYPE = 25
EndSelect

Enumeration
  #WIN_MAIN = 1
  #WIN_OPTIONS

  #GT_ENUM
  #GT_SEARCH
  #GT_OPTIONS
  #GT_PROGRESS
  #GT_LISTICON 

  #OPT_ENABLE_ALL
  #OPT_DISABLE_ALL
EndEnumeration

#STATUS_INFO_LENGTH_MISMATCH = $C0000004
#STATUS_INVALID_DEVICE_REQUEST = $C0000010

#FILE_DEVICE_NAMED_PIPE =          $00000011

#ProcessBasicInformation = 0
#ProcessDebugPort = 7
#ProcessWow64Information = 26
#ProcessImageFileName = 27

Structure PROCESS_BASIC_INFORMATION
  Reserved1.i;
  *PebBaseAddress;
  Reserved2.i[2];
  UniqueProcessId.i;
  Reserved3.i
EndStructure

Structure UNICODE_STRING
  Length.w
  MaxiumLength.w
  *Buffer
EndStructure

Structure OBJECT_TYPE_INFORMATION
  TypeName.UNICODE_STRING
  TotalNumberOfObjects.l
  TotalNumberOfHandles.l
  TotalPagedPoolUsage.l
  TotalNonPagedPoolUsage.l
  TotalNamePoolUsage.l
  TotalHandleTableUsage.l
  HighWaterNumberOfObjects.l
  HighWaterNumberOfHandles.l
  HighWaterPagedPoolUsage.l
  HighWaterNonPagedPoolUsage.l
  HighWaterNamePoolUsage.l
  HighWaterHandleTableUsage.l
  InvalidAttributes.l
  GenericMapping.GENERIC_MAPPING
  ValidAccessMask.l
  SecurityRequired.w
  MaintainHandleCount.w
  PoolType.l
  DefaultPagedPoolCharge.l
  DefaultNonPagedPoolCharge.l
EndStructure

Enumeration
  #SystemBasicInformation
  #SystemProcessorInformation
  #SystemPerformanceInformation
  #SystemTimeOfDayInformation
  #SystemNotImplemented1
  #SystemProcessesAndThreadsInformation
  #SystemCallCounts
  #SystemConfigurationInformation
  #SystemProcessorTimes
  #SystemGlobalFlag
  #SystemNotImplemented2
  #SystemModuleInformation
  #SystemLockInformation
  #SystemNotImplemented3
  #SystemNotImplemented4
  #SystemNotImplemented5
  #SystemHandleInformation
  ;// there are more available, but we do not need them here
EndEnumeration


;The Definition from SysInternals Forum
; Enumeration
;   #ObjectBasicInformation
;   #ObjectNameInformation
;   #ObjectTypeInformation
;   #ObjectAllInformation
;   #ObjectDataInformation
; EndEnumeration

;From http://rongchaua.net/blog/c-get-object-type-number-in-windows-64-bits/
Enumeration
    #ObjectBasicInformation = 0
    #ObjectNameInformation = 1
    #ObjectTypeInformation = 2
    #ObjectAllTypesInformation = 3
    #ObjectHandleInformation = 4
EndEnumeration

; Definition form ReactOS
; Enumeration ;almost all of them are not even documented on "The Undocumented Functions by NTinternals"
;   #ObjectBasicInformation      = 0
;   #ObjectNameInformation       = 1
;   #ObjectTypeInformation       = 2
;   #ObjectTypesInformation      = 3
;   #ObjectHandleFlagInformation = 4
;   #ObjectSessionInformation    = 5
;   #MaxObjectInfoClass          = 6
; EndEnumeration

Enumeration
  #FileDirectoryInformation=1
  #FileFullDirectoryInformation
  #FileBothDirectoryInformation
  #FileBasicInformation
  #FileStandardInformation
  #FileInternalInformation
  #FileEaInformation
  #FileAccessInformation
  #FileNameInformation
  #FileRenameInformation
  #FileLinkInformation
  #FileNamesInformation
  #FileDispositionInformation
  #FilePositionInformation
  #FileFullEaInformation
  #FileModeInformation
  #FileAlignmentInformation
  #FileAllInformation
  #FileAllocationInformation
  #FileEndOfFileInformation
  #FileAlternateNameInformation
  #FileStreamInformation
  #FilePipeInformation
  #FilePipeLocalInformation
  #FilePipeRemoteInformation
  #FileMailslotQueryInformation
  #FileMailslotSetInformation
  #FileCompressionInformation
  #FileCopyOnWriteInformation
  #FileCompletionInformation
  #FileMoveClusterInformation
  #FileQuotaInformation
  #FileReparsePointInformation
  #FileNetworkOpenInformation
  #FileObjectIdInformation
  #FileTrackingInformation
  #FileOleDirectoryInformation
  #FileContentIndexInformation
  #FileInheritContentIndexInformation
  #FileOleInformation
  #FileMaximumInformation
EndEnumeration

Structure CLIENT_ID
   UniqueProcess.i;
   UniqueThread.i;
EndStructure
   
Structure THREAD_BASIC_INFORMATION
  ExitStatus.l;
  TebBaseAddress.i;
  ClientId.CLIENT_ID;
  AffinityMask.l;
  Priority.l;
  BasePriority.l;
EndStructure

Enumeration
  #ThreadBasicInformation
  #ThreadTimes
  #ThreadPriority
  #ThreadBasePriority
  #ThreadAffinityMask
  #ThreadImpersonationToken
  #ThreadDescriptorTableEntry
  #ThreadEnableAlignmentFaultFixup
  #ThreadEventPair
  #ThreadQuerySetWin32StartAddress
  #ThreadZeroTlsCell
  #ThreadPerformanceCount
  #ThreadAmILastThread
  #ThreadIdealProcessor
  #ThreadPriorityBoost
  #ThreadSetTlsArrayAddress
  #ThreadIsIoPending
  #ThreadHideFromDebugger
  #ThreadBreakOnTermination
  #ThreadSwitchLegacyState
  #ThreadIsTerminated
  #ThreadLastSystemCall
  #ThreadIoPriority
  #ThreadCycleTime
  #ThreadPagePriority
  #ThreadActualBasePriority
  #ThreadTebInformation
  #ThreadCSwitchMon
EndEnumeration


Prototype.i GetVolumePathNameW(lpszFileName.p-unicode, *lpszVolumePathName, cchBufferLength.i)
Prototype.i GetVolumePathNameA(lpszFileName.p-ascii, *lpszVolumePathName, cchBufferLength.i)

CompilerIf #PB_Compiler_Unicode
  Global GetVolumePathName.GetVolumePathNameW
CompilerElse
  Global GetVolumePathName.GetVolumePathNameA
CompilerEndIf

Structure SYSTEM_HANDLE_TABLE_ENTRY_INFO
  ProcessId.l
  ObjectTypeNumber.a
  Flags.a
  Handle.w
  *Object
  GrantedAccess.l
EndStructure

Structure SYSTEM_HANDLE_INFORMATION
  HandleCount.l
  Handles.SYSTEM_HANDLE_TABLE_ENTRY_INFO[0] 
EndStructure


Structure FILE_NAME_INFORMATION
  FileNameLength.l;
  FileName.w[512];
EndStructure

Macro WaitNTThread()
  If WaitThread(Thread,100) = 0
    KillThread(Thread)
    Query\ReturnV = 1
    Debug "Killed"
  EndIf
EndMacro

Macro QueryThreadID()

  Protected Info.THREAD_BASIC_INFORMATION
 
  If NtQueryInformationThread_(Query\Handle,#ThreadBasicInformation, @Info, SizeOf(Info),0) = 0
    CName = "ThreadID: " + StrU(Info\ClientId\UniqueThread) + " PID: " + StrU(Info\ClientId\UniqueProcess)
  EndIf
 
EndMacro

; Macro QueryFileName()
;
;   *FILE.FILE_NAME_INFORMATION = AllocateMemory(SizeOf(FILE_NAME_INFORMATION))
;   
;   Query\ObjectName = *FILE
;   
;   If *File
;     Thread = CreateThread(@QueryFileThread(),@Query)
;     If Thread
;       WaitNTThread()
;         
;       If Query\ReturnV = 0 And *File\FileNameLength
;         CName =  PeekS(@*File\FileName[0],*File\FileNameLength,#PB_Unicode)   
;       EndIf
;       
;       
;     EndIf
;     FreeMemory(*File)
;     
;   EndIf
;   
; EndMacro

Macro QueryProcessName()

  Protected *MemoryStr.UNICODE_STRING
 
  *MemoryStr = AllocateMemory(2*#MAX_PATH)
  If *MemoryStr
 
    If ZwQueryInformationProcess_(DupHandle ,#ProcessImageFileName,*MemoryStr,2*#MAX_PATH,0) = 0 And *MemoryStr\Buffer And *MemoryStr\Length
   
      Protected ExePath.s = PeekS(*MemoryStr\Buffer,*MemoryStr\Length,#PB_Unicode)
      CName = StringField(ExePath,CountString(ExePath,"\")+1,"\")
   
    EndIf
   
  EndIf
 
EndMacro

Macro QueryNTObject()

  Query\ObjectName = *ObjectName
 
  Thread = CreateThread(@QueryThread(),@Query)
 
  If Thread
 
    WaitNTThread()
   
    If Query\ReturnV = 0 And *ObjectName\Buffer
      CName = PeekS(*ObjectName\Buffer,*ObjectName\Length,#PB_Unicode)
    EndIf
   
  EndIf

EndMacro

Declare ProcEvents()

Procedure XPTestThread(Handle.i)
  GetFileType_(Handle)
EndProcedure

Procedure AdjustToken()

  Protected Token.i
 
  If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_ALL_ACCESS, @Token)
 
    Protected LUID.q
    Protected TokensAdj.TOKEN_PRIVILEGES
    TokensAdj\PrivilegeCount = 1
   
    If LookupPrivilegeValue_(0,"SeDebugPrivilege",@TokensAdj\Privileges[0]\Luid)
   
      TokensAdj\Privileges[0]\Attributes = #SE_PRIVILEGE_ENABLED
     
      If AdjustTokenPrivileges_(Token, #False, @TokensAdj, SizeOf(TOKEN_PRIVILEGES), 0, 0)
     
        If GetLastError_() = 0
       
          ProcedureReturn #True
         
        EndIf
       
      EndIf
     
    EndIf
   
  EndIf
EndProcedure

Prototype EnumCallBack(PID.i, Type.s, Handle.i, Name.s, CouldAcces.i,User.i)

Structure QueryTH
  Handle.i
  *ObjectName.i
  ReturnV.i
EndStructure

Procedure QueryThread(*Query.QueryTH) ;We need this because NtQueryObject() freezes randomly...

  *Query\ReturnV = NtQueryObject_(*Query\Handle, #ObjectNameInformation, *Query\ObjectName, 255, 0)
 
EndProcedure

; Procedure QueryFileThread(*Query.QueryTH) ;We need this because ZwQueryInformationFile() freezes randomly...
;   Protected Status.q
;   *Query\ReturnV = ZwQueryInformationFile_(*Query\Handle, @STATUS, *Query\ObjectName, SizeOf(FILE_NAME_INFORMATION), #FileNameInformation)
; EndProcedure

Procedure.s ResolveObjectNumber(Obj.i)

  If *Types
    If Obj>0 And Obj <= *Types\Count
      ProcedureReturn *Types\Element[Obj]\Name
    EndIf
  EndIf
 
  ProcedureReturn Str(Obj)
 
EndProcedure

Procedure IsObjectEnabled(Obj.i)

  If *Types
    If Obj>0 And Obj <= *Types\Count
      ProcedureReturn *Types\Element[Obj]\Enabled
    EndIf
  EndIf
 
  ProcedureReturn #True
 
EndProcedure


Procedure FindStringIndex(Text.s, FindString.s, Index.i)
 
  Protected Position = 0
  Protected i.i
 
  For i = 1 To Index
    Position = FindString(Text, FindString,Position+1)
    If Position = 0
      ProcedureReturn 0
    EndIf
  Next
 
  ProcedureReturn Position
 
EndProcedure

Procedure EnumerateAllHandles(Call.EnumCallBack, User)
 
  Protected Length.i = 50
  Protected *Memory.SYSTEM_HANDLE_INFORMATION = AllocateMemory(Length)
  Protected PID.i
  Protected i.i
  Protected HTempProcess.i
  Protected DupHandle.i
  Protected *ObjectName.UNICODE_STRING
 
  If *Memory
   
    *ObjectName.UNICODE_STRING = AllocateMemory(512)
    *ObjectName\MaxiumLength = 254
   
    If *ObjectName
   
      Repeat
        Length * 2 ;There is a bug in the Windows API, Windows does not return the right size, so you have to do it that way
        *Memory = ReAllocateMemory(*Memory,Length)
        If *Memory     
          Result = NtQuerySystemInformation_(#SystemHandleInformation, *Memory, Length, 0)
        EndIf
      Until  Result <> #STATUS_INFO_LENGTH_MISMATCH Or *Memory = 0
     
      If Result = 0 And *Memory <> 0
       
        SetGadgetAttribute(#GT_PROGRESS, #PB_ProgressBar_Maximum, *Memory\HandleCount) ;Remove this, if you want to use it as include
       
        For i = 0 To *Memory\HandleCount -1
         
          
           
          If IsObjectEnabled(*Memory\Handles[i]\ObjectTypeNumber) 
           
            If *Memory\Handles[i]\ProcessId = GetCurrentProcessId_()
             
              DupHandle = *Memory\Handles[i]\Handle

            Else
             
              HTempProcess = OpenProcess_(#PROCESS_DUP_HANDLE,0,*Memory\Handles[i]\ProcessId)
              DupHandle = 0
             
              If HTempProcess
               
                If DuplicateHandle_(HTempProcess, *Memory\Handles[i]\Handle, GetCurrentProcess_(), @DupHandle,0, 0, #DUPLICATE_SAME_ACCESS) = 0
                  DupHandle = 0
                EndIf     
             
              EndIf       
           
            EndIf
           
            Protected CName.s = ""
            Protected Access.i = #True
            If DupHandle

              Protected Query.QueryTH
              Query\Handle = DupHandle
             
              XPError.i = #False
              
              Protected Thread.i
             
              If *Memory\Handles[i]\ObjectTypeNumber = FILE_TYPE
                
                ;This is somehow a crazy trick
                ;NtQueryObject_(*Query\Handle, #ObjectNameInformation,...) would cause a Thread freeze in the kernel
                ;GetFileType_() also freezes, but it is still possible to kill the thread (not like when you call NTQueryObject)
                ;If GetFileType_() freezes, NtQueryObject would freeze too, so just dont call it and we will not get zombie Threads
                If OSVersion() = #PB_OS_Windows_XP
                  Thread = CreateThread(@XPTestThread(),DupHandle)
                  If Thread
                    If WaitThread(Thread,100) = 0
                      KillThread(Thread)
                      XPError = #True
                    EndIf
                  EndIf
                EndIf
                
                If XPError = #False
                  QueryNTObject()
                  If CName <> "" And GetFileType_(DupHandle) = #FILE_TYPE_DISK
                    Protected Position
                    Position = FindStringIndex(CName,"\",3)
                    If Position
           
                      Protected DeviceString.s = Space(128)
                     
                      If GetVolumePathName(CName,@DeviceString,128)
                        CName = DeviceString + Mid(CName,Position+1) 
                      EndIf
           
                    EndIf
                  EndIf
                EndIf

               
              ElseIf Process_TYPE And *Memory\Handles[i]\ObjectTypeNumber = Process_TYPE 
               
                QueryProcessName()
             
              ElseIf Thread_TYPE And *Memory\Handles[i]\ObjectTypeNumber = Thread_TYPE
               
                QueryThreadID()
               
              Else

                QueryNTObject()
               
              EndIf

            Else
              CName = "Not enough rights to access this process"
              Access = #False
            EndIf
           
            Call(*Memory\Handles[i]\ProcessId,ResolveObjectNumber(*Memory\Handles[i]\ObjectTypeNumber), *Memory\Handles[i]\Handle, Cname, Access,User)
           
            If *Memory\Handles[i]\ProcessId <> GetCurrentProcessId_()
              If HTempProcess
                CloseHandle_(HTempProcess)
                If DupHandle
                  CloseHandle_(DupHandle)
                EndIf
              EndIf              
            EndIf
                                       

            SetGadgetState(#GT_PROGRESS, i+1) ;Remove this, if you want to use it as include
            ProcEvents() ;Remove this, if you want to use it as include

          EndIf
          
        Next
        
        MessageRequester("Ready", "Enumerated " + Str(*Memory\HandleCount) + " Handles") ;Remove this, if you want to use it as include
      EndIf
   
      FreeMemory(*ObjectName)
   
    EndIf
   
    FreeMemory(*Memory)
 
  EndIf

EndProcedure

Procedure EnumerateSystemTypes()
 
  Protected *Memory
  *Memory = AllocateMemory(1024*10) ;A bug in Windows, the function does not return the needed size, so we take 10kb, should be enough
  If *Memory
 
    Protected Length.i
    If ZwQueryObject_(0, #ObjectAllTypesInformation, *Memory, 10214, 0) = 0
      If *Types
        FreeMemory(*Types)
      EndIf
      If OSVersion() = #PB_OS_Windows_7
        *Types = AllocateMemory(SizeOf(TypeListArray) + (PeekI(*Memory)+2) * SizeOf(TypeList))
      Else
        *Types = AllocateMemory(SizeOf(TypeListArray) + (PeekI(*Memory)+1) * SizeOf(TypeList))
      EndIf
      If *Types
     
        *Types\Count = PeekI(*Memory)
       
        Protected Offset = *Memory + SizeOf(Integer)
       
        For i = 0 To PeekI(*Memory) - 1
         
          *Item.OBJECT_TYPE_INFORMATION = Offset
          If OSVersion() = #PB_OS_Windows_7 ;Not really sure about it, but i have read it and can not test ist
            *Types\Element[i+2]\Name = PeekS(*Item\TypeName\Buffer,*Item\TypeName\Length,#PB_Unicode)
            *Types\Element[i+2]\Enabled = #True
          Else
            *Types\Element[i+1]\Name = PeekS(*Item\TypeName\Buffer,*Item\TypeName\Length,#PB_Unicode)
            *Types\Element[i+1]\Enabled = #True
          EndIf
         
         
          Offset = *Item\TypeName\Buffer + *Item\TypeName\MaxiumLength
         
          If *Item\TypeName\MaxiumLength % 4 <> 0
            OffSet + (4-*Item\TypeName\MaxiumLength % 4)
          EndIf
         
        Next
       
      EndIf
     
    EndIf
    FreeMemory(*Memory)
  EndIf
 
EndProcedure


Procedure.s GetPathFromPID(PID.i)
  Protected HProcess.i
  Protected *Memory.UNICODE_STRING
  Protected Name.s = ""
  Protected Size.s
  Protected Position.i
  Protected Library.i
 
  If PID = 4 : ProcedureReturn "SYSTEM" : EndIf
 
  *Memory = AllocateMemory(2*#MAX_PATH)
  If *Memory
    HProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION,0,PID)
    If HProcess
      If ZwQueryInformationProcess_(HProcess ,#ProcessImageFileName,*Memory,2*#MAX_PATH,0) = 0
        Name = PeekS(*Memory\Buffer,*Memory\Length,#PB_Unicode)
        Position = FindStringIndex(Name,"\",3)
        If Position

          Protected DeviceString.s = Space(128)
         
          If GetVolumePathName(Name,@DeviceString,128)
            Name = DeviceString + Mid(Name,Position+1) 
          EndIf

        EndIf
      EndIf
      CloseHandle_(HProcess)
    EndIf
    FreeMemory(*Memory)
  EndIf
  ProcedureReturn Name
EndProcedure


Procedure KillHandle(PID.i, Handle.i)
 
  Protected HTempProcess.i
  Protected Result.i = #False
 
  Debug PID
  Debug Handle
 
  HTempProcess = OpenProcess_(#PROCESS_DUP_HANDLE,0,PID)
  If HTempProcess
   
    If DuplicateHandle_(HTempProcess, Handle, GetCurrentProcess_(), 0,0, 0, #DUPLICATE_CLOSE_SOURCE)
      MessageRequester("Information", "Killed... this time you don't have to go to jail")
      Result = #True
    Else
      MessageRequester("Information", "Could not kill the handle, maybe try an axe?")
    EndIf     
   
    CloseHandle_(HTempProcess)
   
  EndIf
 
  ProcedureReturn Result
 
EndProcedure

;- GUI Code

Procedure Enum(PID.i, Type.s, Handle.i, Name.s, CouldAcces.i,User.i)
 
  Protected Path.s
  Protected EXE.s
 
  Path = GetPathFromPID(PID)
 
  If Path
    EXE = StringField(Path,CountString(Path,"\")+1,"\")
  EndIf
 
  AddGadgetItem(#GT_LISTICON,-1, Str(PID) + Chr(10)+ EXE +Chr(10)+ Type +Chr(10) + Str(Handle) + Chr(10) + Name)
 
  If CouldAcces = #False
    ;SetGadgetItemColor(#GT_LISTICON, CountGadgetItems(#GT_LISTICON)-1,#PB_Gadget_BackColor, $BABBFF,-1)
  EndIf
 
EndProcedure

Procedure ProcEvents()
  Protected Event.i
  Protected Gadget.i
  Protected i.i
  Protected Find.s
  Protected Name.s
 
  Event = WindowEvent()
  If EventWindow() = #WIN_MAIN
 
    If Event = #PB_Event_CloseWindow
   
      End
     
    ElseIf Event = #PB_Event_Gadget
   
      Gadget = EventGadget()
     
      If Gadget = #GT_ENUM
     
        DisableGadget(#GT_ENUM, #True)
        DisableGadget(#GT_SEARCH,#False)
        ClearGadgetItems(#GT_LISTICON)
        EnumerateAllHandles(@Enum(),0)
        DisableGadget(#GT_ENUM, #False)
     
      ElseIf Gadget = #GT_SEARCH
     
        Find.s = LCase(InputRequester("Search", "What do you search?",""))
       
        For i = 0 To CountGadgetItems(#GT_LISTICON) -1
         
          Name = LCase(GetGadgetItemText(#GT_LISTICON,i,4))
         
          If FindString(Name,Find,1)
            SetGadgetState(#GT_LISTICON,i)
            Debug "Found " + Str(i)
            Break
          EndIf
       
        Next
     
      ElseIf Gadget = #GT_LISTICON
       
        If EventType() = #PB_EventType_LeftDoubleClick And GetGadgetState(#GT_LISTICON) <> -1
       
          Protected Item.i = GetGadgetState(#GT_LISTICON)
          Protected MSGText.s
          Protected Flag.i
         
          If Val(GetGadgetItemText(#GT_LISTICON, Item,0)) = 4
            MSGText.s = "WARNING! Do you really want to kill a SYSTEM handle? This can cause a BSOD!"
            Flag = #MB_ICONSTOP
          Else
            MSGText.s = "Do you really want to kill this handle?"
            Flag = #MB_ICONWARNING
          EndIf
         
          If MessageRequester("Warning", MSGText ,#PB_MessageRequester_YesNo|Flag) = #PB_MessageRequester_Yes
            If KillHandle(Val(GetGadgetItemText(#GT_LISTICON, Item,0)),Val(GetGadgetItemText(#GT_LISTICON, Item,3)))
              RemoveGadgetItem(#GT_LISTICON, Item)
            EndIf
          EndIf
         
        EndIf
       
      ElseIf Gadget = #GT_OPTIONS
       
        If IsWindow(#WIN_OPTIONS)
          SetActiveWindow(#WIN_OPTIONS)
        Else
          If *Types
           
            #CheckBox_Width = 150

           
            Protected Width.i = (*Types\Count / 10) * (#CheckBox_Width+5) + 10
            If *Types\Count % 10 <> 0
              Width + #CheckBox_Width + 5
            EndIf
           
            OpenWindow(#WIN_OPTIONS,0,0,Width,300,"Options",#PB_Window_ScreenCentered |#PB_Window_SystemMenu)
           
              ButtonGadget(#OPT_ENABLE_ALL, 5, 260, 100,30,"Enable All")
             
              ButtonGadget(#OPT_DISABLE_ALL, 110, 260, 100,30,"Disable All")
             
              For i = 1 To *Types\Count
                *Types\Element[i]\Checkbox = CheckBoxGadget(#PB_Any, ((i -1) / 10) * #CheckBox_Width + 5, ((i -1) % 10) * 25 + 5, #CheckBox_Width, 25, *Types\Element[i]\Name)
                SetGadgetState(*Types\Element[i]\Checkbox, *Types\Element[i]\Enabled)
 
              Next           
          EndIf
         
        EndIf
         
      EndIf   
     
    EndIf
   
  Else
 
    If Event = #PB_Event_CloseWindow
   
      CloseWindow(#WIN_OPTIONS)
     
    ElseIf Event = #PB_Event_Gadget
     
      Gadget = EventGadget()
     
      If Gadget = #OPT_ENABLE_ALL
     
        For i = 1 To *Types\Count
          *Types\Element[i]\Enabled = #True
          SetGadgetState(*Types\Element[i]\Checkbox,#True)
        Next   
     
      ElseIf Gadget =  #OPT_DISABLE_ALL
        For i = 1 To *Types\Count
          *Types\Element[i]\Enabled = #False
          SetGadgetState(*Types\Element[i]\Checkbox,#False)
        Next   
     
      Else
             
        If *Types
         
          For i = 1 To *Types\Count
           
            If *Types\Element[i]\Checkbox = Gadget
              *Types\Element[i]\Enabled = GetGadgetState(*Types\Element[i]\Checkbox)
            EndIf
         
          Next
         
        EndIf 
       
      EndIf 
     
    EndIf
  EndIf
 
EndProcedure


  If IsUserAnAdmin_()
    AdjustToken()
  Else
    MessageRequester("Warning", "You should run this program as Administrator to get access to all Handles!" ,#MB_ICONWARNING)
  EndIf
 
  EnumerateSystemTypes()
  ;Overwrite FILE_TYPE if we could get a better one frome the System:
 
  If *Types
    Define i.i
    For i = 0 To *Types\Count - 1
      If *Types\Element[i]\Name = "File"
        FILE_TYPE = i
      ElseIf *Types\Element[i]\Name = "Process"
        Process_TYPE = i
      ElseIf *Types\Element[i]\Name = "Thread"
        Thread_TYPE = i
      EndIf
    Next
  EndIf
 
  Library = OpenLibrary(#PB_Any,"kernel32.dll")
  If Library
   
    CompilerIf #PB_Compiler_Unicode
      Global GetVolumePathName.GetVolumePathNameW = GetFunction(Library,"GetVolumePathNameW")
    CompilerElse
      Global GetVolumePathName.GetVolumePathNameA = GetFunction(Library,"GetVolumePathNameA")
    CompilerEndIf
   
  Else
    MessageRequester("Warning", "Can not load Kernel32.dll! Stopping Program" ,#MB_ICONWARNING)
    End
  EndIf

InitNetwork()

OpenWindow(#WIN_MAIN,0,0,640,505,"Handle Manager",#PB_Window_ScreenCentered |#PB_Window_SystemMenu)

  ButtonGadget(#GT_ENUM,5,5, 630, 20, "Enumerate Handles")
 
  ButtonGadget(#GT_SEARCH,5,30, 630, 20, "Search for Name")
  DisableGadget(#GT_SEARCH,#True)

  ButtonGadget(#GT_OPTIONS,5,55, 630, 20, "Options")

 
  ProgressBarGadget(#GT_PROGRESS, 5,80, 630, 20, 0 , 100, #PB_ProgressBar_Smooth)
 
  ListIconGadget(#GT_LISTICON, 5, 105, 630, 400, "PID",40, #PB_ListIcon_FullRowSelect | #PB_ListIcon_GridLines | #PB_ListIcon_AlwaysShowSelection)
    AddGadgetColumn(#GT_LISTICON, 1, "PNAME", 80)
    AddGadgetColumn(#GT_LISTICON, 2, "TYPE", 60)
    AddGadgetColumn(#GT_LISTICON, 3, "HANDLE", 60)
    AddGadgetColumn(#GT_LISTICON, 4, "NAME", 350)


  Repeat
    Delay(1)
    ProcEvents()
  ForEver
Last edited by DarkPlayer on Wed Jun 16, 2010 11:55 am, edited 2 times in total.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: Handle Manager

Post by rsts »

error in line 533?

Call(*Memory\Handles\ProcessId,ResolveObjectNumber(*Memory\Handles\ObjectTypeNumber), *Memory\Handles\Handle, Cname, Access,User)

garbage at end of line

cheers
DarkPlayer
Enthusiast
Enthusiast
Posts: 107
Joined: Thu May 06, 2010 11:36 pm

Re: Handle Manager

Post by DarkPlayer »

rsts wrote:error in line 533?

Call(*Memory\Handles\ProcessId,ResolveObjectNumber(*Memory\Handles\ObjectTypeNumber), *Memory\Handles\Handle, Cname, Access,User)

garbage at end of line

cheers


Sorry, but i can not reproduce your error with the newest version of PureBasic. The error message does not make sense for me, maybe you missed something while copying the code?
User avatar
Blue Steel
Enthusiast
Enthusiast
Posts: 132
Joined: Wed Aug 31, 2005 4:49 pm
Contact:

Re: Handle Manager

Post by Blue Steel »

worked fine here ;)
Currently using PureBasic 4.51(x86)

Image http://www.codingmonkeys.com
Covers many languages including PureBasic
DarkPlayer
Enthusiast
Enthusiast
Posts: 107
Joined: Thu May 06, 2010 11:36 pm

Re: Handle Manager

Post by DarkPlayer »

If someone wants to test killing handles, but does not want to cause any damage to another process, use this little test code:

Code: Select all

If CreateFile(0,"searchme.txt")
  Debug "File opened, search for "+Chr(34) + "searchme.txt"+Chr(34)+" and kill the handle"
  Repeat
    If GetFileType_(FileID(0)) = #FILE_TYPE_UNKNOWN And GetLastError_() <> 0
      Debug "File handle is killed!"
      End
    EndIf
    Delay(1)
  ForEver
EndIf
DarkPlayer
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Handle Manager

Post by netmaestro »

Thank you, could be quite useful. And I appreciate very much your willingess to share source code. :D
BERESHEIT
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Re: Handle Manager

Post by Rings »

cool (Win32) stuff ,
, enumerate different handles

i will move it into Tips&Tricks

thx for sharing
SPAMINATOR NR.1
Thorium
Addict
Addict
Posts: 1305
Joined: Sat Aug 15, 2009 6:59 pm

Re: Enumerate Win32 Handles, Handle Manager

Post by Thorium »

Awesome stuff, good work. :)
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: Enumerate Win32 Handles, Handle Manager

Post by SFSxOI »

Good job. Thank You. Works fine here on Window 7 Ultimate x86
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: Enumerate Win32 Handles, Handle Manager

Post by rsts »

Yes. it is quite excellent.

The garbage at end of line error was caused by my default compiler setting of enable inline asm.

Thanks for sharing.

cheers
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: Enumerate Win32 Handles, Handle Manager

Post by DarkDragon »

Nice! :)
bye,
Daniel
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: Enumerate Win32 Handles, Handle Manager

Post by jassing »

On a win xp system, it took 98 minutes to complete -- and all but 3 entries were were "insufficient rights" and I'm logged in as the administrator....
Code is nicely written (easy to read), so I'm sure I'll be able to get what I need out of it.
Thanks for sharing the code!
DarkPlayer
Enthusiast
Enthusiast
Posts: 107
Joined: Thu May 06, 2010 11:36 pm

Re: Enumerate Win32 Handles, Handle Manager

Post by DarkPlayer »

I also use Windows XP and i don't have these Problems. I disabled the debugger and compiled it as Unicode. The program enumerated all 121823 Handles in ~1 minute.
There is a bug in the Windows XP Kernel that will cause a hang up when you trie to get the name of some special File Handles. I found a workaround with a different API command, that also hangs up the running thread, but you can still kill it. To do this, I use a timeout. It seems that you always reach this timeout value.
I can not reproduce the bug. Maybe you are using a 64-bit version of Windows XP? I only tested it on 32 Bit systems.

DarkPlayer
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: Enumerate Win32 Handles, Handle Manager

Post by jassing »

Curious -- my system is also 32bit.
Post Reply