forked from Github/Axter-Stash
Too many changes to list
This commit is contained in:
@@ -17,7 +17,7 @@ Example Usage:
|
||||
of.closeFile(r"B:\V\V\testdup\deleme2.mp4")
|
||||
|
||||
"""
|
||||
import ctypes, os, sys, psutil, argparse, traceback, logging, numbers, string
|
||||
import ctypes, os, sys, argparse, traceback, logging, numbers, string
|
||||
from ctypes import wintypes
|
||||
# from StashPluginHelper import StashPluginHelper
|
||||
# Look at the following links to enhance this code:
|
||||
@@ -30,8 +30,8 @@ from ctypes import wintypes
|
||||
# getPid is the only function which does NOT require elevated admin privileges.
|
||||
class openedFile():
|
||||
# generic strings and constants
|
||||
ntdll = ctypes.WinDLL('ntdll')
|
||||
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
|
||||
ntdll = None
|
||||
kernel32 = None
|
||||
NTSTATUS = wintypes.LONG
|
||||
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
|
||||
FILE_READ_ATTRIBUTES = 0x80
|
||||
@@ -51,57 +51,62 @@ class openedFile():
|
||||
self.stash = stash
|
||||
if handleExe == None or handleExe == "" or not os.path.isfile(handleExe):
|
||||
raise Exception(f"handleExe requires a valid path to Sysinternals 'handle.exe' or 'handle64.exe' executable. Can be downloaded from following link:\nhttps://learn.microsoft.com/en-us/sysinternals/downloads/handle")
|
||||
# create handle on concerned file with dwDesiredAccess == self.FILE_READ_ATTRIBUTES
|
||||
self.kernel32.CreateFileW.restype = wintypes.HANDLE
|
||||
self.kernel32.CreateFileW.argtypes = (
|
||||
wintypes.LPCWSTR, # In lpFileName
|
||||
wintypes.DWORD, # In dwDesiredAccess
|
||||
wintypes.DWORD, # In dwShareMode
|
||||
self.LPSECURITY_ATTRIBUTES, # In_opt lpSecurityAttributes
|
||||
wintypes.DWORD, # In dwCreationDisposition
|
||||
wintypes.DWORD, # In dwFlagsAndAttributes
|
||||
wintypes.HANDLE) # In_opt hTemplateFile
|
||||
if self.stash != None and self.stash.IS_WINDOWS:
|
||||
self.ntdll = ctypes.WinDLL('ntdll')
|
||||
self.kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
|
||||
# create handle on concerned file with dwDesiredAccess == self.FILE_READ_ATTRIBUTES
|
||||
self.kernel32.CreateFileW.restype = wintypes.HANDLE
|
||||
self.kernel32.CreateFileW.argtypes = (
|
||||
wintypes.LPCWSTR, # In lpFileName
|
||||
wintypes.DWORD, # In dwDesiredAccess
|
||||
wintypes.DWORD, # In dwShareMode
|
||||
self.LPSECURITY_ATTRIBUTES, # In_opt lpSecurityAttributes
|
||||
wintypes.DWORD, # In dwCreationDisposition
|
||||
wintypes.DWORD, # In dwFlagsAndAttributes
|
||||
wintypes.HANDLE) # In_opt hTemplateFile
|
||||
|
||||
def getPid(self, path):
|
||||
self.lastPath = path
|
||||
hFile = self.kernel32.CreateFileW(
|
||||
path, self.FILE_READ_ATTRIBUTES, self.FILE_SHARE_READ, None, self.OPEN_EXISTING,
|
||||
self.FILE_FLAG_BACKUP_SEMANTICS, None)
|
||||
if hFile == self.INVALID_HANDLE_VALUE:
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
# prepare data types for system call
|
||||
class IO_STATUS_BLOCK(ctypes.Structure):
|
||||
class _STATUS(ctypes.Union):
|
||||
_fields_ = (('Status', self.NTSTATUS),
|
||||
('Pointer', wintypes.LPVOID))
|
||||
_anonymous_ = '_Status',
|
||||
_fields_ = (('_Status', _STATUS),
|
||||
('Information', self.ULONG_PTR))
|
||||
iosb = IO_STATUS_BLOCK()
|
||||
class FILE_PROCESS_IDS_USING_FILE_INFORMATION(ctypes.Structure):
|
||||
_fields_ = (('NumberOfProcessIdsInList', wintypes.LARGE_INTEGER),
|
||||
('ProcessIdList', wintypes.LARGE_INTEGER * 64))
|
||||
info = FILE_PROCESS_IDS_USING_FILE_INFORMATION()
|
||||
PIO_STATUS_BLOCK = ctypes.POINTER(IO_STATUS_BLOCK)
|
||||
self.ntdll.NtQueryInformationFile.restype = self.NTSTATUS
|
||||
self.ntdll.NtQueryInformationFile.argtypes = (
|
||||
wintypes.HANDLE, # In FileHandle
|
||||
PIO_STATUS_BLOCK, # Out IoStatusBlock
|
||||
wintypes.LPVOID, # Out FileInformation
|
||||
wintypes.ULONG, # In Length
|
||||
self.FILE_INFORMATION_CLASS) # In FileInformationClass
|
||||
# system call to retrieve list of PIDs currently using the file
|
||||
status = self.ntdll.NtQueryInformationFile(hFile, ctypes.byref(iosb),
|
||||
ctypes.byref(info),
|
||||
ctypes.sizeof(info),
|
||||
self.FileProcessIdsUsingFileInformation)
|
||||
pidList = info.ProcessIdList[0:info.NumberOfProcessIdsInList]
|
||||
if len(pidList) > 0:
|
||||
return pidList
|
||||
# ToDo: Add Linux implementation
|
||||
if self.stash != None and self.stash.IS_WINDOWS:
|
||||
hFile = self.kernel32.CreateFileW(
|
||||
path, self.FILE_READ_ATTRIBUTES, self.FILE_SHARE_READ, None, self.OPEN_EXISTING,
|
||||
self.FILE_FLAG_BACKUP_SEMANTICS, None)
|
||||
if hFile == self.INVALID_HANDLE_VALUE:
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
# prepare data types for system call
|
||||
class IO_STATUS_BLOCK(ctypes.Structure):
|
||||
class _STATUS(ctypes.Union):
|
||||
_fields_ = (('Status', self.NTSTATUS),
|
||||
('Pointer', wintypes.LPVOID))
|
||||
_anonymous_ = '_Status',
|
||||
_fields_ = (('_Status', _STATUS),
|
||||
('Information', self.ULONG_PTR))
|
||||
iosb = IO_STATUS_BLOCK()
|
||||
class FILE_PROCESS_IDS_USING_FILE_INFORMATION(ctypes.Structure):
|
||||
_fields_ = (('NumberOfProcessIdsInList', wintypes.LARGE_INTEGER),
|
||||
('ProcessIdList', wintypes.LARGE_INTEGER * 64))
|
||||
info = FILE_PROCESS_IDS_USING_FILE_INFORMATION()
|
||||
PIO_STATUS_BLOCK = ctypes.POINTER(IO_STATUS_BLOCK)
|
||||
self.ntdll.NtQueryInformationFile.restype = self.NTSTATUS
|
||||
self.ntdll.NtQueryInformationFile.argtypes = (
|
||||
wintypes.HANDLE, # In FileHandle
|
||||
PIO_STATUS_BLOCK, # Out IoStatusBlock
|
||||
wintypes.LPVOID, # Out FileInformation
|
||||
wintypes.ULONG, # In Length
|
||||
self.FILE_INFORMATION_CLASS) # In FileInformationClass
|
||||
# system call to retrieve list of PIDs currently using the file
|
||||
status = self.ntdll.NtQueryInformationFile(hFile, ctypes.byref(iosb),
|
||||
ctypes.byref(info),
|
||||
ctypes.sizeof(info),
|
||||
self.FileProcessIdsUsingFileInformation)
|
||||
pidList = info.ProcessIdList[0:info.NumberOfProcessIdsInList]
|
||||
if len(pidList) > 0:
|
||||
return pidList
|
||||
return None
|
||||
|
||||
def isAdmin(self):
|
||||
if os.name=='nt':
|
||||
if self.stash != None and self.stash.IS_WINDOWS:
|
||||
try:
|
||||
return ctypes.windll.shell32.IsUserAnAdmin()
|
||||
except:
|
||||
@@ -112,7 +117,7 @@ class openedFile():
|
||||
def runMeAsAdmin(self):
|
||||
if self.isAdmin() == True:
|
||||
return
|
||||
if os.name=='nt':
|
||||
if self.stash != None and self.stash.IS_WINDOWS:
|
||||
# Below is a Windows only method which does NOT popup a console.
|
||||
import win32com.shell.shell as shell # Requires: pip install pywin32
|
||||
script = os.path.abspath(sys.argv[0])
|
||||
@@ -130,6 +135,7 @@ class openedFile():
|
||||
return filename
|
||||
|
||||
def getFilesOpen(self, pid:int): # Requires running with admin privileges.
|
||||
import psutil # Requires: pip install psutil
|
||||
p = psutil.Process(pid1)
|
||||
return p.open_files()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user