Delphi 使用NTQuerySystemInformation/NtQueryInformationFile/NtQueryObject获取进程使用的Unicode文件名
我从这里稍微修改了代码: 为了按给定的pID返回句柄名称列表,我将每个条目添加到TStringList中。问题是名称在包含unicode字符的文件名中包含像“?”这样的垃圾,例如“xxx”★ “5”显示为“xxx?5”Delphi 使用NTQuerySystemInformation/NtQueryInformationFile/NtQueryObject获取进程使用的Unicode文件名,delphi,delphi-xe3,Delphi,Delphi Xe3,我从这里稍微修改了代码: 为了按给定的pID返回句柄名称列表,我将每个条目添加到TStringList中。问题是名称在包含unicode字符的文件名中包含像“?”这样的垃圾,例如“xxx”★ “5”显示为“xxx?5” 代码中有什么错误?看到任何非ASCII字符都带有问号,这是尝试从Unicode转换为ANSI的标志 此函数中存在问题: function GetFileNameHandleThr(Data: Pointer): DWORD; stdcall; var dwReturn: D
代码中有什么错误?看到任何非ASCII字符都带有问号,这是尝试从Unicode转换为ANSI的标志 此函数中存在问题:
function GetFileNameHandleThr(Data: Pointer): DWORD; stdcall;
var
dwReturn: DWORD;
FileNameInfo: FILE_NAME_INFORMATION;
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
IoStatusBlock: IO_STATUS_BLOCK;
pThreadParam: TGetFileNameThreadParam;
begin
ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
pThreadParam := PGetFileNameThreadParam(Data)^;
Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock, @FileNameInfo, MAX_PATH * 2, FileNameInformation);
if Result = STATUS_SUCCESS then
begin
Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
if Result = STATUS_SUCCESS then
begin
pThreadParam.Result := Result;
WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
end
else
begin
pThreadParam.Result := STATUS_SUCCESS;
Result := STATUS_SUCCESS;
WideCharToMultiByte(CP_ACP, 0, @FileNameInfo.FileName[0], IoStatusBlock.Information, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
end;
end;
PGetFileNameThreadParam(Data)^ := pThreadParam;
ExitThread(Result);
end;
这将在对wideChartMultiByte
的调用中从Unicode转换为ANSI。您只需删除该部分代码
您需要修改此记录
TGetFileNameThreadParam = packed record
hFile : THandle;
Result : NT_STATUS;
FileName : array [0..MAX_PATH - 1] of AnsiChar;
end;
因此,FileName
是一个WideChar
数组
TGetFileNameThreadParam = packed record
hFile : THandle;
Result : NT_STATUS;
FileName : array [0..MAX_PATH - 1] of WideChar;
end;
然后相应地调整GetFileNameHandleThr
。我没有详细研究过,但我想你需要这样的东西:
function GetFileNameHandleThr(Data: Pointer): DWORD; stdcall;
var
dwReturn: DWORD;
FileNameInfo: FILE_NAME_INFORMATION;
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
IoStatusBlock: IO_STATUS_BLOCK;
pThreadParam: TGetFileNameThreadParam;
begin
ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
pThreadParam := PGetFileNameThreadParam(Data)^;
Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock, @FileNameInfo, MAX_PATH * 2, FileNameInformation);
if Result = STATUS_SUCCESS then
begin
Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
if Result = STATUS_SUCCESS then
begin
pThreadParam.Result := Result;
Move(ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], pThreadParam.FileName[0], Min(ObjectNameInfo.Name.Length, MAX_PATH)*SizeOf(WideChar));
//WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
end
else
begin
pThreadParam.Result := STATUS_SUCCESS;
Result := STATUS_SUCCESS;
Move(FileNameInfo.FileName[0], pThreadParam.FileName[0], Min(IoStatusBlock.Information, MAX_PATH)*SizeOf(WideChar));
//WideCharToMultiByte(CP_ACP, 0, @FileNameInfo.FileName[0], IoStatusBlock.Information, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
end;
end;
PGetFileNameThreadParam(Data)^ := pThreadParam;
ExitThread(Result);
end;
我没有运行此代码,因此您可能需要进一步处理它。然而,很明显,问题在于到ANSI的转换
我现在已经运行了这段代码,它运行得很好。文件名现在由于这些更改而为空。我想这是因为您未能进行所有更改。您可能没有将
TGetFileNameThreadParam
更改为使用WideChar
缓冲区。重要的是,您不能仅仅将其视为一个黑盒子,并充分理解代码的工作原理。