Reputation: 37
IMPORTANT: we use DELPHI 7.
I have a problem to get the ProcessId
that is using a file.
Just to let you know, in our software we need to show to the user what Process is using the file that we need.
To do that, I used NtQuerySystemInformation
to get the Process list and Handle list.
After that, I used OpenProcess
on those Process Ids with Handles that are files (ObjectType = 28)
And then I used DuplicateHandle
to get the File Handle.
Let's see the code:
function GetProcessIdUsingFile(const TargetFileName:string): DWORD;
var
hProcess : THandle;
hFile : THandle;
SystemInformationLength : DWORD;
Index : Integer;
pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
hQuery : THandle;
FileName : String;
ReturnInformation : LongBool;
FileInfo : _BY_HANDLE_FILE_INFORMATION;
//Novo
cbRet : DWORD;
cbSize : DWORD;
begin
Result:= 0;
cbSize := $5000;
GetMem(pHandleInfo, cbSize);
repeat
cbSize := cbSize * 2;
ReallocMem(pHandleInfo, cbSize);
hQuery := NtQuerySystemInformation(SystemHandleInformation, pHandleInfo, cbSize, @cbRet);
until hQuery <> STATUS_INFO_LENGTH_MISMATCH;
try
if(hQuery = STATUS_SUCCESS) then
begin
for Index:=0 to pHandleInfo^.uCount-1 do
if pHandleInfo^.Handles[Index].ObjectType=28 then
begin
hProcess := OpenProcess(PROCESS_DUP_HANDLE, FALSE, pHandleInfo^.Handles[Index].uIdProcess);
if(hProcess <> INVALID_HANDLE_VALUE) then
begin
try
if not DuplicateHandle(hProcess, pHandleInfo^.Handles[Index].Handle,GetCurrentProcess(), @hFile, 0 ,FALSE, DUPLICATE_SAME_ACCESS) then
hFile := INVALID_HANDLE_VALUE;
if (hFile<>INVALID_HANDLE_VALUE) then
begin
try
FileName := GetFileNameByHandle(hFile);
finally
CloseHandle(hFile);
end;
end
else
FileName := '';
finally
CloseHandle(hProcess);
end;
if CompareText(ExtractFileName(FileName), TargetFileName)=0 then
Result := pHandleInfo^.Handles[Index].uIdProcess;
end;
end;
end;
finally
if pHandleInfo<>nil then
FreeMem(pHandleInfo);
end;
end;
So, I created GetFileNameByHandle
This function receives a File Handle from the previous code and tries to get its File Name using NtQueryInformationFile
and NtQueryObject
.
But, every call of NtQueryInformationFile
returns STATUS_OBJECT_TYPE_MISMATCH
. How can I get its File Name?
Let me show you the code of this function:
function GetFileNameByHandle(hFile: THandle): String;
var
dwReturn: DWORD;
FileNameInfoRecord: FILE_NAME_INFORMATION;
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
IoStatusBlock: IO_STATUS_BLOCK;
ntSTATUS : DWORD;
FileName : array [0..MAX_PATH - 1] of WCHAR;
begin
FillChar(FileName, SizeOf(FileName), 0);
FillChar(FileNameInfoRecord.FileName, SizeOf(FileNameInfoRecord.FileName), 0);
FileNameInfoRecord.FileNameLength := 0;
ntSTATUS := NtQueryInformationFile(hFile, @IoStatusBlock, @FileNameInfoRecord, SizeOf(FILE_NAME_INFORMATION) * 2 + 1, FileNameInformation);
if ntSTATUS = STATUS_SUCCESS then
begin
// NEVER ENTER HERE... WHY?
ntSTATUS := NtQueryObject(hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
if ntSTATUS = STATUS_SUCCESS then
begin
WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @FileName[0], MAX_PATH, nil, nil);
end
else
begin
ntSTATUS := STATUS_SUCCESS;
WideCharToMultiByte(CP_ACP, 0, @FileNameInfoRecord.FileName[1], IoStatusBlock.Information, @FileName[0], MAX_PATH, nil, nil);
end;
end;
Result := WideCharToString(@FileName);
end;
After that, I compare Filenames in GetProcessIdUsingFile
function to return the PID.
I used this code as a base, and tried some modifications, but nothing work:
Delphi - finding the process that is accessing a file from my program
If you guys need more information, please LMK.
Upvotes: 0
Views: 264