Some more info on the memory leak. I ran this testprogram:
Delphi-Quellcode:
program WTSLeak;
{$APPTYPE CONSOLE}
uses
SysUtils,
JwaWindows;
type
{ array of TWtsSessionInfoA }
PWTSSessionInfoAArray = ^TWTSSessionInfoAArray;
TWTSSessionInfoAArray = array[0..ANYSIZE_ARRAY-1] of TWtsSessionInfoA;
{ array of TWtsSessionInfoW }
PWTSSessionInfoWArray = ^TWTSSessionInfoWArray;
TWTSSessionInfoWArray = array[0..ANYSIZE_ARRAY-1] of TWtsSessionInfoW;
var
SessionInfoPtr: PWTSSessionInfoWArray;
pCount: DWORD;
i,j: Integer;
bRes: Boolean;
ppBuffer: PWideChar;
pBytesReturned: DWORD;
begin
for j := 0 to 10000 do
begin
bRes := WTSEnumerateSessionsW(WTS_CURRENT_SERVER, 0, 1,
PWtsSessionInfoW(SessionInfoPtr), pCount);
if bRes then
begin
for i := 0 to PCount - 1 do
begin
bRes := WTSQuerySessionInformationW(WTS_CURRENT_SERVER,
SessionInfoPtr^[i].SessionId, WTSApplicationName, Pointer(ppBuffer),
pBytesReturned);
if bRes then
begin
WriteLn(Format('ApplicationName=%s', [ppBuffer]));
WTSFreeMemory(Pointer(ppBuffer));
end
else begin
WriteLn(Format('WTSQuerySessionInformation for Session %d failed with error %s',
[SessionInfoPtr^[i].SessionId, SysErrorMessage(GetLastError)]));
end;
end;
WTSFreeMemory(SessionInfoPtr);
end
else begin
WriteLn(Format('WTSEnumerateSessions failed with error %s',
[SysErrorMessage(GetLastError)]));
end;
end;
ReadLn;
end.
If I look in the VMSize/Private Working Set column of task manager (do not use the Memory Usage/Working Set column) we can cleary see that we leak memory on every call to WTSQuerySessionInformation. I also ran it through a profiler which clearly showed that the memory is being allocated in wtsapi32.dll. Further testing shows that the memory is only leaked when the call to WTSQuerySessionInformation fails (it does this on special sessions like the console and the listener sessions). If the call does fail wtsapi leaks exactly 2664 bytes on each call, which is the size of WinStationQueryInformation structure 1 (this is an undocumented
api called by wtsapi32.dll internally).