Page 1 of 2

WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 13 Apr 2016, 03:30
by Bruttosozialprodukt
This script shows a list of all file/folder handles and which process the handles belong to.
If you can't eject your USB flashdrive or can't delete a certain file, just type in the path and the list will immediately show all processes that have an open handle on that file/folder/drive.
You can easily close the handles (or the whole processes if you so desire) with a simple click on a button.

This script also shows a list of ports that are currently blocked (used) and which process is doing it.


Future ideas and the latest information and files can be found here: https://github.com/T-vK/WhoLockedMe/

Downloads:
Download latest version of the script
Downlaod compiled 32bit version
Downlaod compiled 64bit version
Downlaod repository

Sourcecode:

Code: Select all

;#### Credits
; * Credits to HotkeyIt for the super complicated handle retrievement!
; * Credits to "just me" for translating all the handle retrievement stuff into AHK 1.1 and also for GetPathNameByHandle and GetIconByPath and other valuable info about icons in AHK and File System Redirection!
; * Credits to jNizM for a lot of valuable input and research and fine-tuning of GetExtendedTcpTable and GetProcessFilePath! 
; * If your name, someone elses name or anything else is missing from this list, tell me please!
; 
;#### Links
; * [Development topic on autohotkey.com](https://autohotkey.com/boards/viewtopic.php?p=80447)
; * [Release topic on autohotkey.com](https://autohotkey.com/boards/viewtopic.php?p=80455)
; * [The C++ code that has been translated to AHK code for the handle retrievement](http://forums.codeguru.com/showthread.php?176997.html)

#NoEnv
SetBatchLines, -1
RunAsAdmin()
LoadLibraries()
EnablePrivilege()
If (A_Is64bitOS && (A_PtrSize = 4))
    DllCall("Wow64DisableWow64FsRedirection", "UInt*", OldValue)
File := FileOpen(A_ScriptFullPath, "r") ; cause this script to appear in the list
; ==================================================================================================================================
Gui, Add, Tab2, w644 h627, File Handles|Network Ports
Gui, Tab, 1
    Gui, Add, Edit, w620 r1 gGui_FileHandles_CtrlEvt vGui_FileHandles_ApplyFilter
    Gui, Add, ListView, w620 r25 gGui_FileHandles_CtrlEvt vGui_FileHandles_LV +LV0x00000400, Potentially locked|By|PID|Handle
    LV_ModifyCol(1,349), LV_ModifyCol(2,150), LV_ModifyCol(3,50), LV_ModifyCol(4,50)
    Gui, Add, Button, w620 gGui_FileHandles_CtrlEvt vGui_FileHandles_ReloadData, Reload
    Gui, Add, Button, w620 gGui_FileHandles_CtrlEvt vGui_FileHandles_CloseHandle, Close Handle
    Gui, Add, Button, w620 gGui_FileHandles_CtrlEvt vGui_FileHandles_CloseProcess, Close Process
    Gui, Add, Progress, w620 vGui_FileHandles_ProgressBar
Gui, Tab, 2
    Gui, Add, Edit, w620 r1 gGui_NetworkPorts_CtrlEvt vGui_NetworkPorts_ApplyFilter
    Gui, Add, ListView, w620 r25 gGui_NetworkPorts_CtrlEvt vGui_NetworkPorts_LV +LV0x00000400, Port blocked|By|PID
    LV_ModifyCol(1,80), LV_ModifyCol(2,200), LV_ModifyCol(3,50)
    ; TODO: Add columns for remote port and IP addresses
    Gui, Add, Button, w620 gGui_NetworkPorts_CtrlEvt vGui_NetworkPorts_ReloadData, Reload
    Gui, Add, Button, w620 gGui_NetworkPorts_CtrlEvt vGui_NetworkPorts_ReleasePort, Release Port
    Gui, Add, Button, w620 gGui_NetworkPorts_CtrlEvt vGui_NetworkPorts_CloseProcess, Close Process
    Gui, Add, Progress, w620 vGui_NetworkPorts_ProgressBar
Gui, Show,, WhoLockedMe

Gui_FileHandles_CtrlEvt("Gui_FileHandles_ReloadData")
Gui_NetworkPorts_CtrlEvt("Gui_NetworkPorts_ReloadData")


; ==================================================================================================================================
Gui_NetworkPorts_CtrlEvt(CtrlHwnd:=0, GuiEvent:="", EventInfo:="", ErrLvl:="") {
    Static DataArray := []
    Static IconObject := {}
    Static ImageListID := 0
    If (A_DefaultListView != "Gui_NetworkPorts_LV")
        Gui, ListView, Gui_NetworkPorts_LV
    GuiControlGet, ControlName, Name, %CtrlHwnd%
    If (ControlName = "Gui_NetworkPorts_ApplyFilter") {
        GuiControlGet, Gui_NetworkPorts_ApplyFilter
        LV_Delete()
        GuiControl, -Redraw, Gui_NetworkPorts_LV
        Loop % DataArray.Length() {
            Data := DataArray[A_Index]
            Port := Data.LocalPort
            If (InStr(Port, Gui_NetworkPorts_ApplyFilter))
                LV_Add("Icon" Data.IconIndex, Data.LocalPort, Data.ProcName, Data.PID)
        }
        GuiControl, +Redraw, Gui_NetworkPorts_LV
    } Else If (ControlName = "Gui_NetworkPorts_ReloadData") {
        LV_Delete()
        If (ImageListID)
            IL_Destroy(ImageListID)
        ImageListID := IL_Create(100, 10)
        LV_SetImageList(ImageListID)
        GuiControl, , Gui_NetworkPorts_ProgressBar, 0
        DataArray := GetExtendedTcpTable()
        DataArrayCount := DataArray.Length()
        Loop % DataArrayCount {
            GuiControl, , Gui_NetworkPorts_ProgressBar, % A_Index/DataArrayCount*100
            
            DataArray[A_Index].PID := DataArray[A_Index].OwningPid
            If (DataArray[A_Index].PID = 0)
                DataArray[A_Index].ProcName := "[System Process]"
            Else If (DataArray[A_Index].PID = 4)
                DataArray[A_Index].ProcName := "System"
            Else {
                DataArray[A_Index].FilePath := GetProcessFilePathByPID(DataArray[A_Index].PID)
                SplitPath, % DataArray[A_Index].FilePath, ProcessName
                If !ProcessName
                     WinGet, ProcessName, ProcessName, % "ahk_pid " DataArray[A_Index].PID
                ; TODO: find out why that's still not enough to get them all
                DataArray[A_Index].ProcName := ProcessName
                DataArray[A_Index].Exists := FileExist(DataArray[A_Index].FilePath)
            }
            
            Data := DataArray[A_Index]
            IconObjectId := Data.Exists ? Data.FilePath : "\\DELETED"
            If IconObject[IconObjectId]
                DataArray[A_Index].IconIndex := IconObject[IconObjectId]
            Else
                IconObject[IconObjectId] :=  DataArray[A_Index].IconIndex := IL_Add(ImageListID, "HICON:" . GetIconByPath(Data.FilePath, Data.FileExists))
        }
        Gui_NetworkPorts_CtrlEvt("Gui_NetworkPorts_ApplyFilter")
    } Else If (ControlName = "Gui_NetworkPorts_ReleasePort") {
        ;RowNumber := 0
        ;Loop {
        ;    RowNumber := LV_GetNext(RowNumber)
        ;    If !RowNumber
        ;         Break
        ;    LV_GetText(Port, RowNumber, 1)
        ;    LV_GetText(PID, RowNumber, 3)
        ;    
        ;    If PortClosed {
        ;        LV_GetText(Name, RowNumber, 2)
        ;        MsgBox, Error: Unable to release port %Port% used by %Name% (PID: %PID%)!
        ;    } Else {
        ;        i := 1
        ;        Loop % DataArray.Length() {
        ;            If (DataArray[i].Handle = Handle)
        ;                DataArray.RemoveAt(i)
        ;            Else
        ;                i++
        ;        }
        ;    }
        ;}
        ;Gui_NetworkPorts_CtrlEvt("Gui_NetworkPorts_ApplyFilter")
        MsgBox, Not implemented yet!
    } Else If (ControlName = "Gui_NetworkPorts_CloseProcess") {
        RowNumber := 0
        Loop {
            RowNumber := LV_GetNext(RowNumber)
            If !RowNumber
                 Break
            LV_GetText(PID, RowNumber, 3)
            Process, Close, %PID%
            ;Process, WaitClose, %PID%, 5 ;wait up to 5 secs until process closes
            ;If ErrorLevel {
            ;    LV_GetText(Name, RowNumber, 2)
            ;    MsgBox, Error: Unable to close %Name% (PID: %PID%)!
            ;Else {
                i := 1
                Loop % DataArray.Length() {
                    If (DataArray[i].PID = PID)
                        DataArray.RemoveAt(i)
                    Else
                        i++
                }
            ;}
        }
        Gui_NetworkPorts_CtrlEvt("Gui_NetworkPorts_ApplyFilter")
    }
}
; ==================================================================================================================================
Gui_FileHandles_CtrlEvt(CtrlHwnd:=0, GuiEvent:="", EventInfo:="", ErrLvl:="") {
    Static DataArray := []
    Static IconObject := {}
    Static ImageListID := 0
    If (A_DefaultListView != "Gui_FileHandles_LV")
        Gui, ListView, Gui_FileHandles_LV
    GuiControlGet, ControlName, Name, %CtrlHwnd%
    If (ControlName = "Gui_FileHandles_ApplyFilter") {
        GuiControlGet, Gui_FileHandles_ApplyFilter
        LV_Delete()
        GuiControl, -Redraw, Gui_FileHandles_LV
        Loop % DataArray.Length() {
            Data := DataArray[A_Index]
            FilePath := Data.FilePath ? Data.FilePath : Data.DevicePath
            If (InStr(FilePath, Gui_FileHandles_ApplyFilter))
                LV_Add("Icon" Data.IconIndex, FilePath, Data.ProcName, Data.PID, Data.Handle)
        }
        GuiControl, +Redraw, Gui_FileHandles_LV
    } Else If (ControlName = "Gui_FileHandles_ReloadData") {
        LV_Delete()
        If (ImageListID)
            IL_Destroy(ImageListID)
        ImageListID := IL_Create(1000, 100)
        LV_SetImageList(ImageListID)
        Callback := Func("FileHandleCallback")
        DataArray := GetAllFileHandleInfo(Callback)
        GuiControl, , Gui_FileHandles_ProgressBar, 0
        DataArrayCount := DataArray.Length()
        Loop % DataArrayCount {
            GuiControl, , Gui_FileHandles_ProgressBar, % A_Index/DataArrayCount*100
            Data := DataArray[A_Index]
            IconObjectId := Data.Exists ? Data.FilePath : "\\DELETED"
            If IconObject[IconObjectId]
                DataArray[A_Index].IconIndex := IconObject[IconObjectId]
            Else
                IconObject[IconObjectId] :=  DataArray[A_Index].IconIndex := IL_Add(ImageListID, "HICON:" . GetIconByPath(Data.FilePath, Data.FileExists))
        }
        Gui_FileHandles_CtrlEvt("Gui_FileHandles_ApplyFilter")
    } Else If (ControlName = "Gui_FileHandles_CloseHandle") {
        RowNumber := 0
        Loop {
            RowNumber := LV_GetNext(RowNumber)
            If !RowNumber
                 Break
            LV_GetText(Handle, RowNumber, 4)
            LV_GetText(PID, RowNumber, 3)
            
            ProcHandle := OpenProcess(PID, 0x40)
            HandleClosed := DuplicateObject(ProcHandle, 0, Handle, 0x1) ; Close handle
            
            If HandleClosed {
                LV_GetText(Path, RowNumber, 1)
                LV_GetText(Name, RowNumber, 2)
                MsgBox, Error: Unable to close %Name%'s (PID: %PID%) handle on "%Path%"!
            } Else {
                i := 1
                Loop % DataArray.Length() {
                    If (DataArray[i].Handle = Handle)
                        DataArray.RemoveAt(i)
                    Else
                        i++
                }
            }
        }
        Gui_FileHandles_CtrlEvt("Gui_FileHandles_ApplyFilter")
    } Else If (ControlName = "Gui_FileHandles_CloseProcess") {
        RowNumber := 0
        Loop {
            RowNumber := LV_GetNext(RowNumber)
            If !RowNumber
                Break
            LV_GetText(PID, RowNumber, 3)
            Process, Close, %PID%
            ;Process, WaitClose, %PID%, 5 ;wait up to 5 secs until process closes
            ;If ErrorLevel {
            ;    LV_GetText(Name, RowNumber, 2)
            ;    MsgBox, Error: Unable to close %Name% (PID: %PID%)!
            ;Else {
                i := 1
                Loop % DataArray.Length() {
                    If (DataArray[i].PID = PID)
                        DataArray.RemoveAt(i)
                    Else
                        i++
                }
            ;}
        }
        Gui_FileHandles_CtrlEvt("Gui_FileHandles_ApplyFilter")
    }
}
; ==================================================================================================================================
FileHandleCallback(PercentDone) {
    GuiControl, , Gui_FileHandles_ProgressBar, %PercentDone%
}
; ==================================================================================================================================
LoadLibraries() {
    DllCall("LoadLibrary", "Str", "Advapi32.dll", "UPtr")
    DllCall("LoadLibrary", "Str", "Ntdll.dll", "UPtr")
    DllCall("LoadLibrary", "Str", "Shell32.dll", "UPtr")
    DllCall("LoadLibrary", "Str", "Iphlpapi.dll", "UPtr")
    DllCall("LoadLibrary", "Str", "psapi.dll", "UPtr")
}
; ==================================================================================================================================
GuiClose(Hwnd){
    ExitApp
}

; ==================================================================================================================================
; General functions that can simply be used in other scripts =======================================================================
; ==================================================================================================================================
GetProcessFilePath(hProcess) {
    nSize := VarSetCapacity(lpFilename, 260 * (A_IsUnicode ? 2 : 1), 0)
    If !(DllCall("GetModuleFileNameEx", "Ptr", hProcess, "Ptr", 0, "Str", lpFilename, "UInt", nSize))
        If !(DllCall("psapi.dll\GetModuleFileNameEx", "Ptr", hProcess, "Ptr", 0, "Str", lpFilename, "UInt", nSize))
            Return (ErrorLevel := 2) & 0
    Return lpFilename
}
; ==================================================================================================================================
GetProcessFilePathByPID(PID) {
    If !(hProcess := DllCall("OpenProcess", "UInt", 0x10|0x400, "Int", 0, "UInt", PID, "UPtr"))
        Return (ErrorLevel := 1) & 0
    lpFilename := GetProcessFilePath(hProcess)
    DllCall("CloseHandle", "Ptr", hProcess)
    Return lpFilename
}
; ==================================================================================================================================
GetExtendedTcpTable() {
    ; https://msdn.microsoft.com/en-us/library/aa365928.aspx
    Static AF_INET := 2, TCP_TABLE_OWNER_PID_ALL := 5
    DllCall("Iphlpapi.dll\GetExtendedTcpTable", "Ptr", 0, "UInt*", pdwSize, "Int", 0, "UInt", AF_INET, "UInt", TCP_TABLE_OWNER_PID_ALL, "UInt", 0)
    VarSetCapacity(pTcpTable, pdwSize, 0)
    If (DllCall("Iphlpapi.dll\GetExtendedTcpTable", "Ptr", &pTcpTable, "UInt*", pdwSize, "Int", 0, "UInt", AF_INET, "UInt", TCP_TABLE_OWNER_PID_ALL, "UInt", 0) != 0)
        Return (ErrorLevel := 1) & 0
 
    Offset := 0, TcpTable := []
    Loop % NumGet(pTcpTable, "UInt") {
        TcpTable[A_Index, "State"] := NumGet(&pTcpTable + (Offset+=4), "UInt")
        TcpTable[A_Index, "LocalAddr"] := NumGet(&pTcpTable + (Offset+=4), "UInt")
        TcpTable[A_Index, "LocalPort"] := NumGet(&pTcpTable + (Offset+=4), "UInt")
        TcpTable[A_Index, "RemoteAddr"] := NumGet(&pTcpTable + (Offset+=4), "UInt")
        TcpTable[A_Index, "RemotePort"] := NumGet(&pTcpTable + (Offset+=4), "UInt")
        TcpTable[A_Index, "OwningPid"] := NumGet(&pTcpTable + (Offset+=4), "UInt")
    }
    Return TcpTable
}
; ==================================================================================================================================
;SetScrollInfo(hwnd, ScrollInfoObj, fnBar:=1, fRedraw:=True) {
;    ; NOT SUPPORTED ON WINDOWS XP
;    ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb787583%28v=vs.85%29.aspx
;    VarSetCapacity(SCROLLINFO, ScrollInfoObj.Size, 0)
;    NumPut(ScrollInfoObj.Size, SCROLLINFO, 0, "UInt") 
;    NumPut(ScrollInfoObj.Mask, SCROLLINFO, 4, "UInt")
;    NumPut(ScrollInfoObj.Min, SCROLLINFO, 8, "Int")
;    NumPut(ScrollInfoObj.Max, SCROLLINFO, 12, "Int")
;    NumPut(ScrollInfoObj.Page, SCROLLINFO, 16, "UInt")
;    NumPut(ScrollInfoObj.Pos, SCROLLINFO, 20, "Int")
;    NumPut(ScrollInfoObj.TrackPos, SCROLLINFO, 24, "Int")
;    Return DllCall("User32.dll\SetScrollInfo", "Ptr", hwnd, "Int", fnBar, "Ptr", &SCROLLINFO)
;}
;; ==================================================================================================================================
;GetScrollInfo(hwnd, fnBar:=1) {
;    ; NOT SUPPORTED ON WINDOWS XP
;    ; https://msdn.microsoft.com/en-us/library/windows/desktop/bb787583%28v=vs.85%29.aspx
;    VarSetCapacity(SCROLLINFO, 28, 0)
;    NumPut(28, SCROLLINFO, 0, "UInt") 
;    NumPut(0x1F, SCROLLINFO, 4, "UInt") ; SIF_ALL
;    If !DllCall("User32.dll\GetScrollInfo", "Ptr", hwnd, "Int", fnBar, "Ptr", &SCROLLINFO)
;        Return False
;
;    ScrollInfoObj := {}
;    ScrollInfoObj.Size := NumGet(SCROLLINFO, 0, "UInt")
;    ScrollInfoObj.Mask := NumGet(SCROLLINFO, 4, "UInt")
;    ScrollInfoObj.Min := NumGet(SCROLLINFO, 8, "Int")
;    ScrollInfoObj.Max := NumGet(SCROLLINFO, 12, "Int")
;    ScrollInfoObj.Page := NumGet(SCROLLINFO, 16, "UInt")
;    ScrollInfoObj.Pos  := NumGet(SCROLLINFO, 20, "Int")
;    ScrollInfoObj.TrackPos := NumGet(SCROLLINFO, 24, "Int")
;
;    Return ScrollInfoObj
;}
; ==================================================================================================================================
OpenProcess(PID := 0, Privileges := -1) {
    Return DllCall("OpenProcess", "Uint", (Privileges = -1) ? 0x1F0FFF : Privileges, "Uint", False, "Uint", PID ? PID : DllCall("GetCurrentProcessId"))
} 
; ==================================================================================================================================
GetAllFileHandleInfo(Callback:="") {
    Static hCurrentProc := DllCall("GetCurrentProcess", "UPtr")
    DataArray := []
    If !(SHI := QuerySystemHandleInformation()) {
        MsgBox, 16, Error!, % "Couldn't get SYSTEM_HANDLE_INFORMATION`nLast Error: " . Format("0x{:08X}", ErrorLevel)
        Return False
    }
    HandleCount := SHI.Count
    Loop %HandleCount% {
        ; PROCESS_DUP_HANDLE = 0x40, PROCESS_QUERY_INFORMATION = 0x400
        If !(hProc := DllCall("OpenProcess", "UInt", 0x0440, "UInt", 0, "UInt", SHI[A_Index, "PID"], "UPtr"))
            Continue
        ; DUPLICATE_SAME_ATTRIBUTES = 0x04 (4)
        If !(hObject := DuplicateObject(hProc, hCurrentProc, SHI[A_Index, "Handle"], 4)) {
            DllCall("CloseHandle", "Ptr", hProc)
            Continue
        }
        If (OBI := QueryObjectBasicInformation(hObject))
        && (OTI := QueryObjectTypeInformation(hObject))
        && (OTI.Type = "File")
        && (DllCall("GetFileType", "Ptr", hObject, "UInt") = 1)
        && (ONI := QueryObjectNameInformation(hObject)) {
            ; VarSetCapacity(ProcFullPath, 520, 0)
            ; DllCall("QueryFullProcessImageName", "Ptr", hProc, "UInt", 0, "Str", ProcFullPath, "UIntP", sz := 260) ; NOT COMPATIBLE WITH WINDOWS XP
            
            FilePath := GetPathNameByHandle(hObject)
            Data := {}
            Data.ProcFullPath := GetProcessFilePath(hProc)
            Data.PID := SHI[A_Index].PID
            Data.Handle := SHI[A_Index].Handle
            Data.GrantedAccess := SHI[A_Index].Access
            Data.Flags := SHI[A_Index].Flags
            Data.Attributes := OBI.Attr
            Data.HandleCount := (OBI.Handles - 1)
            Data.DevicePath := ONI.Name
            Data.FilePath := FilePath
            Data.Drive := SubStr(FilePath, 1, 1)
            FileExists := FileExist(FilePath)
            Data.Exists := FileExists ? True : False
            Data.Isfolder := InStr(FileExists, "D") ? True : False
            SplitPath, ProcFullPath, ProcName
            Data.ProcName := ProcName
        
            ProgressInPercent := A_Index/HandleCount*100
            If Callback
                Callback.Call(ProgressInPercent)
            
            DataArray.Push(Data)
        }
        DllCall("CloseHandle", "Ptr", hObject)
        DllCall("CloseHandle", "Ptr", hProc)
    }
    If Callback
        Callback.Call(100)
    Return DataArray
}
; ==================================================================================================================================
GetIconByPath(Path, FileExists:="") { ; fully qualified file path, result of FileExist on Path (optional)
    ; SHGetFileInfo  -> http://msdn.microsoft.com/en-us/library/bb762179(v=vs.85).aspx
    ; FIXME:
    ;     For 32-bit AHK File System Redirection is automatically enabled when running on a 64-bit OS. 
    ;     So files which exist in Sytem32 (64-bit) but not in SysWOW64 (32-bit) won't be found. 
    ;     Also, all files which exist in both directories might address the wrong file. 
    ;     So the file redirection must be disabled in this case (A_Is64bitOS && (A_PtrSize = 4)).
    Static AW := A_IsUnicode ? "W" : "A"
    Static cbSFI := A_PtrSize + 8 + (340 << !!A_IsUnicode)
    Static IconType := 2
    FileExists := FileExists ? FileExists : FileExist(Path)
    If (FileExists) {
        SplitPath, Path, , , FileExt
        If (InStr(FileExists, "D") || FileExt = "exe" || FileExt = "ico" || FileExt = "") {
            pszPath := Path
            dwFileAttributes := 0x00
            uFlags := 0x0101
        } Else {
            pszPath := "." FileExt
            dwFileAttributes := 0x80
            uFlags := 0x0111
        }
    } Else ; If the file is deleted reutrn an appropriate icon. 
        Return LoadPicture(A_WinDir "\System32\imageres.dll", "Icon85 w16 h16", IconType) ; TODO: find a way to retrieve the icon just once and return it everytime it is needed
        ;TODO: maybe remove this because other scripts might not want to get this icon when the file is not existent
    
    VarSetCapacity(SFI, cbSFI, 0) ; SHFILEINFO
    DllCall("Shell32.dll\SHGetFileInfo" . AW, "Str", pszPath, "UInt", dwFileAttributes, "Ptr", &SFI, "UInt", cbSFI, "UInt", uFlags, "UInt")
    Return NumGet(SFI, 0, "UPtr")
}
; ==================================================================================================================================
GetPathNameByHandle(hFile) {
    VarSetCapacity(FilePath, 4096, 0)
    DllCall("GetFinalPathNameByHandle", "Ptr", hFile, "Str", FilePath, "UInt", 2048, "UInt", 0, "UInt")
    Return SubStr(FilePath, 1, 4) = "\\?\" ? SubStr(FilePath, 5) : FilePath
}
; ==================================================================================================================================
DuplicateObject(hProc, hCurrentProc, Handle, Options) {
    ; PROCESS_DUP_HANDLE = 0x40, PROCESS_QUERY_INFORMATION = 0x400, DUPLICATE_SAME_ATTRIBUTES = 0x04 (4)
    Status := DllCall("Ntdll.dll\ZwDuplicateObject", "Ptr", hProc
                                                   , "Ptr", Handle
                                                   , "Ptr", hCurrentProc
                                                   , "PtrP", hObject
                                                   , "UInt", 0
                                                   , "UInt", 0
                                                   , "UInt", Options
                                                   , "UInt")
    Return (Status) ? !(ErrorLevel := Status) : hObject
}
; ==================================================================================================================================
QueryObjectBasicInformation(hObject) {
    ; ObjectBasicInformation = 0, STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
    Static Size := 56 ; size of OBJECT_BASIC_INFORMATION
    VarSetCapacity(OBI, Size, 0)
    Status := DllCall("Ntdll.dll\ZwQueryObject", "Ptr", hObject, "UInt", 0, "Ptr", &OBI, "UInt", Size, "UIntP", L, "UInt")
    If (Status = 0xC0000004) {
        VarSetCapacity(OBI, L)
        Status := DllCall("Ntdll.dll\ZwQueryObject", "Ptr", hObject, "UInt", 0, "Ptr", &OBI, "UInt", L, "Ptr", 0, "UInt")
    }
    Return (Status) ? !(ErrorLevel := Status)
                    : {Attr: NumGet(OBI, 0, "UInt")
                       , Access: NumGet(OBI, 4, "UInt")
                       , Handles: NumGet(OBI, 8, "UInt")
                       , Pointers: NumGet(OBI, 12, "UInt")}
}
; ==================================================================================================================================
QueryObjectTypeInformation(hObject, Size := 4096) {
    ; ObjectTypeInformation = 2, STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
    VarSetCapacity(OTI, Size, 0)
    Status := DllCall("Ntdll.dll\ZwQueryObject", "Ptr", hObject, "UInt", 2, "Ptr", &OTI, "UInt", Size, "UIntP", L, "UInt")
    If (Status = 0xC0000004) {
        VarSetCapacity(OTI, L)
        Status := DllCall("Ntdll.dll\ZwQueryObject", "Ptr", hObject, "UInt", 2, "Ptr", &OTI, "UInt", L, "Ptr", 0, "UInt")
    }
    Return (Status) ? !(ErrorLevel := Status)
                    : {Type: StrGet(NumGet(OTI, A_PtrSize, "UPtr"), NumGet(OTI, 0, "UShort") // 2, "UTF-16")}
}
; ==================================================================================================================================
QueryObjectNameInformation(hobject, Size := 4096) {
    ; ObjectNameInformation = 1, STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
    VarSetCapacity(ONI, Size, 0)
    Status := DllCall("Ntdll.dll\ZwQueryObject", "Ptr", hObject, "UInt", 1, "Ptr", &ONI, "UInt", Size, "UIntP", L, "UInt")
    If (Status = 0xc0000004) {
        VarSetCapacity(ONI, L)
        Status := DllCall("Ntdll.dll\ZwQueryObject", "Ptr", hObject, "UInt", 1, "Ptr", &ONI, "UInt", L, "Ptr", 0, "UInt")
    }
    Return (Status) ? !(ErrorLevel := Status)
                    : {Name: StrGet(NumGet(ONI, A_PtrSize, "UPtr"), NumGet(ONI, 0, "UShort") // 2, "UTF-16")}
}
; ==================================================================================================================================
QuerySystemHandleInformation() {
    ; SystemHandleInformation = 16, STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
    Static SizeSH := 8 + (A_PtrSize * 2)
    Static Size := A_PtrSize * 4096
    VarSetCapacity(SHI, Size)
    Status := DllCall("Ntdll.dll\NtQuerySystemInformation", "UInt", 16, "Ptr", &SHI, "UInt", Size, "UIntP", L, "UInt")
    While (Status = 0xc0000004) {
        VarSetCapacity(SHI, L)
        Status := DllCall("Ntdll.dll\NtQuerySystemInformation", "UInt", 16, "Ptr", &SHI, "UInt", L, "UIntP", L, "UInt")
    }
    If (Status)
        Return !(ErrorLevel := Status)
    HandleCount := NumGet(SHI, "UInt")
    ObjSHI := {Count: HandleCount}
    Addr := &SHI + A_PtrSize
    Loop, %HandleCount% {
        ObjSHI.Push({PID: NumGet(Addr + 0, "UInt")
                   , Type: NumGet(Addr + 4, "UChar")
                   , Flags: NumGet(Addr + 5, "UChar")
                   , Handle: NumGet(Addr + 6, "UShort")
                   , Addr: NumGet(Addr + 8, "UPtr")
                   , Access: NumGet(Addr + 8, A_PtrSize, "UInt")})
        Addr += SizeSH
    }
    Return ObjSHI
}
; ==================================================================================================================================
EnablePrivilege(Name := "SeDebugPrivilege") {
    hProc := DllCall("GetCurrentProcess", "UPtr")
    If DllCall("Advapi32.dll\LookupPrivilegeValue", "Ptr", 0, "Str", Name, "Int64P", LUID := 0, "UInt")
    && DllCall("Advapi32.dll\OpenProcessToken", "Ptr", hProc, "UInt", 32, "PtrP", hToken := 0, "UInt") { ; TOKEN_ADJUST_PRIVILEGES = 32
        VarSetCapacity(TP, 16, 0) ; TOKEN_PRIVILEGES
        , NumPut(1, TP, "UInt")
        , NumPut(LUID, TP, 4, "UInt64")
        , NumPut(2, TP, 12, "UInt") ; SE_PRIVILEGE_ENABLED = 2
        , DllCall("Advapi32.dll\AdjustTokenPrivileges", "Ptr", hToken, "UInt", 0, "Ptr", &TP, "UInt", 0, "Ptr", 0, "Ptr", 0, "UInt")
    }
    LastError := A_LastError
    If (hToken)
        DllCall("CloseHandle", "Ptr", hToken)
    Return !(ErrorLevel := LastError)
}
; ==================================================================================================================================
RunAsAdmin() {
    If !(A_IsAdmin) {
        Run % "*RunAs " . (A_IsCompiled ? "" : A_AhkPath . " ") . """" . A_ScriptFullPath . """"
        ExitApp
    }
}
Image
Image
Image
Image

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 14 Apr 2016, 08:00
by Bruttosozialprodukt
Thanks to "just me" the script now runs on AHK_L! :D

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 14 Apr 2016, 09:45
by just me
What's AHK_L? Do you mean AHK 1.1? ;)

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 14 Apr 2016, 10:15
by Bruttosozialprodukt
Oh, I didn't realize.. I meant 1.1 of course. :D

Wow

Posted: 14 Apr 2016, 16:18
by Best-Code-in-Use
Looks pretty cool ;-) The Ideas for the next Releases are very interesting...
Thanks for sharing...

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 05:01
by Bruttosozialprodukt
Changelog:
Improved loading speed significantly.
Added functionality to close any handle you want.
Added functionality to close any process you want.
Some other bugfixes.

Known bugs:
When using the reload button some icons disappear.
Scroll position resets itself to 0 when closing handles/processes.

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 16:21
by Bruttosozialprodukt
Changelog:
Gui is made out of 2 tabs now: "File Handles" and "Network Ports"
The Network Ports tab contains new functionality:
-Shows a list of all tcp ports that are being listened on.
-Shows which process is listening.
-Allows to close any of the processes.

Known bugs:
When using the reload button some icons disappear.
Scroll position resets itself to 0 when closing handles/processes.
The network port list view is not able to retrieve all process names properly and also fails to load icons for some processes.
It also only shows tcp ports, no udp ports.

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 16:50
by Xatmo
This seems to stop responding about 25% in on loading on my old windows XP laptop i have tried with updated AHK_L but still Stops not sure why xD

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 17:01
by Bruttosozialprodukt
I might have have accidentally used a WinAPI call that is not supported by Windows XP. I'd have to check later.
I assume you have the latest service packs installed? There is at least one function that requires SP2.

Edit:
QueryFullProcessImageName and GetFinalPathNameByHandle
are not supported on XP. I'll have to find alternatives for them later.

My ScrollBar functions neither (fortunately they are not actually used in the script yet).

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 17:10
by Xatmo
Yeah. Win XP SP3 Installed no rush to get it to work on XP lol .Just thought id let you know tho. It could be that i just have a service disabled that it uses

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 17:15
by Xatmo
Oh ok. Yeah no rush for win XP i just happened to be on here when i tried it xD

Re: Reveal processes responsible for locking a file (keeping USB devices from ejecting / files from being moved and dele

Posted: 16 Apr 2016, 17:21
by Bruttosozialprodukt
Thanks for reporting though! I usually try my best to support anything down to Windows XP.

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 18 Apr 2016, 09:11
by Bruttosozialprodukt
Changelog:
Added code for XP compatibility.
Cleaned up some functions.
(Hopefully) fixed icon problems in the File Handles tab.

Known bugs:
When using the reload button some icons disappear.
Scroll position resets itself to 0 when closing handles/processes.
Using the 32bit version, the network port list view is not able to retrieve all process names properly and also fails to load icons for some processes.
It also only shows tcp ports, no udp ports.
Probably still not fully XP compatible.

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 19 Apr 2016, 01:25
by Xatmo
Hello i retried the updated code for Win xp and the result is the same it freezes with the loading bar around 25% of the way in GUI loads up but after putting in some debug MsgBoxs i see that this function never finishes so somewhere in that function does not work. I am not sure if it has to do with some services i have disable or if it is indeed that function thats not compatible with Win XP

Function:
Gui_FileHandles_CtrlEvt("Gui_FileHandles_ReloadData")

MsgBox Before this function works.
MsgBox After this function Fails

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 19 Apr 2016, 04:37
by Bruttosozialprodukt
Okay, thanks for reporting. I'll set up a Windows XP VM and do some more debugging.

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 04 Feb 2017, 15:12
by jeeswg
I'm using Windows 7 and I had the same problem,
'it freezes with the loading bar around 25% of the way' (or perhaps 33%).
I tried running it with AHK v1.1 32-bit, and AHK v1.1 64-bit.

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 22 Feb 2017, 08:02
by Bruttosozialprodukt
I'm currently working on other projects. I will get back to this project at some point, but I can't say when that is yet.

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 22 Feb 2017, 08:14
by jeeswg
Cheers, that's great to hear. No worries, I know what it's like!

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 24 Feb 2017, 04:40
by aaffe
For me it stops at 25% too. Have Windows 10 64bit

Re: WhoLockedMe - Reveal processes locking files / blocking ports and release them with a simple click

Posted: 24 Feb 2017, 05:15
by qwerty12
(I don't know why this doesn't work on some Windows 7 and Windows 10 machines - it works fine for me here on Windows 10 64-bit 14393, but then again I avoid antivirus programs like the plague - but for the XP issues, give this a read, which has quite a few workarounds for XP's hanging when NtQueryObject is called on some named pipes' handles.)