Delphi - Load files & folders to TreeView ( using IOUtils ) - file

How can I properly organize the loading of a specific path of the file system (Windows) in TreeView?
For example:
load files & folders to TreeView (with IOUtils)
(*
tv_zapis: TTreeView
uses
System.IOUtils,
System.Types;
*)
procedure TF1.tb_ReDirectClick(Sender: TObject);
{ ReDirect ( Reorganization Directoris ) dirs & files to TTreeView }
procedure DFToTv(_Tv: TTreeView;
withNode: TTreeNode;
dfPath: string);
var
InsNode: TTreeNode;
Short_Name,
Short_EXT: string; // '*.txt' - delete
sPath: string;
arMask: TStringDynArray;
FilterTN: TDirectory.TFilterPredicate;
SO: TSearchOption;
s: TShiftState;
begin
sPath := Trim(dfPath);
SO := TSearchOption.soAllDirectories; // Search for All Directories in dir
FilterTN := // Filter for Find files
function(const Path: string; const SearchRec: TSearchRec): Boolean
var
nDir, // name Folder ( ! not full path )
sDF: string;
fAtts: TFileAttributes;
begin
nDir := TPath.GetFileName(Path); { Path Name - name of 'folder' }
sDF := IncludeTrailingPathDelimiter(Path) + SearchRec.Name ; // + '\' + SearchRec.Name
// Ignor find dir '_Setting'
if (SearchRec.Name = APL_nameS) or (nDir = APL_nameS)
then exit(False);
{ Browse a file and read its attributes }
fAtts := TPath.GetAttributes(sDF, False);
if (TFileAttribute.faDirectory in fAtts) then
begin
{ if path ' FOLDER ' }
Short_Name := SearchRec.Name;
// ??????????
InsNode := withNode.Parent;
if (InsNode = nil) then
begin
// ShowMessage( ' 1 ? ' );
// ??????????
//if (InsNode.Text = tNode.Text) then
InsNode := _Tv.Items.AddChild(withNode, Short_Name)
//else
// InsNode := _Tv.Items.AddChild(InsNode, Short_Name);
end
else
begin
ShowMessage( ' 2 ? ' );
// ??????????
InsNode := _Tv.Items.AddChild(InsNode, Short_Name);
end;
InsNode.ImageIndex := 1;
InsNode.SelectedIndex := 2;
Exit(True);
end
else
begin
{ if path ' File ' }
Short_EXT := AnsiUpperCase(ExtractFileExt(SearchRec.Name));
if (Short_EXT = '.TXT') then
Short_Name := ChangeFileExt(SearchRec.Name , '')
else
Short_Name := SearchRec.Name;
ShowMessage( ' 3 ? ' );
// ??????????
InsNode := _Tv.Items.AddChild(InsNode.Parent, Short_Name);
if (Short_EXT = '.TXT') then
begin
InsNode.ImageIndex := 3;
InsNode.SelectedIndex := 4;
end
else
begin
InsNode.ImageIndex := 5;
InsNode.SelectedIndex := 5;
end;
Exit(True);
end;
end;
{ FIND FOLDER & File }
arMask := TDirectory.GetFileSystemEntries(sPath, SO, FilterTN);
Application.ProcessMessages;
//Screen.Cursor := crDefault;
// ShowMessage(' All Good :))) ');
(*
ShowMessage( 'sDF - ' + '`' + sDF + '`' + sLineBreak + sLineBreak +
'Path - ' + Path + sLineBreak + sLineBreak +
'SearchRec.Name - ' + '`' + SearchRec.Name + '`' + sLineBreak
);
*)
end;
var
tNode: TTreeNode;
nodeChild: Boolean;
begin
if (DirectoryExists(APL_Files) = False) then Exit;
tv_zapis.Items.Item[0].Selected := True;
Screen.Cursor := crHourGlass;
tv_zapis.Items.BeginUpdate;
try
tv_zapis.Items.Clear;
tNode := tv_zapis.Items.AddChild(nil, 'Dominant_Folder');
begin
DFToTv (tv_zapis, tNode, APL_Files);
end;
finally
tv_zapis.Items.EndUpdate;
Screen.Cursor := crDefault;
end;
end;
Everything functions correctly, but the path does not display correctly on the TreeView (tv_zapis).

Related

How to get the path to the file using backslash symbol and 2 dots ('\..')

In Delphi program I use ExtractFileDir function for getting parent folder and this code works correctly:
Fmain.frxReport1.LoadFromFile(ExtractFileDir(ExtractFileDir(ExtractFileDir(ExtractFilePath(ParamStr(0)))))+'\FastReports\report1.fr3');
How can I modify it and get parent folder's path with using "\.." as it is realised in Delphi sample program
Update:
I wrote this code:
setcurrentdir('../../');
s1:=getcurrentdir();
frxReport1.LoadFromFile(s1+'\FastReports\report1.fr3');
but I want one-line(as my code with ExtractFileDir ) and well-readable code to replace my code.
I have a function which absolutize a relative path.
To absolutize a path, you need to know the base path.
I the case of Delphi you show, the paths are relative to the project directory.
Once you have an absolute path, you can apply ExtractFilePath several times to go up in the directory levels.
Let's take an example: You have a relative path "....\SomeFile.txt". This path is relative to the base path "C:\ProgramData\Acme\Project\Demo". The complete path is: "C:\ProgramData\Acme\Project\Demo....\SomeFile.txt". Then the absolute path result of AbsolutizePath will be "C:\ProgramData\Acme\SomeFile.txt".
Note that Absolutize path take care of ".." (parent directory), "." (Current directory) and drive specification (Such as C:).
function AbsolutizePath(
const RelPath : String;
const BasePath : String = '') : String;
var
I, J : Integer;
begin
if RelPath = '' then
Result := BasePath
else if RelPath[1] <> '\' then begin
if (BasePath = '') or
((Length(RelPath) > 1) and (RelPath[2] = ':')) then
Result := RelPath
else
Result := IncludeTrailingPathDelimiter(BasePath) + RelPath;
end
else
Result := RelPath;
// If there is no drive in the result, add the one from base if any
if (Length(Result) > 1) and (Result[2] <> ':') and
(Length(BasePath) > 1) and (BasePath[2] = ':') then
Insert(Copy(BasePath, 1, 2), Result, 1);
// Delete "current dir" marker
I := 1;
while TRUE do begin
I := Pos('\.\', Result, I);
if I <= 0 then
break;
Delete(Result, I, 2);
end;
// Process "up one level" marker
I := 1;
while TRUE do begin
I := Pos('\..\', Result, I);
if I <= 0 then
break;
J := I - 1;
while (J > 0) and (not CharInSet(Result[J], ['\', ':'])) do
Dec(J);
// Check if we hit drive delimiter and fix it
if (J = 2) and (Result[J] = ':') then
J := 3;
Delete(Result, J + 1, I - J + 3);
I := J;
end;
end;

Delphi: Timer in Service Stops my FileReader

I am writing a Service that has a Timer which should check every 60 seconds if a Line has a particular number. Here is the code of the timer:
procedure TConnectionChecker.Timer2Timer(Sender: TObject);
var
myFile: TextFile;
sLine: string;
fileOpenLog: TStreamWriter;
fileOpenLogName, fileOpenLogPathName: string;
begin
ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
filename:= 'restult.txt';
filePath:= TPath.Combine(exePath, 'OutputFile');
filePathName:= TPath.Combine(filePath, filename);
fileOpenLogName:= 'Log_fileOpen.txt';
serviceLogPath:= TPath.Combine(exePath, 'LogFiles');
fileOpenLogPathName:= TPath.Combine(serviceLogPath, fileOpenLogName);
fileOpenLog := TStreamWriter.Create(TFileStream.Create(fileOpenLogPathName, fmCreate or fmShareDenyWrite));
if not FileExists(filePathName) then
begin
fileOpenLog.WriteLine('File not found');
TServiceThread.Current.Terminate;
fileOpenLog.Free;
end;
fileOpenLog.WriteLine('File found');
try
AssignFile(myFile, filePathName);
Reset(myFile);
fileOpenLog.WriteLine('File opened');
while NOT eof(myFile) do
begin
PingWorkedAufrufe:= PingWorkedAufrufe + 1;
readln(myFile, sLine);
fileOpenLog.WriteLine('Read Line: ' + sLine);
checkIfPingWorked(sLine);
end;
fileOpenLog.WriteLine('EOF');
finally
CloseFile(myFile);
end;
fileOpenLog.Free;
end;
And here is the code of my Procedure: checkIfPingWorked:
procedure TConnectionChecker.checkIfPingWorked(ALine: String);
var
AValue, StartOfLineToFind: String;
checkIfPingWorkedLog: TStreamWriter;
checkIfPingWorkedLogName, checkIfPingWorkedLogPathName: string;
begin
ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
StartOfLineToFind:= ' Pakete: Gesendet =';
ip:= '...';
fileName:= 'restult.txt';
filepath:= TPath.Combine(exePath, 'OutputFile');
filepathname:= TPath.Combine(filepath, fileName);
serviceLogPath:= TPath.Combine(exePath, 'LogFiles');
checkIfPingWorkedLogName:= 'Log_checkIfPingWorked.txt';
checkIfPingWorkedLogPathName := TPath.Combine(serviceLogPath, checkIfPingWorkedLogName);
checkIfPingWorkedLog := TStreamWriter.Create(TFileStream.Create(checkIfPingWorkedLogPathName, fmCreate or fmShareDenyWrite));
checkIfPingWorkedLog.WriteLine('Zeilen werden überprüft');
if Pos(StartOfLineToFind, ALine) = 1 then
begin
AValue:= Copy(ALine, 39, 1);
if AValue = IntToStr(5) then
checkIfPingWorkedLog.WriteLine('Success')
else
begin
checkIfPingWorkedLog.WriteLine('Error');
//Writing E-Mail...
//Authentifizierung
IdSMTP1.AuthType := TIdSMTPAuthenticationType.satDefault;
//Benutzerdaten für Authentifizierung
IdSMTP1.Username := '...';
IdSMTP1.Password := '...';
//Server-Daten
IdSMTP1.Host := '...';
IdSMTP1.Port := ...;
IdSMTP1.Connect;
try
IdMessage1.From.Address := '';
IdMessage1.Recipients.EMailAddresses := '';
//IdMessage1.CCList.EMailAddresses := '';
//IdMessage1.BCCList.EMailAddresses := '';
IdMessage1.Subject := '--AUTOMATISCHE BENACHRICHTIGUNG--';
IdMessage1.Body.Text := 'Der PC mit der IP: ' + ip + ' konnte nicht mehr erreicht werden';
IdSMTP1.Send(IdMessage1);
finally
IdSMTP1.Disconnect;
end;
checkIfPingWorkedLog.WriteLine('Email sent');
TServiceThread.Current.Terminate;
end;
end;
checkIfPingWorkedLog.Free;
end;
But I can only read the first two lines and then it stops.
Important to say is that I originally wrote this as a normal Program. And it worked fine. Now I am converting it into a Windows Service.
The Problem was, that I created everywhere and everytime new Log Files.
Now I Create one Log file on Service Create:
procedure TConnectionChecker.ServiceCreate(Sender: TObject);
var
logFilePathName, logFileName, exePath, logFilePath: String;
begin
ExePath := TPath.GetDirectoryName(GetModuleName(HInstance));
logFileName:= 'log_connectionTest.txt';
logFilePath:= TPath.Combine(exePath, 'logFile');
logFilePathName:= TPath.Combine(logFilePath, logFileName);
if not TDirectory.Exists(logFilePath) then
TDirectory.CreateDirectory(logFilePath);
swLogFile:= TStreamWriter.Create(TFileStream.Create(logFilePathName, fmCreate or fmShareDenyWrite));
end;
And I made a procedure where I ask for 2 params (destination and text) and write the line to the Log file.:
procedure TConnectionChecker.WriteToLog(destination, Text: string);
begin
swLogFile.WriteLine('[' + DateTimeToStr(now) + '] ' + destination + ' schreibt: ' + text);
end;
Finally I can call it in every procedure:
WriteToLog('checkIfPingWorked', 'Success')

Dynamic array of bytes to string

For a project, I need to read a name inside a TrueType font file (.ttf). I written a code to do that, inspirated from a c++ example. Here is the code:
TWByteArray = array of Byte;
TWAnsiCharArray = array of AnsiChar;
...
//---------------------------------------------------------------------------
class function TWStringHelper.ByteToStr(const bytes: TWByteArray): string;
begin
SetLength(Result, Length(bytes));
if Length(Result) > 0 then
Move(bytes[0], Result[1], Length(bytes));
end;
//---------------------------------------------------------------------------
class function TWStringHelper.UniStrToByte(const str: UnicodeString): TWByteArray;
begin
SetLength(Result, Length(str) * SizeOf(WideChar));
if (Length(Result) > 0) then
Move(str[1], Result[0], Length(Result));
end;
//---------------------------------------------------------------------------
class function TWStringHelper.BytesToUniStr(const bytes: TWByteArray): UnicodeString;
begin
SetLength(Result, Length(bytes) div SizeOf(WideChar));
if Length(Result) > 0 then
Move(bytes[0], Result[1], Length(bytes));
end;
//---------------------------------------------------------------------------
...
//---------------------------------------------------------------------------
class function TWControlFont.SwapWord(value: Word): Word;
begin
Result := MakeWord(HiByte(value), LoByte(value));
end;
//---------------------------------------------------------------------------
class function TWControlFont.SwapLong(value: LongInt): LongInt;
begin
Result := MakeLong(SwapWord(HiWord(value)), SwapWord(LoWord(value)));
end;
//---------------------------------------------------------------------------
class function TWControlFont.GetFontNameFromFile(const fileName: UnicodeString): UnicodeString;
var
pFile: TFileStream;
offsetTable: ITTFOffsetTable;
dirTable: ITTFDirectoryTable;
nameHeader: ITTFNameTableHeader;
nameRecord: ITTFNameRecord;
nameBuffer: TWByteArray;//TWAnsiCharArray;
i: USHORT;
found: Boolean;
test2: string;
test3: UnicodeString;
test: Integer;
const name: array [0..3] of Byte = (Ord('n'), Ord('a'), Ord('m'), Ord('e'));
begin
// open font file
pFile := TFileStream.Create(fileName, fmOpenRead);
// succeeded?
if (not Assigned(pFile)) then
Exit;
try
pFile.Seek(0, soFromBeginning);
// read TTF offset table
if (pFile.Read(offsetTable, SizeOf(ITTFOffsetTable)) <> SizeOf(ITTFOffsetTable)) then
Exit;
offsetTable.m_NumOfTables := SwapWord(offsetTable.m_NumOfTables);
offsetTable.m_MajorVersion := SwapWord(offsetTable.m_MajorVersion);
offsetTable.m_MinorVersion := SwapWord(offsetTable.m_MinorVersion);
// is truetype font and version is 1.0?
if ((offsetTable.m_MajorVersion <> 1) or (offsetTable.m_MinorVersion <> 0)) then
Exit;
found := False;
// iterate through file tables
if (offsetTable.m_NumOfTables > 0) then
for i := 0 to offsetTable.m_NumOfTables - 1 do
begin
// read table
if (pFile.Read(dirTable, SizeOf(ITTFDirectoryTable)) <> SizeOf(ITTFDirectoryTable)) then
Exit;
// found name table?
if (CompareMem(#dirTable.m_Tag, #name, 4) = True) then
begin
found := True;
dirTable.m_Length := SwapLong(dirTable.m_Length);
dirTable.m_Offset := SwapLong(dirTable.m_Offset);
break;
end;
end;
// found name table?
if (not found) then
Exit;
// seek to name location
pFile.Position := dirTable.m_Offset;
// read name table header
if (pFile.Read(nameHeader, SizeOf(ITTFNameTableHeader)) <> SizeOf(ITTFNameTableHeader)) then
Exit;
nameHeader.m_NRCount := SwapWord(nameHeader.m_NRCount);
nameHeader.m_StorageOffset := SwapWord(nameHeader.m_StorageOffset);
// iterate through name records
if (nameHeader.m_NRCount > 0) then
for i := 0 to nameHeader.m_NRCount - 1 do
begin
// read name record
if (pFile.Read(nameRecord, SizeOf(ITTFNameRecord)) <> SizeOf(ITTFNameRecord)) then
Exit;
nameRecord.m_NameID := SwapWord(nameRecord.m_NameID);
// found font name?
if (nameRecord.m_NameID = 1) then
begin
// get font name length and offset
nameRecord.m_StringLength := SwapWord(nameRecord.m_StringLength);
nameRecord.m_StringOffset := SwapWord(nameRecord.m_StringOffset);
if (nameRecord.m_StringLength = 0) then
continue;
// calculate and seek to font name offset
pFile.Position := dirTable.m_Offset + nameRecord.m_StringOffset + nameHeader.m_StorageOffset;
try
SetLength(nameBuffer, nameRecord.m_StringLength + 1);
//REM FillChar(nameBuffer[0], nameRecord.m_StringLength + 1, $0);
// read font name from file
if (pFile.Read(nameBuffer[0], nameRecord.m_StringLength)
<> nameRecord.m_StringLength)
then
Exit;
nameBuffer[nameRecord.m_StringLength] := $0;
//OutputDebugString(PChar(nameBuffer));
//TWMemoryHelper.SwapBytes(nameBuffer[0], nameRecord.m_StringLength);
//OutputDebugString(PChar(nameBuffer));
//test := StringElementSize(RawByteString(#nameBuffer[0]));
//Result := TWStringHelper.BytesToUniStr(nameBuffer);
//Result := UnicodeString(AnsiString(TWStringHelper.ByteToStr(nameBuffer)));
//REM Result := UnicodeString(nameBuffer);
test2 := TWStringHelper.ByteToStr(nameBuffer);
OutputDebugStringA(PAnsiChar(test2));
test3 := UnicodeString(PAnsiChar(test2));
OutputDebugStringW(PWideChar(test3));
Result := test3;
OutputDebugStringW(PWideChar(test3));
finally
SetLength(nameBuffer, 0);
end;
break;
end;
end;
finally
pFile.Free;
end;
end;
//---------------------------------------------------------------------------
This code works well until the final part of the GetFontNameFromFile() function. There, things start to get complicated. Indeed, I'm unable to convert the nameBuffer byte array to a string in a correct manner.
The first problem I met is that the nameBuffer may be a simple ASCII string, or an UTF16 string, depend on file (I tried with the emoji.ttf available in FireFox, that returns an ASCII string, and Tahoma.ttf from my Win installation, that returns a UTF16 string). I need a way to determine that, and I don't know if there is a function or class in the VCL to do that.
The second problem is the conversion itself. The above code works more or less, but I feel that is not a correct solution. When I try to convert to an UnicodeString directly from nameBuffer, I get some strange crashes. If I try to convert nameBuffer to an AnsiString, the conversion seems success, however a conversion like UnicodeString(AnsiString(nameBuffer)) fails.
And the code seems to be full of memory issues. As I'm new with Delphi, I'm not very comfortable with the memory usage. For example, I suspect several issues with the byte array when I activate the
FillChar(nameBuffer[0], nameRecord.m_StringLength + 1, $0);
line.
So anybody can analyse this code and points me what I doing wrong?
Thanks in advance,
Regards

Reading directory in delphi 7 gives nothing

I'm a delphi noob, and I simply try to read the the files in a directory (I will be doing sth with this files later).
I tried ouple methods, and nothing works - there is simply nothing outputed.
directoryPath := exePath + 'XML_out\'; //correct directory
wiadomosc := wiadomosc + sLineBreak + sLineBreak + 'FILES IN DIRECTORY:' + directoryPath; //will output correct directory
//first method
directoryEOFound:= False;
if FindFirst(directoryPath, faAnyFile, directoryRes) = 0 then
wiadomosc := wiadomosc + sLineBreak + 'DIRECTORY N)T FOUND' + sLineBreak //should save info about directory not found but return nothing
// exit //exit is killing app, like directory was not found.... but directory is there
else
while not directoryEOFound do begin
wiadomosc := wiadomosc + sLineBreak + directoryRes.Name; //gives nothing
directoryEOFound:= FindNext(directoryRes) <> 0;
end;
FindClose(directoryRes) ;
//second method
if FindFirst(directoryPath, faAnyFile, directoryRes) = 0 then try
repeat
if (directoryRes.Name = '.') or (directoryRes.Name = '..') then
continue;
wiadomosc := wiadomosc + sLineBreak + 'file: ' + directoryRes.Name; //gives nothing, i dont think its initiated
until FindNext(directoryRes) <> 0;
finally
SysUtils.FindClose(directoryRes);
end;
Neither method works, so maybe its a OS matter? (windows 7 64 bit) No errors in compilation offcourse.
You need to include a pattern to search for files. Replace
directoryPath := exePath + 'XML_out\';
with
directoryPath := exePath + 'XML_out\*';
The first block of code is odd. It appears to give up when FindFirst returns 0. But the 0 return value indicates success. So that condition is wrong. The second block of code looks reasonable.

NTQueryObject - STATUS_INVALID_INFO_CLASS error

when using the Delphi code provided as answer on this page,
Delphi - get what files are opened by an application
I get nice results on Windows 8 but an error on XP
in the provided function "GetObjectInfo" :
NTQueryObject called at line 4 is returning STATUS_INVALID_INFO_CLASS (3221225475).
It seems that the class ObjectNameInformation is not a valid info class.
I use Delphi 7.
program ListAllHandles;
{$APPTYPE CONSOLE}
uses
PSApi,
Windows,
SysUtils;
const
SystemHandleInformation = $10;
STATUS_SUCCESS = $00000000;
STATUS_BUFFER_OVERFLOW = $80000005;
STATUS_INFO_LENGTH_MISMATCH = $C0000004;
DefaulBUFFERSIZE = $100000;
type
OBJECT_INFORMATION_CLASS = (ObjectBasicInformation,ObjectNameInformation,ObjectTypeInformation,ObjectAllTypesInformation,ObjectHandleInformation );
SYSTEM_HANDLE=packed record
uIdProcess:ULONG;
ObjectType:UCHAR;
Flags :UCHAR;
Handle :Word;
pObject :Pointer;
GrantedAccess:ACCESS_MASK;
end;
PSYSTEM_HANDLE = ^SYSTEM_HANDLE;
SYSTEM_HANDLE_ARRAY = Array[0..0] of SYSTEM_HANDLE;
PSYSTEM_HANDLE_ARRAY= ^SYSTEM_HANDLE_ARRAY;
SYSTEM_HANDLE_INFORMATION=packed record
uCount:ULONG;
Handles:SYSTEM_HANDLE_ARRAY;
end;
PSYSTEM_HANDLE_INFORMATION=^SYSTEM_HANDLE_INFORMATION;
TNtQuerySystemInformation=function (SystemInformationClass:DWORD; SystemInformation:pointer; SystemInformationLength:DWORD; ReturnLength:PDWORD):THandle; stdcall;
TNtQueryObject =function (ObjectHandle:cardinal; ObjectInformationClass:OBJECT_INFORMATION_CLASS; ObjectInformation:pointer; Length:ULONG;ResultLength:PDWORD):THandle;stdcall;
UNICODE_STRING=packed record
Length :Word;
MaximumLength:Word;
Buffer :PWideChar;
end;
OBJECT_NAME_INFORMATION=UNICODE_STRING;
POBJECT_NAME_INFORMATION=^OBJECT_NAME_INFORMATION;
Var
NTQueryObject :TNtQueryObject;
NTQuerySystemInformation:TNTQuerySystemInformation;
function GetObjectInfo(hObject:cardinal; objInfoClass:OBJECT_INFORMATION_CLASS):LPWSTR;
var
pObjectInfo:POBJECT_NAME_INFORMATION;
HDummy :THandle;
dwSize :DWORD;
begin
Result:=nil;
dwSize := sizeof(OBJECT_NAME_INFORMATION);
pObjectInfo := AllocMem(dwSize);
HDummy := NTQueryObject(hObject, objInfoClass, pObjectInfo,dwSize, #dwSize);
if((HDummy = STATUS_BUFFER_OVERFLOW) or (HDummy = STATUS_INFO_LENGTH_MISMATCH)) then
begin
FreeMem(pObjectInfo);
pObjectInfo := AllocMem(dwSize);
HDummy := NTQueryObject(hObject, objInfoClass, pObjectInfo,dwSize, #dwSize);
end;
if((HDummy >= STATUS_SUCCESS) and (pObjectInfo.Buffer <> nil)) then
begin
Result := AllocMem(pObjectInfo.Length + sizeof(WCHAR));
CopyMemory(result, pObjectInfo.Buffer, pObjectInfo.Length);
end;
FreeMem(pObjectInfo);
end;
Procedure EnumerateOpenFiles();
var
sDummy : string;
hProcess : THandle;
hObject : THandle;
ResultLength: DWORD;
aBufferSize : DWORD;
aIndex : Integer;
pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
HDummy : THandle;
lpwsName : PWideChar;
lpwsType : PWideChar;
lpszProcess : PAnsiChar;
begin
AbufferSize := DefaulBUFFERSIZE;
pHandleInfo := AllocMem(AbufferSize);
HDummy := NTQuerySystemInformation(DWORD(SystemHandleInformation), pHandleInfo,AbufferSize, #ResultLength); //Get the list of handles
if(HDummy = STATUS_SUCCESS) then //If no error continue
begin
for aIndex:=0 to pHandleInfo^.uCount-1 do //iterate the list
begin
hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pHandleInfo.Handles[aIndex].uIdProcess); //open the process to get aditional info
if(hProcess <> INVALID_HANDLE_VALUE) then //Check valid handle
begin
hObject := 0;
if DuplicateHandle(hProcess, pHandleInfo.Handles[aIndex].Handle,GetCurrentProcess(), #hObject, STANDARD_RIGHTS_REQUIRED,FALSE, 0) then //Get a copy of the original handle
begin
lpwsName := GetObjectInfo(hObject, ObjectNameInformation); //Get the filename linked to the handle
if (lpwsName <> nil) then
begin
lpwsType := GetObjectInfo(hObject, ObjectTypeInformation);
lpszProcess := AllocMem(MAX_PATH);
if GetModuleFileNameEx(hProcess, 0,lpszProcess, MAX_PATH)<>0 then //get the name of the process
sDummy:=ExtractFileName(lpszProcess)
else
sDummy:= 'System Process';
Writeln('PID ',pHandleInfo.Handles[aIndex].uIdProcess);
Writeln('Handle ',pHandleInfo.Handles[aIndex].Handle);
Writeln('Process ',sDummy);
Writeln('FileName ',string(lpwsName));
Writeln;
FreeMem(lpwsName);
FreeMem(lpwsType);
FreeMem(lpszProcess);
end;
CloseHandle(hObject);
end;
CloseHandle(hProcess);
end;
end;
end;
FreeMem(pHandleInfo);
Any help ?
There are a number of errors in your translation:
In C an enum has a minimum size of 4 bytes, so you should set {$ENUMSIZE 4}
Records should not be packed but aligned
NtQueryObject doesn't return a handle but an NTSTATUS
My advise is to use the existing translations in the Jedi Apilib since they are time tested. You need the JwaNative unit.
On my blog you can find a complete example on enumerating all handles: http://www.remkoweijnen.nl/blog/2012/03/07/running-multiple-instances-of-lync-howto/

Resources