Autoit如何通过进程PID检索进程打开的文件路径
Autoit How to retrieve file path opened by process by process PID
我想获取某个进程打开的某个文件的完整路径
例如:由 paint 打开的图像或在我的情况下多个记事本进程是 运行 我得到了每个 notepad.exe 进程的 PID 所以当使用
_ProcessGetPath
我得到的是 notepad.exe 的路径,而不是进程打开的 file.txt 的路径,现在如何检索 txt 文件路径?
Credits go to the authors of AutoIt Unlocker!
#NoTrayIcon
#include "WinAPIEx.au3"
#include <WinAPI.au3>
Dim $hTimer = TimerInit()
Dim $aFiles = _ProcessListFiles("firefox.exe") ; Get a list of files currently opened by the process
ConsoleWrite("+>Took " & Round(TimerDiff($hTimer)) & " milliseconds" & @CRLF)
#include <Array.au3>
_ArrayDisplay($aFiles)
Exit
Func _ProcessListFiles($vProcess, $nMaxFiles = 1000)
Static Local $aPrivilege = DllCall("ntdll.dll", "int", "RtlAdjustPrivilege", "int", 20, "int", 1, "int", 0, "int*", 0)
Local $nProcessId = ProcessExists($vProcess), $aRet
Static Local $hCurrentProcess = _WinAPI_GetCurrentProcess()
Local $aHandles = _WinAPI_EnumProcessHandles($nProcessId)
Local $hObject, $aFiles[$nMaxFiles+1], $sPath
Local $hProcess = _WinAPI_OpenProcess(0x0040, 0, $nProcessId, True)
For $i = 1 To $aHandles[0][0] Step 1
If $aHandles[$i][3] = 0x00120189 Or $aHandles[$i][3] = 0x0012019f Or $aHandles[$i][3] = 0x00100000 Then ContinueLoop
$hObject = _WinAPI_DuplicateHandle($hProcess, $aHandles[$i][0], $hCurrentProcess, 0, False, $DUPLICATE_SAME_ACCESS)
If Not $hObject Then ContinueLoop
If __IsFileObject($hObject) Then
$sPath = __FileObjectPath($hObject)
_WinAPI_CloseHandle($hObject)
If FileExists($sPath) Then
For $n = 1 To $aFiles[0]
If $aFiles[$n] = $sPath Then
$sPath = 0
ExitLoop
EndIf
Next
If $sPath Then
$aFiles[0] += 1
$aFiles[$aFiles[0]] = $sPath
If $aFiles[0] >= $nMaxFiles Then ExitLoop
EndIf
EndIf
EndIf
Next
ReDim $aFiles[$aFiles[0]+1]
Return $aFiles
EndFunc
Func __IsFileObject(ByRef $hObject)
Static Local $tPOTI = DllStructCreate('ushort;ushort;ptr;byte[128]'), $pData, $Length, $tString
Local $aRet = DllCall("ntdll.dll", 'uint', 'NtQueryObject', 'ptr', $hObject, 'uint', 2, 'ptr', DllStructGetPtr($tPOTI), 'ulong', DllStructGetSize($tPOTI), 'ptr', 0)
If @error Or $aRet[0] Then Return
$pData = DllStructGetData($tPOTI, 3)
If Not $pData Then Return
$Length = DllCall("kernel32.dll", 'int', 'lstrlenW', 'ptr', $pData)
If @error Or Not $Length[0] Then Return
$Length = $Length[0]
$tString = DllStructCreate('wchar[' & ($Length + 1) & ']', $pData)
If @error Then Return
Return (DllStructGetData($tString, 1) == "File")
EndFunc
Func __FileObjectPath($hObject)
Static Local $tStruct = DllStructCreate("char[255];")
Local $aDrive = DriveGetDrive("ALL"), $sPath
Local $aDrivesInfo[UBound($aDrive) - 1][2]
For $I = 0 To UBound($aDrivesInfo) - 1
$aDrivesInfo[$I][0] = $aDrive[$I + 1]
DllCall("kernel32.dll", "dword", "QueryDosDevice", "str", $aDrivesInfo[$I][0], "ptr", DllStructGetPtr($tStruct), "dword", 255)
$aDrivesInfo[$I][1] = DllStructGetData($tStruct, 1)
Next
Local Static $tPOTI = DllStructCreate("ushort Length;ushort MaximumLength;ptr Buffer;wchar Reserved[260];"), $sDeviceStr, $vSolid = False
DllCall("ntdll.dll", "ulong", "NtQueryObject", "ptr", $hObject, "int", 1, "ptr", DllStructGetPtr($tPOTI), "ulong", DllStructGetSize($tPOTI), "ulong*", "")
$sDeviceStr = DllStructGetData(DllStructCreate("wchar[" & Ceiling(DllStructGetData($tPOTI, "Length") / 2) & "];", DllStructGetData($tPOTI, "buffer")), 1)
For $y = 0 To UBound($aDrivesInfo) - 1
If StringLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1])) = $aDrivesInfo[$y][1] Then
$sPath = StringUpper($aDrivesInfo[$y][0]) & StringTrimLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1]))
EndIf
Next
Return $sPath
EndFunc
或尝试:
#NoTrayIcon
#include "WinAPIEx.au3"
#include <WinAPI.au3>
Dim $hTimer = TimerInit()
Dim $aFiles = _ProcessListFiles("wmplayer.exe") ; Get a list of files currently opened by the process
ConsoleWrite("+>Took " & Round(TimerDiff($hTimer)) & " milliseconds" & @CRLF)
#include <Array.au3>
_ArrayDisplay($aFiles)
Func _ProcessListFiles($vProcess, $nMaxFiles = 1000)
Static Local $aPrivilege = DllCall("ntdll.dll", "int", "RtlAdjustPrivilege", "int", 20, "int", 1, "int", 0, "int*", 0)
Local $nProcessId = ProcessExists($vProcess), $aRet
Static Local $hCurrentProcess = _WinAPI_GetCurrentProcess()
Local $aHandles = _WinAPI_EnumProcessHandles($nProcessId)
Local $hObject, $aFiles[$nMaxFiles+1], $sPath
Local $hProcess = _WinAPI_OpenProcess(0x0040, 0, $nProcessId, True)
For $i = 1 To $aHandles[0][0] Step 1
$hObject = _WinAPI_DuplicateHandle($hProcess, $aHandles[$i][0], $hCurrentProcess, 0, False, $DUPLICATE_SAME_ACCESS)
If Not $hObject Then ContinueLoop
If __IsFileObject($hObject) Then
If $aHandles[$i][3] = 0x00120189 Or $aHandles[$i][3] = 0x0012019f Or $aHandles[$i][3] = 0x00100000 Or $aHandles[$i][3] = 0x001F01FF Then
$sPath = __FileObjectPath_UD($hObject)
Else
$sPath = __FileObjectPath($hObject)
EndIf
_WinAPI_CloseHandle($hObject)
If FileExists($sPath) Then
For $n = 1 To $aFiles[0]
If $aFiles[$n] = $sPath Then
$sPath = 0
ExitLoop
EndIf
Next
If $sPath Then
$aFiles[0] += 1
$aFiles[$aFiles[0]] = $sPath
If $aFiles[0] >= $nMaxFiles Then ExitLoop
EndIf
EndIf
EndIf
Next
ReDim $aFiles[$aFiles[0]+1]
Return $aFiles
EndFunc
Func __IsFileObject(ByRef $hObject)
Static Local $tPOTI = DllStructCreate('ushort;ushort;ptr;byte[128]'), $pData, $Length, $tString
Local $aRet = DllCall("ntdll.dll", 'uint', 'NtQueryObject', 'ptr', $hObject, 'uint', 2, 'ptr', DllStructGetPtr($tPOTI), 'ulong', DllStructGetSize($tPOTI), 'ptr', 0)
If @error Or $aRet[0] Then Return
$pData = DllStructGetData($tPOTI, 3)
If Not $pData Then Return
$Length = DllCall("kernel32.dll", 'int', 'lstrlenW', 'ptr', $pData)
If @error Or Not $Length[0] Then Return
$Length = $Length[0]
$tString = DllStructCreate('wchar[' & ($Length + 1) & ']', $pData)
If @error Then Return
Return (DllStructGetData($tString, 1) == "File")
EndFunc
Func __FileObjectPath_UD($hObject)
Static Local $tStruct = DllStructCreate("char[255];")
Local $aDrive = DriveGetDrive("ALL"), $sPath
Local $aDrivesInfo[UBound($aDrive) - 1][2]
For $I = 0 To UBound($aDrivesInfo) - 1
$aDrivesInfo[$I][0] = $aDrive[$I + 1]
DllCall("kernel32.dll", "dword", "QueryDosDevice", "str", $aDrivesInfo[$I][0], "ptr", DllStructGetPtr($tStruct), "dword", 255)
$aDrivesInfo[$I][1] = DllStructGetData($tStruct, 1)
Next
$sDeviceStr = _ObjectGetNameUD_Threaded($hObject)
If Not $sDeviceStr Then Return
For $y = 0 To UBound($aDrivesInfo) - 1
If StringLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1])) = $aDrivesInfo[$y][1] Then
$sPath = StringUpper($aDrivesInfo[$y][0]) & StringTrimLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1]))
EndIf
Next
Return $sPath
EndFunc
Func __FileObjectPath($hObject)
Static Local $tStruct = DllStructCreate("char[255];")
Local $aDrive = DriveGetDrive("ALL"), $sPath
Local $aDrivesInfo[UBound($aDrive) - 1][2]
For $I = 0 To UBound($aDrivesInfo) - 1
$aDrivesInfo[$I][0] = $aDrive[$I + 1]
DllCall("kernel32.dll", "dword", "QueryDosDevice", "str", $aDrivesInfo[$I][0], "ptr", DllStructGetPtr($tStruct), "dword", 255)
$aDrivesInfo[$I][1] = DllStructGetData($tStruct, 1)
Next
Local Static $tPOTI = DllStructCreate("ushort Length;ushort MaximumLength;ptr Buffer;wchar Reserved[260];"), $sDeviceStr, $vSolid = False
DllCall("ntdll.dll", "ulong", "NtQueryObject", "ptr", $hObject, "int", 1, "ptr", DllStructGetPtr($tPOTI), "ulong", DllStructGetSize($tPOTI), "ulong*", "")
$sDeviceStr = DllStructGetData(DllStructCreate("wchar[" & Ceiling(DllStructGetData($tPOTI, "Length") / 2) & "];", DllStructGetData($tPOTI, "buffer")), 1)
For $y = 0 To UBound($aDrivesInfo) - 1
If StringLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1])) = $aDrivesInfo[$y][1] Then
$sPath = StringUpper($aDrivesInfo[$y][0]) & StringTrimLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1]))
EndIf
Next
Return $sPath
EndFunc
; ==============================================================================================
; Func _ObjectGetNameUD_Threaded($hObject)
;
; Gets the Name associated with a Kernel Object Handle.
; Most useful for 'File' Types
;
; This differs from _ObjectGetNameUD() in that it launches a thread to try and get the name
; If the thread times-out, it is killed.
;
; This is a workaround for the NamedPipes issue - often these types of Objects will be
; locked in reads/writes/waits for long periods of time and cause any type of querying
; attempts on the Object to lockup indefinitely.
;
; Returns:
; Success: String representing the name of the Object
; Failure: "" with @error set
;
; Author: Ascend4nt
; ==============================================================================================
Func _ObjectGetNameUD_Threaded($hObject)
Local $OGNT_CODE
;~ $aRet=DllCall("ntdll.dll", "long", "NtQueryObject", "handle", $hObject, "int", 1, _
;~ "ptr", DllStructGetPtr($stBuffer), "ulong", DllStructGetSize($stBuffer), "ulong*", 0)
If @AutoItX64 Then
$OGNT_CODE='0x4831C04889CE483906742D483946087427504883EC2049C7C1FF7F00004C8D461848C7C201000000488B4E08488B1EFFD34883C428894610C3'
Else
$OGNT_CODE='0x5589E531C08B750839067421394604741C50B8FF7F0000508D461050B801000000508B4604508B1EFFD38946085DC3'
EndIf
Local $aRet, $sStr = "", $iErr = 0, $iExt = 0, $stData
Local $stCode, $iCodeSize, $pThreadMem, $hThread = 0
If Not IsPtr($hObject) Or $hObject = 0 Then Return SetError(1,0,"")
$iCodeSize = BinaryLen($OGNT_CODE)
$aRet = DllCall("kernel32.dll", "ptr", "GetModuleHandleA", "str", "ntdll.dll")
If @error Then Return SetError(2, @error, "")
If $aRet[0] = 0 Then Return SetError(3, 0, "")
$aRet = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $aRet[0], "str", "NtQueryObject")
If @error Then Return SetError(2, @error, "")
If $aRet[0] = 0 Then Return SetError(3, 0, "")
;$pNTQO = $aRet[0]
; Data to receive (must be kept alive while thread exists!)
$stData = DllStructCreate("ptr NTQO;handle Object;ulong StatusRet;ulong StructPad;ushort Length;ushort MaximumLength;ptr Buffer;" & "byte [32768];")
DllStructSetData($stData, "Object", $hObject)
DllStructSetData($stData, "NTQO", $aRet[0]) ; $pNTQO
$aRet = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "handle", -1, _
"ptr", 0, "ulong_ptr", $iCodeSize, "dword", 0x1000, "dword", 0x40)
If @error Then Return SetError(2, @error, "")
If $aRet[0] = 0 Then Return SetError(3, 0, "")
$pThreadMem = $aRet[0]
ConsoleWrite("...Return from VirtualAllocEx = " & $pThreadMem & @CRLF)
; Code area (set in newly allocated space)
$stCode = DllStructCreate("byte ["&$iCodeSize&"];", $pThreadMem)
; Set the code
DllStructSetData($stCode, 1, $OGNT_CODE)
;MsgBox(0, "Code Set", "Code set at " & $pThreadMem) ; For setting Breakpoints
; Create the Thread - passing a pointer to $stData
$aRet = DllCall("kernel32.dll", "handle", "CreateThread", "ptr", 0, _
"ulong_ptr", 0, "ptr", $pThreadMem, "ulong_ptr", DllStructGetPtr($stData), "dword", 0, "dword*", 0)
If @error Then
$iExt = @error
$iErr = 2
ConsoleWrite("CreateThread error:" & @error & @CRLF)
ElseIf $aRet[0] = 0 Then
$iErr = 3
Else
ConsoleWrite("...Created Thread, Commencing Wait.."&@CRLF)
$hThread = $aRet[0]
; Wait a suitable amount of time for thread to complete (100 ms here)
$aRet = DllCall("kernel32.dll", "dword", "WaitForSingleObject", "handle", $hThread, "dword", 100)
If @error Then
$iExt = @error
$iErr = 2
ConsoleWrite("WaitForSingleObject error: " & @error & @CRLF)
; Anything other than WAIT_OBJECT_0 (i.e., success)
ElseIf $aRet[0] <> 0 Then
$iErr = -1
; Terminate thread - probably was locked up on querying a NamedPipe
$aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
ConsoleWrite("..TerminateThread return: " & $aRet[0] & @CRLF)
Else
ConsoleWrite("..Checking status return and looking for string.."&@CRLF)
$iExt = DllStructGetData($stData, "StatusRet")
; Check for NTSTATUS return of STATUS_SUCCESS (0)
If $iExt = 0 Then
; Success, let's check and grab the string return
Local $pStr, $stString
$pStr = DllStructGetData($stData, "Buffer")
If $pStr = 0 Then
;ConsoleWrite(@TAB&"-- No Object Name string --"&@CRLF)
;$sStr = ""
Else
$stString = DllStructCreate("wchar ["&(DllStructGetData($stData, "Length")/2)&"];", $pStr)
$sStr = DllStructGetData($stString, 1)
;ConsoleWrite(@TAB&"Object Name string = " & $aHandleInfo[$i][6] & @CRLF)
EndIf
Else
$iErr = 3
EndIf
EndIf
EndIf
; Now free the memory the code was in
$aRet = DllCall("kernel32.dll", "bool", "VirtualFreeEx", "handle", -1, "ptr", $pThreadMem, "ulong_ptr", 0, "dword", 0x8000)
ConsoleWrite("..Return from VirtualFreeEx = " & $aRet[0] & @CRLF)
_WinAPI_CloseHandle($hThread)
; Any errors?
If $iErr Then Return SetError($iErr, $iExt, "")
; Yay, we have a string (or a "" if there was none)
Return $sStr
EndFunc
我想获取某个进程打开的某个文件的完整路径 例如:由 paint 打开的图像或在我的情况下多个记事本进程是 运行 我得到了每个 notepad.exe 进程的 PID 所以当使用
_ProcessGetPath
我得到的是 notepad.exe 的路径,而不是进程打开的 file.txt 的路径,现在如何检索 txt 文件路径?
Credits go to the authors of AutoIt Unlocker!
#NoTrayIcon
#include "WinAPIEx.au3"
#include <WinAPI.au3>
Dim $hTimer = TimerInit()
Dim $aFiles = _ProcessListFiles("firefox.exe") ; Get a list of files currently opened by the process
ConsoleWrite("+>Took " & Round(TimerDiff($hTimer)) & " milliseconds" & @CRLF)
#include <Array.au3>
_ArrayDisplay($aFiles)
Exit
Func _ProcessListFiles($vProcess, $nMaxFiles = 1000)
Static Local $aPrivilege = DllCall("ntdll.dll", "int", "RtlAdjustPrivilege", "int", 20, "int", 1, "int", 0, "int*", 0)
Local $nProcessId = ProcessExists($vProcess), $aRet
Static Local $hCurrentProcess = _WinAPI_GetCurrentProcess()
Local $aHandles = _WinAPI_EnumProcessHandles($nProcessId)
Local $hObject, $aFiles[$nMaxFiles+1], $sPath
Local $hProcess = _WinAPI_OpenProcess(0x0040, 0, $nProcessId, True)
For $i = 1 To $aHandles[0][0] Step 1
If $aHandles[$i][3] = 0x00120189 Or $aHandles[$i][3] = 0x0012019f Or $aHandles[$i][3] = 0x00100000 Then ContinueLoop
$hObject = _WinAPI_DuplicateHandle($hProcess, $aHandles[$i][0], $hCurrentProcess, 0, False, $DUPLICATE_SAME_ACCESS)
If Not $hObject Then ContinueLoop
If __IsFileObject($hObject) Then
$sPath = __FileObjectPath($hObject)
_WinAPI_CloseHandle($hObject)
If FileExists($sPath) Then
For $n = 1 To $aFiles[0]
If $aFiles[$n] = $sPath Then
$sPath = 0
ExitLoop
EndIf
Next
If $sPath Then
$aFiles[0] += 1
$aFiles[$aFiles[0]] = $sPath
If $aFiles[0] >= $nMaxFiles Then ExitLoop
EndIf
EndIf
EndIf
Next
ReDim $aFiles[$aFiles[0]+1]
Return $aFiles
EndFunc
Func __IsFileObject(ByRef $hObject)
Static Local $tPOTI = DllStructCreate('ushort;ushort;ptr;byte[128]'), $pData, $Length, $tString
Local $aRet = DllCall("ntdll.dll", 'uint', 'NtQueryObject', 'ptr', $hObject, 'uint', 2, 'ptr', DllStructGetPtr($tPOTI), 'ulong', DllStructGetSize($tPOTI), 'ptr', 0)
If @error Or $aRet[0] Then Return
$pData = DllStructGetData($tPOTI, 3)
If Not $pData Then Return
$Length = DllCall("kernel32.dll", 'int', 'lstrlenW', 'ptr', $pData)
If @error Or Not $Length[0] Then Return
$Length = $Length[0]
$tString = DllStructCreate('wchar[' & ($Length + 1) & ']', $pData)
If @error Then Return
Return (DllStructGetData($tString, 1) == "File")
EndFunc
Func __FileObjectPath($hObject)
Static Local $tStruct = DllStructCreate("char[255];")
Local $aDrive = DriveGetDrive("ALL"), $sPath
Local $aDrivesInfo[UBound($aDrive) - 1][2]
For $I = 0 To UBound($aDrivesInfo) - 1
$aDrivesInfo[$I][0] = $aDrive[$I + 1]
DllCall("kernel32.dll", "dword", "QueryDosDevice", "str", $aDrivesInfo[$I][0], "ptr", DllStructGetPtr($tStruct), "dword", 255)
$aDrivesInfo[$I][1] = DllStructGetData($tStruct, 1)
Next
Local Static $tPOTI = DllStructCreate("ushort Length;ushort MaximumLength;ptr Buffer;wchar Reserved[260];"), $sDeviceStr, $vSolid = False
DllCall("ntdll.dll", "ulong", "NtQueryObject", "ptr", $hObject, "int", 1, "ptr", DllStructGetPtr($tPOTI), "ulong", DllStructGetSize($tPOTI), "ulong*", "")
$sDeviceStr = DllStructGetData(DllStructCreate("wchar[" & Ceiling(DllStructGetData($tPOTI, "Length") / 2) & "];", DllStructGetData($tPOTI, "buffer")), 1)
For $y = 0 To UBound($aDrivesInfo) - 1
If StringLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1])) = $aDrivesInfo[$y][1] Then
$sPath = StringUpper($aDrivesInfo[$y][0]) & StringTrimLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1]))
EndIf
Next
Return $sPath
EndFunc
或尝试:
#NoTrayIcon
#include "WinAPIEx.au3"
#include <WinAPI.au3>
Dim $hTimer = TimerInit()
Dim $aFiles = _ProcessListFiles("wmplayer.exe") ; Get a list of files currently opened by the process
ConsoleWrite("+>Took " & Round(TimerDiff($hTimer)) & " milliseconds" & @CRLF)
#include <Array.au3>
_ArrayDisplay($aFiles)
Func _ProcessListFiles($vProcess, $nMaxFiles = 1000)
Static Local $aPrivilege = DllCall("ntdll.dll", "int", "RtlAdjustPrivilege", "int", 20, "int", 1, "int", 0, "int*", 0)
Local $nProcessId = ProcessExists($vProcess), $aRet
Static Local $hCurrentProcess = _WinAPI_GetCurrentProcess()
Local $aHandles = _WinAPI_EnumProcessHandles($nProcessId)
Local $hObject, $aFiles[$nMaxFiles+1], $sPath
Local $hProcess = _WinAPI_OpenProcess(0x0040, 0, $nProcessId, True)
For $i = 1 To $aHandles[0][0] Step 1
$hObject = _WinAPI_DuplicateHandle($hProcess, $aHandles[$i][0], $hCurrentProcess, 0, False, $DUPLICATE_SAME_ACCESS)
If Not $hObject Then ContinueLoop
If __IsFileObject($hObject) Then
If $aHandles[$i][3] = 0x00120189 Or $aHandles[$i][3] = 0x0012019f Or $aHandles[$i][3] = 0x00100000 Or $aHandles[$i][3] = 0x001F01FF Then
$sPath = __FileObjectPath_UD($hObject)
Else
$sPath = __FileObjectPath($hObject)
EndIf
_WinAPI_CloseHandle($hObject)
If FileExists($sPath) Then
For $n = 1 To $aFiles[0]
If $aFiles[$n] = $sPath Then
$sPath = 0
ExitLoop
EndIf
Next
If $sPath Then
$aFiles[0] += 1
$aFiles[$aFiles[0]] = $sPath
If $aFiles[0] >= $nMaxFiles Then ExitLoop
EndIf
EndIf
EndIf
Next
ReDim $aFiles[$aFiles[0]+1]
Return $aFiles
EndFunc
Func __IsFileObject(ByRef $hObject)
Static Local $tPOTI = DllStructCreate('ushort;ushort;ptr;byte[128]'), $pData, $Length, $tString
Local $aRet = DllCall("ntdll.dll", 'uint', 'NtQueryObject', 'ptr', $hObject, 'uint', 2, 'ptr', DllStructGetPtr($tPOTI), 'ulong', DllStructGetSize($tPOTI), 'ptr', 0)
If @error Or $aRet[0] Then Return
$pData = DllStructGetData($tPOTI, 3)
If Not $pData Then Return
$Length = DllCall("kernel32.dll", 'int', 'lstrlenW', 'ptr', $pData)
If @error Or Not $Length[0] Then Return
$Length = $Length[0]
$tString = DllStructCreate('wchar[' & ($Length + 1) & ']', $pData)
If @error Then Return
Return (DllStructGetData($tString, 1) == "File")
EndFunc
Func __FileObjectPath_UD($hObject)
Static Local $tStruct = DllStructCreate("char[255];")
Local $aDrive = DriveGetDrive("ALL"), $sPath
Local $aDrivesInfo[UBound($aDrive) - 1][2]
For $I = 0 To UBound($aDrivesInfo) - 1
$aDrivesInfo[$I][0] = $aDrive[$I + 1]
DllCall("kernel32.dll", "dword", "QueryDosDevice", "str", $aDrivesInfo[$I][0], "ptr", DllStructGetPtr($tStruct), "dword", 255)
$aDrivesInfo[$I][1] = DllStructGetData($tStruct, 1)
Next
$sDeviceStr = _ObjectGetNameUD_Threaded($hObject)
If Not $sDeviceStr Then Return
For $y = 0 To UBound($aDrivesInfo) - 1
If StringLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1])) = $aDrivesInfo[$y][1] Then
$sPath = StringUpper($aDrivesInfo[$y][0]) & StringTrimLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1]))
EndIf
Next
Return $sPath
EndFunc
Func __FileObjectPath($hObject)
Static Local $tStruct = DllStructCreate("char[255];")
Local $aDrive = DriveGetDrive("ALL"), $sPath
Local $aDrivesInfo[UBound($aDrive) - 1][2]
For $I = 0 To UBound($aDrivesInfo) - 1
$aDrivesInfo[$I][0] = $aDrive[$I + 1]
DllCall("kernel32.dll", "dword", "QueryDosDevice", "str", $aDrivesInfo[$I][0], "ptr", DllStructGetPtr($tStruct), "dword", 255)
$aDrivesInfo[$I][1] = DllStructGetData($tStruct, 1)
Next
Local Static $tPOTI = DllStructCreate("ushort Length;ushort MaximumLength;ptr Buffer;wchar Reserved[260];"), $sDeviceStr, $vSolid = False
DllCall("ntdll.dll", "ulong", "NtQueryObject", "ptr", $hObject, "int", 1, "ptr", DllStructGetPtr($tPOTI), "ulong", DllStructGetSize($tPOTI), "ulong*", "")
$sDeviceStr = DllStructGetData(DllStructCreate("wchar[" & Ceiling(DllStructGetData($tPOTI, "Length") / 2) & "];", DllStructGetData($tPOTI, "buffer")), 1)
For $y = 0 To UBound($aDrivesInfo) - 1
If StringLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1])) = $aDrivesInfo[$y][1] Then
$sPath = StringUpper($aDrivesInfo[$y][0]) & StringTrimLeft($sDeviceStr, StringLen($aDrivesInfo[$y][1]))
EndIf
Next
Return $sPath
EndFunc
; ==============================================================================================
; Func _ObjectGetNameUD_Threaded($hObject)
;
; Gets the Name associated with a Kernel Object Handle.
; Most useful for 'File' Types
;
; This differs from _ObjectGetNameUD() in that it launches a thread to try and get the name
; If the thread times-out, it is killed.
;
; This is a workaround for the NamedPipes issue - often these types of Objects will be
; locked in reads/writes/waits for long periods of time and cause any type of querying
; attempts on the Object to lockup indefinitely.
;
; Returns:
; Success: String representing the name of the Object
; Failure: "" with @error set
;
; Author: Ascend4nt
; ==============================================================================================
Func _ObjectGetNameUD_Threaded($hObject)
Local $OGNT_CODE
;~ $aRet=DllCall("ntdll.dll", "long", "NtQueryObject", "handle", $hObject, "int", 1, _
;~ "ptr", DllStructGetPtr($stBuffer), "ulong", DllStructGetSize($stBuffer), "ulong*", 0)
If @AutoItX64 Then
$OGNT_CODE='0x4831C04889CE483906742D483946087427504883EC2049C7C1FF7F00004C8D461848C7C201000000488B4E08488B1EFFD34883C428894610C3'
Else
$OGNT_CODE='0x5589E531C08B750839067421394604741C50B8FF7F0000508D461050B801000000508B4604508B1EFFD38946085DC3'
EndIf
Local $aRet, $sStr = "", $iErr = 0, $iExt = 0, $stData
Local $stCode, $iCodeSize, $pThreadMem, $hThread = 0
If Not IsPtr($hObject) Or $hObject = 0 Then Return SetError(1,0,"")
$iCodeSize = BinaryLen($OGNT_CODE)
$aRet = DllCall("kernel32.dll", "ptr", "GetModuleHandleA", "str", "ntdll.dll")
If @error Then Return SetError(2, @error, "")
If $aRet[0] = 0 Then Return SetError(3, 0, "")
$aRet = DllCall("kernel32.dll", "ptr", "GetProcAddress", "handle", $aRet[0], "str", "NtQueryObject")
If @error Then Return SetError(2, @error, "")
If $aRet[0] = 0 Then Return SetError(3, 0, "")
;$pNTQO = $aRet[0]
; Data to receive (must be kept alive while thread exists!)
$stData = DllStructCreate("ptr NTQO;handle Object;ulong StatusRet;ulong StructPad;ushort Length;ushort MaximumLength;ptr Buffer;" & "byte [32768];")
DllStructSetData($stData, "Object", $hObject)
DllStructSetData($stData, "NTQO", $aRet[0]) ; $pNTQO
$aRet = DllCall("kernel32.dll", "ptr", "VirtualAllocEx", "handle", -1, _
"ptr", 0, "ulong_ptr", $iCodeSize, "dword", 0x1000, "dword", 0x40)
If @error Then Return SetError(2, @error, "")
If $aRet[0] = 0 Then Return SetError(3, 0, "")
$pThreadMem = $aRet[0]
ConsoleWrite("...Return from VirtualAllocEx = " & $pThreadMem & @CRLF)
; Code area (set in newly allocated space)
$stCode = DllStructCreate("byte ["&$iCodeSize&"];", $pThreadMem)
; Set the code
DllStructSetData($stCode, 1, $OGNT_CODE)
;MsgBox(0, "Code Set", "Code set at " & $pThreadMem) ; For setting Breakpoints
; Create the Thread - passing a pointer to $stData
$aRet = DllCall("kernel32.dll", "handle", "CreateThread", "ptr", 0, _
"ulong_ptr", 0, "ptr", $pThreadMem, "ulong_ptr", DllStructGetPtr($stData), "dword", 0, "dword*", 0)
If @error Then
$iExt = @error
$iErr = 2
ConsoleWrite("CreateThread error:" & @error & @CRLF)
ElseIf $aRet[0] = 0 Then
$iErr = 3
Else
ConsoleWrite("...Created Thread, Commencing Wait.."&@CRLF)
$hThread = $aRet[0]
; Wait a suitable amount of time for thread to complete (100 ms here)
$aRet = DllCall("kernel32.dll", "dword", "WaitForSingleObject", "handle", $hThread, "dword", 100)
If @error Then
$iExt = @error
$iErr = 2
ConsoleWrite("WaitForSingleObject error: " & @error & @CRLF)
; Anything other than WAIT_OBJECT_0 (i.e., success)
ElseIf $aRet[0] <> 0 Then
$iErr = -1
; Terminate thread - probably was locked up on querying a NamedPipe
$aRet = DllCall("kernel32.dll", "bool", "TerminateThread", "handle", $hThread, "int", -1)
ConsoleWrite("..TerminateThread return: " & $aRet[0] & @CRLF)
Else
ConsoleWrite("..Checking status return and looking for string.."&@CRLF)
$iExt = DllStructGetData($stData, "StatusRet")
; Check for NTSTATUS return of STATUS_SUCCESS (0)
If $iExt = 0 Then
; Success, let's check and grab the string return
Local $pStr, $stString
$pStr = DllStructGetData($stData, "Buffer")
If $pStr = 0 Then
;ConsoleWrite(@TAB&"-- No Object Name string --"&@CRLF)
;$sStr = ""
Else
$stString = DllStructCreate("wchar ["&(DllStructGetData($stData, "Length")/2)&"];", $pStr)
$sStr = DllStructGetData($stString, 1)
;ConsoleWrite(@TAB&"Object Name string = " & $aHandleInfo[$i][6] & @CRLF)
EndIf
Else
$iErr = 3
EndIf
EndIf
EndIf
; Now free the memory the code was in
$aRet = DllCall("kernel32.dll", "bool", "VirtualFreeEx", "handle", -1, "ptr", $pThreadMem, "ulong_ptr", 0, "dword", 0x8000)
ConsoleWrite("..Return from VirtualFreeEx = " & $aRet[0] & @CRLF)
_WinAPI_CloseHandle($hThread)
; Any errors?
If $iErr Then Return SetError($iErr, $iExt, "")
; Yay, we have a string (or a "" if there was none)
Return $sStr
EndFunc