Hoi
Ik heb iets vreemd in een functie waar ik al dagen in aan het zoeken ben.
In een functie (volledig gestrip met alleen het error gedeelte) vraag ik het volume label of drive mapping op.
Doe ik dit voor alle 26 mogelijke driveletters los, dan gaat het prima, doe ik dit in een loop van 0..25 dan heb ik een memory leak.
De standaard API's bieden geen functionaliteit voor drives die wel als driveletter in Windows aanwezig zijn maar op dat moment niet beschikbaar zijn (disconnected).
In mijn situatie heb ik een netwerk media box die standaard uit staat, drive M: is dan wel aanwezig binnen Windows maar drive is disconnected.
Windows laat dit zelf overigens wel goed zien.
Ik hoop dat iemand me hiermee kan helpen want ik kom er niet uit (mijn debugging skills ontbreken bij deze een beetje )
In de gestripte code bereik ik hetzelfde as wat Windows laat zien en kan opvragen wat de naam van drive M: is.
Code:
program TSTDiskInfoMemLeak;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
WinAPI.Windows,
Winapi.ShellAPI;
type
TDiskSign = string[2];
TDiskType = (dtUnknown, dtNotExists, dtRemovable, dtFixed, dtRemote, dtCDROM, dtRAMDisk, dtRemovableNotConnected);
TDiskInfo = record
DiskSign : TDiskSign;
DiskType : TDiskType;
VolumeLabel : string;
ImageIndex : integer;
end;
function DiskTypeToStr (aDiskType: TDiskType) : string;
begin
case aDiskType of
dtUnknown : result := 'Unknown';
dtNotExists : result := 'Does''t exists';
dtRemovable : result := 'Removable';
dtFixed : result := 'Fixed';
dtRemote : result := 'Remote';
dtCDROM : result := 'CDrom';
dtRAMDisk : result := 'RAMdisk';
dtRemovableNotConnected : result := 'Removable disconnected';
end;
end;
function GetDiskInfo (aDiskSign : TDiskSign) : TDiskInfo;
var
lpnLength : Cardinal;
lError : DWORD;
lBufVolumeLabel : PChar;
begin
Result.DiskSign := aDiskSign; // TDiskInfo.Sign = Driveletter STRING[2]
Result.DiskType := dtUnknown; // Init
Result.VolumeLabel := ''; // Init
Result.ImageIndex := -1; // Init
case GetDriveType(PChar(IncludeTrailingPathDelimiter(string(aDiskSign)))) of // Check if drive removable, fixed, CD-ROM, RAM disk, or network drive.
DRIVE_UNKNOWN : Result.DiskType := dtUnknown; // The drive type cannot be determined
DRIVE_NO_ROOT_DIR : Result.DiskType := dtNotExists; // The root path is invalid. For example, no volume is mounted at the path.
DRIVE_REMOVABLE : Result.DiskType := dtRemovable; // The disk can be removed from the drive.
DRIVE_FIXED : Result.DiskType := dtFixed; // The disk cannot be removed from the drive
DRIVE_REMOTE : Result.DiskType := dtRemote; // The drive is a remote (network) drive
DRIVE_CDROM : Result.DiskType := dtCDROM; // The drive is a CD-ROM drive
DRIVE_RAMDISK : Result.DiskType := dtRAMDisk; // The drive is a RAM disk
end;
if Result.DiskType = dtNotExists then // if NotExists then start checking for Disconnected drive
begin
lpnLength := 0; // Init
lError := WNetGetConnection(PChar(aDiskSign), nil, lpnLength); // Get Size for lBufVolumeLabel in lpnLength
if lError = ERROR_MORE_DATA then // size received in lpnLength
begin
lBufVolumeLabel := AllocMem(lpnLength); // Alloc memory for VolumeLabel buffer
try
lError := WNetGetConnection(PChar(aDiskSign), lBufVolumeLabel, lpnLength); // Get network name
if lError = ERROR_CONNECTION_UNAVAIL then // It exists but is unavailable
begin
Result.VolumeLabel := lBufVolumeLabel; // <<<<<<<<<<<<<<<<<<< MEM LEAK // Return volume label
Result.DiskType := dtRemovableNotConnected; // Return DiskType
Result.ImageIndex := SIID_DRIVENETDISABLED; // Set imageindex to disconnected icon
end
else
Result.DiskType := dtNotExists; // otherwise reurn dtNotExists
finally
FreeMem(lBufVolumeLabel, lpnLength); // Free Memory
end;
end;
end;
end;
var
lDiskInfo : TDiskInfo;
I : byte;
begin
ReportMemoryleaksOnShutdown := true;
try
for I := 0 to 25 do // Loop through all possible drives
// I := 12; // or use one
begin
FillChar(lDiskInfo, SizeOf(lDiskInfo), #0); // Clear the DiskInfo record
lDiskInfo := GetDiskInfo (shortstring(Char(I + Ord('A'))+':')); // Driveletter
WriteLn (format('I=%d Drive=%s',[I,lDiskInfo.DiskSign] ));
if lDiskInfo.DiskType <> dtNotExists then
begin
WriteLn(format('%-30s : %s',['DiskSign' ,lDiskInfo.DiskSign]));
WriteLn(format('%-30s : %s',['DiskType' ,DiskTypeToStr(lDiskInfo.DiskType)]));
WriteLn(format('%-30s : %s',['VolumeLabel' ,lDiskInfo.VolumeLabel]));
//WriteLn(format('%-30s : %d',['ImageIndex' ,lDiskInfo.ImageIndex]));
WriteLn('--------------------------------------------------------------------------------');
end
else
WriteLn('--------------------------------------------------------------------------------');
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.
Draai ik dit 26x los, geen probleem, in een loop krijgt ik volgende error.
Code:
I=0 Drive=A:
--------------------------------------------------------------------------------
I=1 Drive=B:
--------------------------------------------------------------------------------
I=2 Drive=C:
DiskSign : C:
DiskType : Fixed
VolumeLabel :
--------------------------------------------------------------------------------
I=3 Drive=D:
DiskSign : D:
DiskType : Fixed
VolumeLabel :
--------------------------------------------------------------------------------
I=4 Drive=E:
DiskSign : E:
DiskType : Fixed
VolumeLabel :
--------------------------------------------------------------------------------
I=5 Drive=F:
DiskSign : F:
DiskType : Removable
VolumeLabel :
--------------------------------------------------------------------------------
I=6 Drive=G:
--------------------------------------------------------------------------------
I=7 Drive=H:
--------------------------------------------------------------------------------
I=8 Drive=I:
--------------------------------------------------------------------------------
I=9 Drive=J:
--------------------------------------------------------------------------------
I=10 Drive=K:
--------------------------------------------------------------------------------
I=11 Drive=L:
--------------------------------------------------------------------------------
I=12 Drive=M:
DiskSign : M:
DiskType : Removable disconnected
VolumeLabel : \\192.168.0.240\Disk_sda1
--------------------------------------------------------------------------------
I=13 Drive=N:
--------------------------------------------------------------------------------
I=14 Drive=O:
--------------------------------------------------------------------------------
I=15 Drive=P:
--------------------------------------------------------------------------------
I=16 Drive=Q:
--------------------------------------------------------------------------------
I=17 Drive=R:
--------------------------------------------------------------------------------
I=18 Drive=S:
--------------------------------------------------------------------------------
I=19 Drive=T:
DiskSign : T:
DiskType : Remote
VolumeLabel :
--------------------------------------------------------------------------------
I=20 Drive=U:
DiskSign : U:
DiskType : Remote
VolumeLabel :
--------------------------------------------------------------------------------
I=21 Drive=V:
--------------------------------------------------------------------------------
I=22 Drive=W:
--------------------------------------------------------------------------------
I=23 Drive=X:
--------------------------------------------------------------------------------
I=24 Drive=Y:
--------------------------------------------------------------------------------
I=25 Drive=Z:
DiskSign : Z:
DiskType : Remote
VolumeLabel :
--------------------------------------------------------------------------------
Unexpected Memory Leak
An unexpected memory leak has occurred. The unexpected small block leaks are:
61 - 68 bytes: UnicodeString x 1
Bookmarks