mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-07 09:25:33 +00:00
2028 lines
64 KiB
ObjectPascal
2028 lines
64 KiB
ObjectPascal
{******************************************************************}
|
|
{ This Unit provides Delphi translations of some functions from }
|
|
{ WinSta.dll and Utildll. }
|
|
{ Most functions are undocumented and somehow related to }
|
|
{ Terminal Server }
|
|
{ }
|
|
{ Author: Remko Weijnen (r dot weijnen at gmail dot com) }
|
|
{ Documentation can be found at www.remkoweijnen.nl }
|
|
{ }
|
|
{ The contents of this file are subject to }
|
|
{ the Mozilla Public License Version 1.1 (the "License"); you may }
|
|
{ not use this file except in compliance with the License. You may }
|
|
{ obtain a copy of the License at }
|
|
{ http://www.mozilla.org/MPL/MPL-1.1.html }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an }
|
|
{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
|
|
{ implied. See the License for the specific language governing }
|
|
{ rights and limitations under the License. }
|
|
{******************************************************************}
|
|
|
|
{$IFNDEF JWA_OMIT_SECTIONS}
|
|
|
|
unit JwaWinSta;
|
|
|
|
|
|
interface
|
|
|
|
{$I ..\Includes\JediAPILib.inc}
|
|
|
|
uses
|
|
SysUtils, JwaWinType, // JwaWinType must be declared before JwaWinBase because of duplicate declaration of FILETIME
|
|
JwaWinBase, JwaWinError, JwaNTStatus, JwaWinNT, JwaWinsock2,
|
|
JwaWinSvc, JwaWtsApi32, JwaWinNLS, JwaNative, JwaBitFields;
|
|
{$ENDIF JWA_OMIT_SECTIONS}
|
|
|
|
|
|
{$IFNDEF JWA_IMPLEMENTATIONSECTION}
|
|
//==============================================================================
|
|
// Defines
|
|
//==============================================================================
|
|
const
|
|
SERVERNAME_CURRENT = 0;
|
|
|
|
// old (reversed) constants used for WinStationGetTermSrvCounters
|
|
{ TOTAL_SESSIONS_CREATED_COUNTER = 1;
|
|
TOTAL_SESSIONS_DISCONNECTED_COUNTER = 2;
|
|
TOTAL_SESSIONS_RECONNECTED_COUNTER = 3;
|
|
TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER = 4;
|
|
TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER = 5;
|
|
TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER_2 = 6; //TermSrvSuccLocalLogons;
|
|
TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER_2 = 7;}
|
|
|
|
// Max lenght for ElapsedTimeString (server 2008 version of utildll
|
|
// fixes size at 15, so that's assumed to be safe
|
|
ELAPSED_TIME_STRING_LENGTH = 15;
|
|
|
|
// WdFlag = WinStation Driver Flag, it is returned in class 3 (WdConfig)
|
|
// of WinStationQueryInformation and has a different value which
|
|
// depends on the protocol. WdFlag is also returned by QueryCurrentWinStation
|
|
WD_FLAG_CONSOLE_XP = $24; // XP
|
|
WD_FLAG_CONSOLE = $34; // 2003/2008
|
|
WD_FLAG_RDP = $36; // XP/2003/2008
|
|
WD_FLAG_ICA = $6E; // Citrix Presentation Server
|
|
// (value from Citrix PS4, other versions could be different!)
|
|
|
|
const
|
|
// WdFlag: Driver flags. SHOULD be any bitwise OR combination of the following
|
|
// values.
|
|
WDF_UNUSED = $1; // Not used.
|
|
WDF_SHADOW_SOURCE = $2; // Valid shadow source.
|
|
WDF_SHADOW_TARGET = $4; // Valid shadow target.
|
|
WDF_OTHER = $8; // Other protocol.
|
|
WDF_TSHARE = $10; // Remote Protocol used by Terminal Services.
|
|
WDF_DYNAMIC_RECONNECT = $20; // Session can resize display at reconnect.
|
|
WDF_USER_VCIOCTL = $40; // User mode applications can send virtual channel IOCTL
|
|
WDF_SUBDESKTOP = $8000; // Sub-desktop session.
|
|
|
|
WDPREFIX_LENGTH = 12;
|
|
STACK_ADDRESS_LENGTH = 128;
|
|
MAX_BR_NAME = 65;
|
|
DIRECTORY_LENGTH = 256;
|
|
INITIALPROGRAM_LENGTH = 256;
|
|
{$IFNDEF JWA_INCLUDEMODE}
|
|
AF_INET = 2; // internetwork: UDP, TCP, etc.
|
|
{$EXTERNALSYM AF_INET}
|
|
AF_INET6 = 23; // Internetwork Version 6
|
|
{$EXTERNALSYM AF_INET6}
|
|
|
|
USERNAME_LENGTH = 20;
|
|
DOMAIN_LENGTH = 17;
|
|
{$ENDIF JWA_INCLUDEMODE}
|
|
PASSWORD_LENGTH = 14;
|
|
NASISPECIFICNAME_LENGTH = 14;
|
|
NASIUSERNAME_LENGTH = 47;
|
|
NASIPASSWORD_LENGTH = 24;
|
|
NASISESSIONNAME_LENGTH = 16;
|
|
NASIFILESERVER_LENGTH = 47;
|
|
|
|
CLIENTDATANAME_LENGTH = 7;
|
|
{$IFNDEF JWA_INCLUDEMODE}
|
|
CLIENTNAME_LENGTH = 20;
|
|
CLIENTADDRESS_LENGTH = 30;
|
|
{$ENDIF JWA_INCLUDEMODE}
|
|
|
|
IMEFILENAME_LENGTH = 32;
|
|
CLIENTLICENSE_LENGTH = 32;
|
|
CLIENTMODEM_LENGTH = 40;
|
|
CLIENT_PRODUCT_ID_LENGTH = 32;
|
|
|
|
MAX_COUNTER_EXTENSIONS = 2; {/* actual value not known*/}
|
|
|
|
|
|
{$IFNDEF JWA_INCLUDEMODE}
|
|
WINSTATIONNAME_LENGTH = 32;
|
|
{$ENDIF JWA_INCLUDEMODE}
|
|
|
|
|
|
type
|
|
_WINSTATIONINFOCLASS = (
|
|
WinStationCreateData,
|
|
WinStationConfiguration,
|
|
WinStationPdParams,
|
|
WinStationWd,
|
|
WinStationPd,
|
|
WinStationPrinter,
|
|
WinStationClient,
|
|
WinStationModules,
|
|
WinStationInformation,
|
|
WinStationTrace,
|
|
WinStationBeep,
|
|
WinStationEncryptionOff,
|
|
WinStationEncryptionPerm,
|
|
WinStationNtSecurity, // vista returns Incorrect function
|
|
WinStationUserToken,
|
|
WinStationUnused1,
|
|
WinStationVideoData, // vista returns Incorrect function
|
|
WinStationInitialProgram,
|
|
WinStationCd,
|
|
WinStationSystemTrace,
|
|
WinStationVirtualData,
|
|
WinStationClientData,
|
|
WinStationSecureDesktopEnter, // not supported on RDP (ica?)
|
|
WinStationSecureDesktopExit, // not supported on RDP (ica?)
|
|
WinStationLoadBalanceSessionTarget,
|
|
WinStationLoadIndicator,
|
|
WinStationShadowInfo,
|
|
WinStationDigProductId, // vista returns Incorrect function
|
|
WinStationLockedState,
|
|
WinStationRemoteAddress,
|
|
WinStationIdleTime,
|
|
WinStationLastReconnectType,
|
|
WinStationDisallowAutoReconnect,
|
|
WinStationMprNotifyInfo,
|
|
WinStationExecSrvSystemPipe,
|
|
WinStationSmartCardAutoLogon,
|
|
WinStationIsAdminLoggedOn,
|
|
WinStationReconnectedFromId,
|
|
WinStationEffectsPolicy
|
|
);
|
|
|
|
WINSTATIONINFOCLASS = _WINSTATIONINFOCLASS;
|
|
TWinStationInfoClass = WINSTATIONINFOCLASS;
|
|
|
|
{ old declarations of infoclasses which were reversed:
|
|
WinStationCreate = 0;
|
|
WinStationClient = 1;
|
|
WdConfig = 3;
|
|
WinStationConfig = 6;
|
|
WinStationInformation = 8;
|
|
WinStationBeep = 10; // Calls MessageBeep
|
|
WinStationToken = 14;
|
|
WinStationResolution = 16;
|
|
WinStationShadowInformation = 26;
|
|
WinStationProductId = 27;
|
|
WinStationLock = 28; // Locks or Unlocks the WinStation
|
|
WinStationRemoteAddress = 29;
|
|
WinStationPipeInformation = 33; }
|
|
|
|
const
|
|
SECONDS_PER_DAY = 86400;
|
|
SECONDS_PER_HOUR = 3600;
|
|
SECONDS_PER_MINUTE = 60;
|
|
|
|
// shadow state constants (class 26)
|
|
SHADOW_STATE_NONE = 0;
|
|
SHADOW_STATE_SHADOWING = 1;
|
|
SHADOW_STATE_BEING_SHADOWED = 2;
|
|
|
|
// shadow mode constants (class 26)
|
|
SHADOW_MODE_NONE_ALLOWED = 0;
|
|
SHADOW_MODE_FULL_CONTROL_WITH_PERMISSION = 1;
|
|
SHADOW_MODE_FULL_CONTROL_WITHOUT_PERMISSION = 2;
|
|
SHADOW_MODE_VIEW_ONLY_WITH_PERMISSION = 3;
|
|
SHADOW_MODE_VIEW_ONLY_WITHOUT_PERMISSION = 4;
|
|
|
|
type
|
|
// This type is used for ElapsedTimeString
|
|
TDiffTime = record
|
|
wDays: Word;
|
|
wHours: Word;
|
|
wMinutes: Word;
|
|
wSeconds: Word;
|
|
wMilliseconds: Word;
|
|
end;
|
|
PDiffTime = ^TDiffTime;
|
|
|
|
// This type is used for WinStationQueryLogonCredentialsW
|
|
// dwType can be one of the types defined in JwaWinWlx
|
|
// WLX_CREDENTIAL_TYPE_V1_0 or WLX_CREDENTIAL_TYPE_V2_0 = 2
|
|
_LOGON_CREDENTIALSW = record
|
|
dwType: DWORD;
|
|
pUsername: PWideChar;
|
|
pDomain: PWideChar;
|
|
pPassword: PWideChar;
|
|
Unknown2 : DWORD;
|
|
Unknown3 : DWORD;
|
|
Unknown4: DWORD;
|
|
end;
|
|
PLOGON_CREDENTIALSW = ^_LOGON_CREDENTIALSW;
|
|
TLogonCredentialsW = _LOGON_CREDENTIALSW;
|
|
PLogonCredentialsW = PLOGON_CREDENTIALSW;
|
|
|
|
// WinStationToken (14)
|
|
// You must set ProcessId and ThreadId to the valid values
|
|
// Function actually duplicates a token handle to the
|
|
// process, which id (ProcessId and ThreadId) are set here.
|
|
_WINSTATIONUSERTOKEN = record
|
|
ProcessId: DWORD;
|
|
ThreadId: DWORD;
|
|
UserToken: HANDLE;
|
|
end;
|
|
TWinStationUserToken = _WINSTATIONUSERTOKEN; {WinStationUserToken is alreay an enum}
|
|
PWINSTATIONUSERTOKEN = ^_WINSTATIONUSERTOKEN;
|
|
|
|
_WINSTA_USER_TOKEN = record
|
|
ProcessId : DWORD;
|
|
ThreadId : DWORD;
|
|
TokenHandle : THandle;
|
|
end;
|
|
PWINSTA_USER_TOKEN = ^_WINSTA_USER_TOKEN;
|
|
TWinstaUserToken = _WINSTA_USER_TOKEN;
|
|
PWinstaUserToken = ^TWinstaUserToken;
|
|
|
|
_LOADFACTORTYPE = (
|
|
ErrorConstraint,
|
|
PagedPoolConstraint,
|
|
NonPagedPoolConstraint,
|
|
AvailablePagesConstraint,
|
|
SystemPtesConstraint,
|
|
CPUConstraint );
|
|
LOADFACTORTYPE = _LOADFACTORTYPE;
|
|
TLoadFactorType = _LOADFACTORTYPE;
|
|
|
|
_WINSTATIONLOADINDICATORDATA = record
|
|
RemainingSessionCapacity: ULONG;
|
|
LoadFactor: LOADFACTORTYPE;
|
|
TotalSessions: ULONG;
|
|
DisconnectedSessions: ULONG;
|
|
IdleCPU: LARGE_INTEGER;
|
|
TotalCPU: LARGE_INTEGER;
|
|
RawSessionCapacity: ULONG;
|
|
reserved1: ULONG;
|
|
SessionAvgPaged: ULONG; { undocumented }
|
|
reserved3: ULONG;
|
|
SessionAvgCommit: ULONG; { undocumented }
|
|
SessionAvgPte: ULONG; { undocumented }
|
|
SessionAvgPaged2: ULONG; { undocumented }
|
|
reserved: array[0..2] of ULONG
|
|
end {_WINSTATIONLOADINDICATORDATA};
|
|
WINSTATIONLOADINDICATORDATA = _WINSTATIONLOADINDICATORDATA;
|
|
TWinStationLoadIndicatorData = WINSTATIONLOADINDICATORDATA;
|
|
PWINSTATIONLOADINDICATORDATA = ^_WINSTATIONLOADINDICATORDATA;
|
|
|
|
_TS_UNICODE_STRING = record
|
|
Length: USHORT;
|
|
MaximumLength: USHORT;
|
|
Buffer: PWSTR;
|
|
end;
|
|
TS_UNICODE_STRING = _TS_UNICODE_STRING;
|
|
TTSUnicodeString = TS_UNICODE_STRING;
|
|
|
|
_TS_SYS_PROCESS_INFORMATION = record
|
|
NextEntryOffset: ULONG;
|
|
NumberOfThreads: ULONG;
|
|
SpareLi1: LARGE_INTEGER;
|
|
SpareLi2: LARGE_INTEGER;
|
|
SpareLi3: LARGE_INTEGER;
|
|
CreateTime: LARGE_INTEGER;
|
|
UserTime: LARGE_INTEGER;
|
|
KernelTime: LARGE_INTEGER;
|
|
ImageName: TS_UNICODE_STRING;
|
|
BasePriority: LONG;
|
|
UniqueProcessId: DWORD;
|
|
InheritedFromUniqueProcessId: DWORD;
|
|
HandleCount: ULONG;
|
|
SessionId: ULONG;
|
|
SpareUl3: ULONG;
|
|
PeakVirtualSize: SIZE_T;
|
|
VirtualSize: SIZE_T;
|
|
PageFaultCount: ULONG;
|
|
PeakWorkingSetSize: ULONG;
|
|
WorkingSetSize: ULONG;
|
|
QuotaPeakPagedPoolUsage: SIZE_T;
|
|
QuotaPagedPoolUsage: SIZE_T;
|
|
QuotaPeakNonPagedPoolUsage: SIZE_T;
|
|
QuotaNonPagedPoolUsage: SIZE_T;
|
|
PagefileUsage: SIZE_T;
|
|
PeakPagefileUsage: SIZE_T;
|
|
PrivatePageCount: SIZE_T;
|
|
end;
|
|
TS_SYS_PROCESS_INFORMATION = _TS_SYS_PROCESS_INFORMATION;
|
|
PTS_SYS_PROCESS_INFORMATION = ^TS_SYS_PROCESS_INFORMATION;
|
|
TTSSysProcessInformation = TS_SYS_PROCESS_INFORMATION;
|
|
PTSSysProcessInformation = PTS_SYS_PROCESS_INFORMATION;
|
|
|
|
_TS_ALL_PROCESSES_INFO = record
|
|
pTsProcessInfo: PTS_SYS_PROCESS_INFORMATION;
|
|
SizeOfSid: DWORD;
|
|
UserSid: PSID;
|
|
end;
|
|
TS_ALL_PROCESSES_INFO = _TS_ALL_PROCESSES_INFO;
|
|
PTS_ALL_PROCESSES_INFO = ^TS_ALL_PROCESSES_INFO;
|
|
TTSAllProcessesInfo = TS_ALL_PROCESSES_INFO;
|
|
PTSAllProcessesInfo = PTS_ALL_PROCESSES_INFO;
|
|
|
|
{ helper array to ease enumeration }
|
|
TS_ALL_PROCESSES_INFO_ARRAY = array [0..ANYSIZE_ARRAY-1] of TS_ALL_PROCESSES_INFO;
|
|
PTS_ALL_PROCESSES_INFO_ARRAY = ^TS_ALL_PROCESSES_INFO_ARRAY;
|
|
TTSAllProcessesInfoArray = TS_ALL_PROCESSES_INFO_ARRAY;
|
|
PTSAllProcessesInfoArray = PTS_ALL_PROCESSES_INFO_ARRAY;
|
|
|
|
// The following types are used for WinStationGetAllProcesses
|
|
// _WINSTA_PROCESS_INFO
|
|
_WINSTA_PROCESS_INFO = record
|
|
ExtendedInfo: PSYSTEM_PROCESSES;
|
|
dwSidLength: DWORD;
|
|
pUserSid: PSID;
|
|
end;
|
|
PWINSTA_PROCESS_INFO = ^_WINSTA_PROCESS_INFO;
|
|
TWinstaProcessInfo = _WINSTA_PROCESS_INFO;
|
|
PWinstaProcessInfo = PWINSTA_PROCESS_INFO;
|
|
|
|
// Array of _WINSTA_PROCESS_INFO
|
|
_WINSTA_PROCESS_INFO_ARRAY = array [0..ANYSIZE_ARRAY-1] of _WINSTA_PROCESS_INFO;
|
|
PWINSTA_PROCESS_INFO_ARRAY= ^_WINSTA_PROCESS_INFO_ARRAY;
|
|
TWinstaProcessInfoArray = _WINSTA_PROCESS_INFO_ARRAY;
|
|
PWinstaProcessInfoArray = PWINSTA_PROCESS_INFO_ARRAY;
|
|
|
|
// The following types are used for WinStationQueryInformationW
|
|
|
|
// WinStationCreate (0)
|
|
// Both functions (A and W) shares the single definition
|
|
|
|
_WINSTATION_CREATE = record
|
|
EnableWinStation : BOOL;
|
|
MaxInstanceCount : DWORD;
|
|
end;
|
|
PWINSTATION_CREATE = ^_WINSTATION_CREATE;
|
|
TWinStationCreate = _WINSTATION_CREATE;
|
|
PWinStationCreate = PWINSTATION_CREATE;
|
|
|
|
// WinStationClient (1)
|
|
// returns information as provided by the
|
|
// Terminal Server client (mstsc).
|
|
{ _WINSTATION_CLIENTW = record
|
|
Comment: array[0..59] of WCHAR;
|
|
Reserved1: array[0..2] of DWORD;
|
|
ClientUsername: array[0..20] of WCHAR;
|
|
ClientDomain: array[0..17] of WCHAR;
|
|
ClientPassword: array[0..255] of WCHAR; // this was fixec win2000 SP4
|
|
Reserved2: array[0..1635] of BYTE;
|
|
Reserved3: array[0..6] of DWORD;
|
|
Reserved4: array[0..275] of BYTE;
|
|
end;
|
|
PWINSTATION_CLIENTW = ^_WINSTATION_CLIENTW;
|
|
TWinStationClientW = _WINSTATION_CLIENTW;
|
|
PWinStationClientW = PWINSTATION_CLIENTW;}
|
|
|
|
TWinStationClientFlags = Set Of (
|
|
fTextOnly, //: 1
|
|
fDisableCtrlAltDel, //: 1
|
|
fMouse, //: 1
|
|
fDoubleClickDetect, //: 1
|
|
fINetClient, //: 1
|
|
fWinStationClientPromptForPassword, //: 1
|
|
fMaximizeShell, //: 1
|
|
fEnableWindowsKey, //: 1
|
|
fRemoteConsoleAudio, //: 1
|
|
fWinStationClientPasswordIsScPin, //: 1
|
|
fNoAudioPlayback, //: 1
|
|
fUsingSavedCreds, //: 1
|
|
{$IFDEF DELPHI6_UP}
|
|
_TWinStationClientFlagsAlign = al32Bit
|
|
{$ELSE}
|
|
_TWinStationClientFlagsAlign1,
|
|
_TWinStationClientFlagsAlign2,
|
|
_TWinStationClientFlagsAlign3,
|
|
_TWinStationClientFlagsAlign4,
|
|
_TWinStationClientFlagsAlign5,
|
|
_TWinStationClientFlagsAlign6,
|
|
_TWinStationClientFlagsAlign7,
|
|
_TWinStationClientFlagsAlign8,
|
|
_TWinStationClientFlagsAlign9,
|
|
_TWinStationClientFlagsAlign10,
|
|
_TWinStationClientFlagsAlign11,
|
|
_TWinStationClientFlagsAlign12,
|
|
_TWinStationClientFlagsAlign13,
|
|
_TWinStationClientFlagsAlign14,
|
|
_TWinStationClientFlagsAlign15,
|
|
_TWinStationClientFlagsAlign16,
|
|
_TWinStationClientFlagsAlign17,
|
|
_TWinStationClientFlagsAlign18,
|
|
_TWinStationClientFlagsAlign19,
|
|
_TWinStationClientFlagsAlign20,
|
|
_TWinStationClientFlagsAlign21,
|
|
_TWinStationClientFlagsAlign22,
|
|
_TWinStationClientFlagsAlign23,
|
|
_TWinStationClientFlagsAlign24,
|
|
_TWinStationClientFlagsAlign25,
|
|
_TWinStationClientFlagsAlign26,
|
|
_TWinStationClientFlagsAlign27,
|
|
_TWinStationClientFlagsAlign28,
|
|
_TWinStationClientFlagsAlign29,
|
|
_TWinStationClientFlagsAlign30,
|
|
_TWinStationClientFlagsAlign31,
|
|
_TWinStationClientFlagsAlign32
|
|
{$ENDIF}
|
|
);
|
|
|
|
_TS_SYSTEMTIME = record
|
|
wYear: USHORT;
|
|
wMonth: USHORT;
|
|
wDayOfWeek: USHORT;
|
|
wDay: USHORT;
|
|
wHour: USHORT;
|
|
wMinute: USHORT;
|
|
wSecond: USHORT;
|
|
wMilliseconds: USHORT;
|
|
end {_TS_SYSTEMTIME};
|
|
TS_SYSTEMTIME = _TS_SYSTEMTIME;
|
|
|
|
_TS_TIME_ZONE_INFORMATION = record
|
|
Bias: LongInt;
|
|
StandardName: Array[0..31] of WCHAR;
|
|
StandardDate: TS_SYSTEMTIME;
|
|
StandardBias: LongInt;
|
|
DaylightName: Array[0..31] of WCHAR;
|
|
DaylightDate: TS_SYSTEMTIME;
|
|
DaylightBias: LongInt;
|
|
end {_TS_TIME_ZONE_INFORMATION};
|
|
TS_TIME_ZONE_INFORMATION = _TS_TIME_ZONE_INFORMATION;
|
|
|
|
|
|
const
|
|
TS_PERF_DISABLE_NOTHING = $0;
|
|
TS_PERF_DISABLE_WALLPAPER = $1;
|
|
TS_PERF_DISABLE_FULLWINDOWDRAG = $2;
|
|
TS_PERF_DISABLE_MENUANIMATIONS = $4;
|
|
TS_PERF_DISABLE_THEMING = $8;
|
|
TS_PERF_ENABLE_ENHANCED_GRAPHICS = $10;
|
|
TS_PERF_DISABLE_CURSOR_SHADOW = $20;
|
|
TS_PERF_DISABLE_CURSORSETTINGS = $40;
|
|
TS_PERF_ENABLE_FONT_SMOOTHING= $80;
|
|
TS_PERF_ENABLE_DESKTOP_COMPOSITION = $100;
|
|
TS_PERF_DEFAULT_NONPERFCLIENT_SETTING = $40000000;
|
|
TS_PERF_RESERVED1 = $80000000;
|
|
|
|
type
|
|
_WINSTATIONCLIENTW = record
|
|
WinStationClientFlags: TWinStationClientFlags;
|
|
ClientName: Array[0..CLIENTNAME_LENGTH] of WCHAR;
|
|
Domain: Array[0..DOMAIN_LENGTH] of WCHAR;
|
|
UserName: Array[0..USERNAME_LENGTH] of WCHAR;
|
|
Password: Array[0..PASSWORD_LENGTH] of WCHAR;
|
|
WorkDirectory: Array[0..DIRECTORY_LENGTH] of WCHAR;
|
|
InitialProgram: Array[0..INITIALPROGRAM_LENGTH] of WCHAR;
|
|
SerialNumber: ULONG;
|
|
EncryptionLevel: BYTE;
|
|
ClientAddressFamily: ULONG;
|
|
ClientAddress: Array[0..CLIENTADDRESS_LENGTH] of WCHAR;
|
|
HRes: USHORT;
|
|
VRes: USHORT;
|
|
ColorDepth: USHORT;
|
|
ProtocolType: USHORT;
|
|
KeyboardLayout: ULONG;
|
|
KeyboardType: ULONG;
|
|
KeyboardSubType: ULONG;
|
|
KeyboardFunctionKey: ULONG;
|
|
imeFileName: Array[0..IMEFILENAME_LENGTH] of WCHAR;
|
|
ClientDirectory: Array[0..DIRECTORY_LENGTH] of WCHAR;
|
|
ClientLicense: Array[0..CLIENTLICENSE_LENGTH] of WCHAR;
|
|
ClientModem: Array[0..CLIENTMODEM_LENGTH] of WCHAR;
|
|
ClientBuildNumber: ULONG;
|
|
ClientHardwareId: ULONG;
|
|
ClientProductId: USHORT;
|
|
OutBufCountHost: USHORT;
|
|
OutBufCountClient: USHORT;
|
|
OutBufLength: USHORT;
|
|
AudioDriverName: Array[0..8] of WCHAR;
|
|
ClientTimeZone: TS_TIME_ZONE_INFORMATION;
|
|
ClientSessionId: ULONG;
|
|
clientDigProductId: Array[0..CLIENT_PRODUCT_ID_LENGTH-1] of WCHAR;
|
|
PerformanceFlags: ULONG;
|
|
ActiveInputLocale: ULONG;
|
|
end {_WINSTATIONCLIENTW};
|
|
WINSTATIONCLIENTW = _WINSTATIONCLIENTW;
|
|
PWINSTATIONCLIENTW = ^_WINSTATIONCLIENTW;
|
|
|
|
|
|
// WdConfig class (3)
|
|
// returns information about the WinStationDriver
|
|
_WD_CONFIGW = record
|
|
WdName: array[0..32] of WCHAR;
|
|
WdDLL: array[0..32] of WCHAR;
|
|
WsxDLL: array[0..33] of WCHAR;
|
|
WdFlag: DWORD;
|
|
InputBufferLength: DWORD;
|
|
CfgDLL: array[0..32] of WCHAR;
|
|
WdPrefix: array[0..12] of WCHAR;
|
|
end;
|
|
PWD_CONFIGW = ^_WD_CONFIGW;
|
|
TWdConfigW = _WD_CONFIGW;
|
|
PWdConfigW = PWD_CONFIGW;
|
|
|
|
// WinStationConfig (6)
|
|
// class, returns information about the client's
|
|
// configuration such as network, time(zone) settings and such
|
|
{ _WINSTATION_CONFIGW = record
|
|
Reserved1: DWORD;
|
|
ClientName: array[0..20] of WCHAR;
|
|
Domain: array[0..17] of WCHAR;
|
|
Username: array[0..35] of WCHAR;
|
|
CurrentDirectory: array[0..256] of WCHAR;
|
|
ApplicationName:array[0..259] of WCHAR;
|
|
Reserved2: DWORD;
|
|
AddressFamily: DWORD; // AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
|
|
ClientAddress: array[0..27] of WCHAR;
|
|
Reserved3: array[0..7] of BYTE;
|
|
Reserved4: array[0..4] of DWORD;
|
|
Reserved5: array[0..69] of BYTE;
|
|
ClientDLLName: array[0..330] of WCHAR;
|
|
Reserved6: array[0..1] of FILETIME;
|
|
AudioDriver: array[0..9] of WCHAR;
|
|
TZBias: DWORD;
|
|
TZStandardName: array[0..31] of WCHAR;
|
|
Reserved7: DWORD; // Standard Bias??
|
|
TZDaylightName: array[0..31] of WCHAR;
|
|
TZDayLightStart: array[0..15] of BYTE;
|
|
TZDayLightBias: DWORD;
|
|
Reserved8: DWORD; // Daylight offset?
|
|
TSInstanceID: array[0..33] of WCHAR; // sometimes windows license key(s)
|
|
Reserved9: DWORD; // related to license key or instanceid?
|
|
end;
|
|
PWINSTATION_CONFIGW = ^_WINSTATION_CONFIGW;
|
|
TWinStationConfigW = _WINSTATION_CONFIGW;
|
|
PWinStationConfigW = PWINSTATION_CONFIGW;}
|
|
|
|
// class WinStationInformation (8)
|
|
// provides information about the current state of the client such as
|
|
// idletime, sessionstatus and transferred/received bytes
|
|
{ The structure below was reverse engineered but is now documented. I replaced
|
|
it with the offical structure _WINSTATIONINFORMATIONW (in this unit)
|
|
_WINSTATION_INFORMATIONW = record
|
|
State: DWORD;
|
|
WinStationName: array[0..10] of WideChar;
|
|
Unknown1: array[0..10] of byte;
|
|
Unknown3: array[0..10] of WideChar;
|
|
Unknown2: array[0..8] of byte;
|
|
SessionId: DWORD;
|
|
Reserved2: array[0..3] of byte;
|
|
ConnectTime: FILETIME;
|
|
DisconnectTime: FILETIME;
|
|
LastInputTime: FILETIME;
|
|
LogonTime: FILETIME;
|
|
Unknown4: array[0..11] of byte;
|
|
OutgoingFrames: DWORD;
|
|
OutgoingBytes: DWORD;
|
|
OutgoingCompressBytes: DWORD;
|
|
Unknown5: array[0..435] of byte;
|
|
IncomingCompressedBytes: DWORD;
|
|
Unknown6: array[0..7] of byte;
|
|
IncomingFrames: DWORD;
|
|
IncomingBytes: DWORD;
|
|
Unknown7: array[0..3] of byte;
|
|
Reserved3: array[0..528] of byte;
|
|
Domain: array[0..17] of WideChar;
|
|
Username: array[0..22] of WideChar;
|
|
CurrentTime: FILETIME;
|
|
end;
|
|
PWINSTATION_INFORMATIONW = ^_WINSTATION_INFORMATIONW;
|
|
TWinStationInformationExW = _WINSTATION_INFORMATIONW;
|
|
PWinStationInformationExW = PWINSTATION_INFORMATIONW;}
|
|
|
|
{ The WINSTATIONSTATECLASS enumeration represents the current state of a session
|
|
RW: corresponds to WTS_CONNECTSTATE_CLASS from WtsApi32
|
|
State_Active: A user is logged on to a session and the client is connected.
|
|
State_Connected: A client is connected to a session but the user has not yet logged on.
|
|
State_ConnectQuery: A session is in the process of connecting to a client.
|
|
State_Shadow: A session is shadowing another session.
|
|
State_Disconnected: A user is logged on to the session but the client is currently disconnected from the server.
|
|
State_Idle: A session is waiting for a client to connect to the server.
|
|
State_Listen: A listener is waiting for connections from the Terminal Services client.
|
|
State_Reset: A session is being reset. As a result, the user is logged off, the session is terminated, and the client is disconnected.<34>
|
|
State_Down: A session is currently tearing down or is in the down state, indicating an error.
|
|
State_Init: A session is in the process of being initialized.
|
|
}
|
|
_WINSTATIONSTATECLASS = (
|
|
State_Active {= 0},
|
|
State_Connected {= 1},
|
|
State_ConnectQuery {= 2},
|
|
State_Shadow {= 3},
|
|
State_Disconnected {= 4},
|
|
State_Idle {= 5},
|
|
State_Listen {= 6},
|
|
State_Reset {= 7},
|
|
State_Down {= 8},
|
|
State_Init {= 9 } );
|
|
WINSTATIONSTATECLASS = _WINSTATIONSTATECLASS;
|
|
TWinStationStateClass = _WINSTATIONSTATECLASS;
|
|
|
|
WINSTATIONNAMEW = Array[0..WINSTATIONNAME_LENGTH] of WCHAR;
|
|
WINSTATIONNAMEA = Array[0..WINSTATIONNAME_LENGTH] of AnsiChar;
|
|
|
|
_TSHARE_COUNTERS = packed record
|
|
Reserved: ULONG;
|
|
end {_TSHARE_COUNTERS};
|
|
TSHARE_COUNTERS = _TSHARE_COUNTERS;
|
|
PTSHARE_COUNTERS = ^_TSHARE_COUNTERS;
|
|
|
|
_PROTOCOLCOUNTERS = packed record
|
|
WdBytes: ULONG;
|
|
WdFrames: ULONG;
|
|
WaitForOutBuf: ULONG;
|
|
Frames: ULONG;
|
|
Bytes: ULONG;
|
|
CompressedBytes: ULONG;
|
|
CompressFlushes: ULONG;
|
|
Errors: ULONG;
|
|
Timeouts: ULONG;
|
|
AsyncFramingError: ULONG;
|
|
AsyncOverrunError: ULONG;
|
|
AsyncOverflowError: ULONG;
|
|
AsyncParityError: ULONG;
|
|
TdErrors: ULONG;
|
|
ProtocolType: USHORT;
|
|
case Length: USHORT of
|
|
1: (TShareCounters: TSHARE_COUNTERS);
|
|
2: (Reserved: Array[0..99] of ULONG);
|
|
end {_PROTOCOLCOUNTERS};
|
|
PROTOCOLCOUNTERS = _PROTOCOLCOUNTERS;
|
|
PPROTOCOLCOUNTERS = ^_PROTOCOLCOUNTERS;
|
|
TProtocolCounters = _PROTOCOLCOUNTERS;
|
|
|
|
_THINWIRECACHE = packed record
|
|
CacheReads: ULONG;
|
|
CacheHits: ULONG;
|
|
end {_THINWIRECACHE};
|
|
THINWIRECACHE = _THINWIRECACHE;
|
|
PTHINWIRECACHE = ^_THINWIRECACHE;
|
|
|
|
const
|
|
MAX_THINWIRECACHE = 4;
|
|
|
|
type
|
|
|
|
_RESERVED_CACHE = packed record
|
|
ThinWireCache: Array[0..MAX_THINWIRECACHE-1] of THINWIRECACHE;
|
|
end {_RESERVED_CACHE};
|
|
RESERVED_CACHE = _RESERVED_CACHE;
|
|
PRESERVED_CACHE = ^_RESERVED_CACHE;
|
|
|
|
_TSHARE_CACHE = packed record
|
|
Reserved: ULONG;
|
|
end {_TSHARE_CACHE};
|
|
TSHARE_CACHE = _TSHARE_CACHE;
|
|
PTSHARE_CACHE = ^_TSHARE_CACHE;
|
|
|
|
CACHE_STATISTICS = packed record
|
|
ProtocolType: USHORT;
|
|
case Length: USHORT of
|
|
1: (ReservedCacheStats: RESERVED_CACHE);
|
|
2: (TShareCacheStats: TSHARE_CACHE);
|
|
3: (Reserved: Array[0..19] of ULONG);
|
|
end {CACHE_STATISTICS};
|
|
|
|
_PROTOCOLSTATUS = packed record
|
|
Output: PROTOCOLCOUNTERS;
|
|
Input: PROTOCOLCOUNTERS;
|
|
Cache: CACHE_STATISTICS;
|
|
AsyncSignal: ULONG;
|
|
AsyncSignalMask: ULONG;
|
|
end {_PROTOCOLSTATUS};
|
|
PROTOCOLSTATUS = _PROTOCOLSTATUS;
|
|
PPROTOCOLSTATUS = ^_PROTOCOLSTATUS;
|
|
|
|
_WINSTATIONINFORMATIONW = record
|
|
ConnectState: WINSTATIONSTATECLASS;
|
|
WinStationName: WINSTATIONNAMEW;
|
|
LogonId: ULONG;
|
|
Align: array[0..3] of byte;
|
|
ConnectTime: LARGE_INTEGER;
|
|
DisconnectTime: LARGE_INTEGER;
|
|
LastInputTime: LARGE_INTEGER;
|
|
LogonTime: LARGE_INTEGER;
|
|
Status: PROTOCOLSTATUS;
|
|
Domain: Array[0..DOMAIN_LENGTH] of WCHAR;
|
|
UserName: Array[0..USERNAME_LENGTH] of WCHAR;
|
|
CurrentTime: LARGE_INTEGER;
|
|
end {_WINSTATIONINFORMATIONW};
|
|
WINSTATIONINFORMATIONW = _WINSTATIONINFORMATIONW;
|
|
PWINSTATIONINFORMATIONW = ^_WINSTATIONINFORMATIONW;
|
|
|
|
// Class WinStationResolution (16)
|
|
_WINSTATION_RESOLUTION = record
|
|
HorizontalResolution : WORD; // width
|
|
VerticalResolution : WORD; // height
|
|
ColorDepth : WORD; // bits per pixel, see JwaWtsApi._WTS_CLIENT_DISPLAY.ColorDepth for format
|
|
end;
|
|
PWINSTATION_RESOLUTION = ^_WINSTATION_RESOLUTION;
|
|
TWinStationResolution = _WINSTATION_RESOLUTION;
|
|
PWinStationResolution = PWINSTATION_RESOLUTION;
|
|
|
|
|
|
// WinStationRemoteAddress (class 29)
|
|
// Definition is preliminary
|
|
// AddressFamily can be AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
|
|
// Port is the remote port number (local port number is 3389 by default)
|
|
// Address (for type AF_INET it start's at a 2 byte offset)
|
|
// You can format IP Address to string like this:
|
|
// Format('%d.%d.%d.%d', [WinStationAddress.Address[2],
|
|
// WinStationRemoteAddress.[3], WinStationRemoteAddress.Address[4],
|
|
// WinStationRemoteAddress.Address[5]]);
|
|
//
|
|
// Be sure to fill the structure with zeroes before query!
|
|
_WINSTATION_REMOTE_ADDRESS = record
|
|
AddressFamily: DWORD;
|
|
Port: WORD;
|
|
Address: array [0..19] of BYTE;
|
|
Reserved: array[0..5] of BYTE;
|
|
end;
|
|
PWINSTATION_REMOTE_ADDRESS = ^_WINSTATION_REMOTE_ADDRESS;
|
|
TWinStationRemoteAddress = _WINSTATION_REMOTE_ADDRESS;
|
|
PWinStationRemoteAddress = PWINSTATION_REMOTE_ADDRESS;
|
|
|
|
// WinStationShadowInformation (26)
|
|
// Setting it requires the caller to be a local system, only ShadowMode field is used
|
|
_WINSTATION_SHADOW_INFORMATION = record
|
|
CurrentShadowState : DWORD; //one of the SHADOW_STATE_XXX constants
|
|
ShadowMode : DWORD; // one of the SHADOW_MODE_XXX constants
|
|
CurrentSessionId : DWORD;
|
|
Unknown1 : DWORD; // unknown; contains 2 or normal sessions, 0 on console and idle sessions
|
|
end;
|
|
PWINSTATION_SHADOW_INFORMATION = ^_WINSTATION_SHADOW_INFORMATION;
|
|
TWinStationShadowInformation = _WINSTATION_SHADOW_INFORMATION;
|
|
PWinStationShadowInformation = PWINSTATION_SHADOW_INFORMATION;
|
|
|
|
// WinStationPipeInformation (33)
|
|
// returns name of the pipe (e.g. \\.\pipe\TerminalServer\g0djjEInbXQFxJ9JLPl\2)
|
|
// which is used to create processes in the target session
|
|
// by default, system can write and read to this pipe
|
|
_WINSTATION_PIPE_INFORMATIONW = record
|
|
PipeName : array [0..47] of WideChar;
|
|
end;
|
|
PWINSTATION_PIPE_INFORMATIONW = ^_WINSTATION_PIPE_INFORMATIONW;
|
|
TWinStationPipeInformationW = _WINSTATION_PIPE_INFORMATIONW;
|
|
PWinStationPipeInformationW = PWINSTATION_PIPE_INFORMATIONW;
|
|
|
|
{ The header of the Terminal Services performance counter structure providing
|
|
general information on the counter.
|
|
dwCounterID: The identifier of the counter. Set by the caller of
|
|
(Rpc)WinStationGetTermSrvCountersValue to indicate the counter on which to
|
|
retrieve data. This will be set to zero by
|
|
(Rpc)WinStationGetTermSrvCountersValue if the dwCounterId isn't recognized.
|
|
bResult: Set to TRUE if counter information is returned. Set to FALSE if
|
|
counter data isn't being returned because the counter ID being requested
|
|
was unrecognized.
|
|
|
|
The following counters are supported:
|
|
Total number of sessions: dwCounterId SHOULD be TERMSRV_TOTAL_SESSIONS.
|
|
Value will indicate the total number of reconnections to the server since
|
|
startup.
|
|
Number of disconnected sessions: dwCounterId SHOULD be TERMSRV_DISC_SESSIONS.
|
|
Value will indicate the total number of disconnections from the server since
|
|
startup.
|
|
Number of reconnected sessions: dwCounterId SHOULD be TERMSRV_RECON_SESSIONS.
|
|
Value will indicate the total number of all reconnected sessions that have
|
|
existed on the server since startup.
|
|
Current number of active sessions: dwCounterId SHOULD be
|
|
TERMSRV_CURRENT_ACTIVE_SESSIONS.
|
|
Value will indicate the current number of active sessions on the server.
|
|
Current number of disconnected sessions: dwCounterId SHOULD be
|
|
TERMSRV_CURRENT_DISC_SESSIONS. Value will indicate the current number of
|
|
disconnected sessions on the server. Windows XP only
|
|
}
|
|
const TERMSRV_TOTAL_SESSIONS = 1;
|
|
const TERMSRV_DISC_SESSIONS = 2;
|
|
const TERMSRV_RECON_SESSIONS = 3;
|
|
const TERMSRV_CURRENT_ACTIVE_SESSIONS = 4;
|
|
const TERMSRV_CURRENT_DISC_SESSIONS = 5;
|
|
const TERMSRV_PENDING_SESSIONS = 6;
|
|
const TERMSRV_SUCC_TOTAL_LOGONS = 7;
|
|
const TERMSRV_SUCC_LOCAL_LOGONS = 8;
|
|
const TERMSRV_SUCC_REMOTE_LOGONS = 9;
|
|
const TERMSRV_SUCC_SESSION0_LOGONS = 10;
|
|
const TERMSRV_CURRENT_TERMINATING_SESSIONS = 11;
|
|
const TERMSRV_CURRENT_LOGGEDON_SESSIONS = 12;
|
|
|
|
type
|
|
_TS_COUNTER_HEADER = record
|
|
dwCounterID: DWORD;
|
|
bResult: Boolean;
|
|
end;
|
|
TS_COUNTER_HEADER = _TS_COUNTER_HEADER;
|
|
TTSCounterHeader = TS_COUNTER_HEADER;
|
|
PTS_COUNTER_HEADER = ^TS_COUNTER_HEADER;
|
|
PTSCounterHeader = PTS_COUNTER_HEADER;
|
|
|
|
_TS_COUNTER = record
|
|
CounterHead: TS_COUNTER_HEADER;
|
|
dwValue: DWORD;
|
|
StartTime: LARGE_INTEGER; //Currently, always set to zero because time stamps are not supported.
|
|
end;
|
|
TS_COUNTER = _TS_COUNTER;
|
|
TTSCounter = TS_COUNTER;
|
|
PTS_COUNTER = ^TS_COUNTER;
|
|
PTSCounter = PTS_COUNTER;
|
|
|
|
function AreWeRunningTerminalServices: Boolean;
|
|
|
|
procedure CachedGetUserFromSid(pSid: PSID; pUserName: LPWSTR;
|
|
var cbUserName: DWORD); stdcall;
|
|
|
|
function CalculateDiffTime(TimeLow: INT64; TimeHigh: INT64): INT64;
|
|
stdcall;
|
|
|
|
// Calculate Elapsed time from a Filetime (UTC time) to DiffTime structure
|
|
function CalculateElapsedTime(lpFileTime: PFILETIME; var DiffTime: TDiffTime):
|
|
Boolean; stdcall;
|
|
|
|
function CpuTime2Str(ACPUTime: LARGE_INTEGER): String;
|
|
|
|
function CurrentDateTimeString(out lpBuffer: PWideChar): Boolean; stdcall;
|
|
|
|
// This is the version for NT Terminal Server, 2000, XP/2003 and Server 2008
|
|
function DateTimeString(DateTime: PFILETIME; lpBuffer: PWideChar): PWideChar;
|
|
stdcall;
|
|
|
|
// This is a wrapper for all OS versions, you are strongly recommended to use
|
|
// only this version.
|
|
function DateTimeStringSafe(DateTime: PFILETIME; lpBuffer: PWideChar;
|
|
cchDest: SIZE_T): PWideChar; stdcall;
|
|
|
|
// This is the Vista RTM version which takes an additional parameter with
|
|
// maximum buffer size (you have to set it). This bug was fixed in SP1.
|
|
function DateTimeStringVistaRTM(DateTime: PFILETIME; lpBuffer: PWideChar;
|
|
cchDest: SIZE_T): PWideChar; stdcall;
|
|
|
|
function DiffTimeString(FTLow: FILETIME; FTHigh: FILETIME;
|
|
out pwElapsedTime: PWideChar): Integer;
|
|
|
|
// This is the version for NT Terminal Server, 2000, XP/2003 and Server 2008
|
|
function ElapsedTimeString(DiffTime: PDiffTime; bShowSeconds: Boolean;
|
|
lpElapsedTime: PWideChar): Integer; stdcall;
|
|
|
|
// This is a wrapper for all OS versions, you are strongly recommended to use
|
|
// only this version.
|
|
function ElapsedTimeStringSafe(DiffTime: PDiffTime; bShowSeconds: Boolean;
|
|
lpElapsedTime: PWideChar; cchDest: SIZE_T): Integer;
|
|
|
|
// This is the Vista RTM version of ElapsedTimeString which takes an additional
|
|
// parameter with the count of characters for lpElapsedTime (you have to set it)
|
|
// This bug was fixed in SP1.
|
|
function ElapsedTimeStringVistaRTM(DiffTime: PDiffTime; bShowSeconds: Boolean;
|
|
lpElapsedTime: PWideChar; cchDest: SIZE_T): HRESULT; stdcall;
|
|
|
|
|
|
|
|
//returns -109205 on error
|
|
function FileTime2DateTime(FileTime: TFileTime): TDateTime;
|
|
|
|
function GetUnknownString: PWideChar; stdcall;
|
|
|
|
function IsTerminalServiceRunning: boolean;
|
|
|
|
// Tested and working on Windows XP but doesn't seem to work on
|
|
// Windows Vista/2008. Better use W version to be sure!
|
|
function LogonIdFromWinStationNameA(hServer: HANDLE; pWinStationName: LPSTR;
|
|
var SessionId: DWORD): Boolean; stdcall;
|
|
|
|
// Tested and working on XP, 2003 and 2008
|
|
function LogonIdFromWinStationNameW(hServer: HANDLE; pWinStationName: LPWSTR;
|
|
var SessionId: DWORD): Boolean; stdcall;
|
|
|
|
// This is the version for NT Terminal Server, 2000, XP/2003 and Server 2008
|
|
// Reserve 66 bytes for pWinStationName and 21 for pUserName
|
|
function QueryCurrentWinStation(pWinStationName: LPWSTR;
|
|
pUserName: LPWSTR; var SessionId: DWORD; var WdFlag: DWORD): Boolean;
|
|
stdcall;
|
|
|
|
// This is the Vista RTM version of QueryCurrentWinStation which takes an
|
|
// additional parameter with the count of characters for pUserName
|
|
// note that pWinStationname is Fixed Size!
|
|
// This bug was fixed in SP1.
|
|
function QueryCurrentWinStationVistaRTM(pWinStationName: LPWSTR;
|
|
pUserName: PWideChar; cchDest: DWORD; var SessionId: DWORD;
|
|
var WdFlag: DWORD): Boolean; stdcall;
|
|
|
|
// This is a wrapper for all OS versions, you are strongly recommended to use
|
|
// only this version.
|
|
function QueryCurrentWinStationSafe(pWinStationName: LPWSTR;
|
|
pUserName: PWideChar; cchDest: DWORD; var SessionId: DWORD;
|
|
var WdFlag: DWORD): Boolean; stdcall;
|
|
|
|
function StrConnectState(ConnectState: WTS_CONNECTSTATE_CLASS;
|
|
bShortString: BOOL): PWideChar; stdcall;
|
|
|
|
function WinStationBroadcastSystemMessage(hServer: HANDLE;
|
|
SendToAllWinstations: BOOL; SessionId: DWORD; TimeOut: DWORD;
|
|
dwFlags: DWORD; lpdwRecipients: DWORD; uiMessage: ULONG; _wParam: WPARAM;
|
|
_lParam: LPARAM; pResponse: LONGINT): LONGINT; stdcall;
|
|
|
|
function WinStationCallBack(hServer:HANDLE; SessionId: DWORD;
|
|
pPhoneNumber: LPWSTR): BOOL; stdcall;
|
|
|
|
procedure WinStationCloseServer(hServer: HANDLE); stdcall;
|
|
|
|
function WinStationConnectW(hServer: Handle; SessionId: DWORD;
|
|
TargetSessionId: DWORD; pPassword: LPWSTR;
|
|
bWait: BOOL): Boolean; stdcall;
|
|
|
|
function WinStationDisconnect(hServer: THandle; SessionId: DWORD;
|
|
bWait: BOOL): Boolean; stdcall;
|
|
|
|
function WinStationEnumerateA(hServer: HANDLE;
|
|
var ppSessionInfo: PWTS_SESSION_INFOA; var pCount: DWORD): Boolean; stdcall;
|
|
|
|
function WinStationEnumerateW(hServer: HANDLE;
|
|
var ppSessionInfo: PWTS_SESSION_INFOW; var pCount: DWORD): Boolean; stdcall;
|
|
|
|
// Used to release memory allocated by WinStationGetAllProcesses
|
|
function WinStationFreeGAPMemory(Level: DWORD;
|
|
ppTsAllProcessesInfo: PTS_ALL_PROCESSES_INFO_ARRAY;
|
|
pNumberOfProcesses: Integer): Boolean; stdcall;
|
|
|
|
// Important! pProcessInfo must be nil before calling this function
|
|
// by using Out parameter Delphi takes care of this for us
|
|
function WinStationGetAllProcesses(hServer: HANDLE; Level: DWORD;
|
|
var pNumberOfProcesses: Integer;
|
|
out ppTsAllProcessesInfo: PTS_ALL_PROCESSES_INFO_ARRAY): Boolean stdcall;
|
|
|
|
function WinStationGetLanAdapterNameW(hServer: HANDLE; LanaId: DWORD;
|
|
ProtocolTypeLength: DWORD; ProtocolType: PWideChar;
|
|
var ResultLength: DWORD; var LanAdapterName: PWideChar): DWORD; stdcall;
|
|
|
|
function WinStationGetProcessSid(hServer: Handle; dwPID: DWORD;
|
|
ProcessStartTime: FILETIME; pProcessUserSid: PSID; var dwSidSize: DWORD):
|
|
Boolean; stdcall;
|
|
|
|
function WinStationGetRemoteIPAddress(hServer: HANDLE; SessionId: DWORD;
|
|
var RemoteIPAddress: WideString; var Port: WORD): Boolean;
|
|
|
|
function WinStationGetTermSrvCountersValue(hServer: Handle;
|
|
dwEntries: DWORD; pCounter: PTS_COUNTER): Boolean; stdcall;
|
|
|
|
function WinStationNameFromLogonIdA(hServer: HANDLE; SessionId: ULONG;
|
|
pWinStationName: LPSTR): Boolean; stdcall;
|
|
|
|
function WinStationNameFromLogonIdW(hServer: HANDLE; SessionId: ULONG;
|
|
pWinStationName: LPWSTR): Boolean; stdcall;
|
|
|
|
function WinStationOpenServerA(pServerName: LPSTR): HANDLE; stdcall;
|
|
|
|
function WinStationOpenServerW(pServerName: LPWSTR): HANDLE; stdcall;
|
|
|
|
function WinStationQueryInformationW(hServer: HANDLE; SessionId: DWORD;
|
|
WinStationInformationClass: WINSTATIONINFOCLASS; pWinStationInformation: PVOID;
|
|
WinStationInformationLength: DWORD; var pReturnLength: DWORD):
|
|
Boolean; stdcall;
|
|
|
|
function WinStationQueryLogonCredentialsW(
|
|
var LogonCredentials: _LOGON_CREDENTIALSW): HRESULT; stdcall;
|
|
|
|
function WinstationQueryUserToken(hServer: HANDLE; SessionId: DWORD;
|
|
var hToken: HANDLE): Boolean;
|
|
|
|
function WinStationRegisterConsoleNotification(hServer: HANDLE; _hwnd: HWND;
|
|
dwFlags: Cardinal): Boolean; stdcall;
|
|
|
|
// WinStationRename needs Admin rights and always returns true
|
|
// need to check GetLastError
|
|
// Duplicate names are not allowed
|
|
// Renaming a WinStation gives errors on Remote Connections:
|
|
// the windowstation is busy processing connect, disconnect, reset
|
|
// or login request
|
|
|
|
// A version untested
|
|
function WinStationRenameA(hServer: HANDLE; pOldWinStationName: LPSTR;
|
|
pNewWinStationName: LPSTR): Boolean; stdcall;
|
|
|
|
// W version was tested
|
|
function WinStationRenameW(hServer: HANDLE; pOldWinStationName: LPWSTR;
|
|
pNewWinStationName: LPWSTR): Boolean; stdcall;
|
|
|
|
function WinStationSendMessageA(hServer: HANDLE; SessionId: DWORD;
|
|
pTitle: LPSTR; TitleLength: DWORD; pMessage: LPSTR; MessageLength: DWORD;
|
|
Style: DWORD; Timeout: DWORD; var pResponse: DWORD;
|
|
bWait: BOOL): Boolean; stdcall;
|
|
|
|
function WinStationSendMessageW(hServer: HANDLE; SessionId: DWORD;
|
|
pTitle: LPWSTR; TitleLength: DWORD; pMessage: LPWSTR; MessageLength: DWORD;
|
|
Style: DWORD; Timeout: DWORD; var pResponse: DWORD;
|
|
bWait: BOOL): Boolean; stdcall;
|
|
|
|
function WinStationServerPing(hServer: HANDLE): BOOLEAN; stdcall;
|
|
|
|
function WinStationSetInformationA(hServer: HANDLE; SessionID: DWORD;
|
|
InformationClass: WINSTATIONINFOCLASS; pWinStationInformation: PVOID;
|
|
WinStationInformationLength: DWORD): Boolean; stdcall;
|
|
|
|
function WinStationSetInformationW(hServer: HANDLE; SessionID: DWORD;
|
|
InformationClass: WINSTATIONINFOCLASS; pWinStationInformation: PVOID;
|
|
DataSWinStationInformationLength: DWORD): Boolean; stdcall;
|
|
|
|
function WinStationShadow(hServer: Handle; pServerName: LPWSTR;
|
|
SessionId: DWORD; HotKey: DWORD; HKModifier: DWORD): Boolean; stdcall;
|
|
|
|
// Admin can stop a shadowed session. SessionId is the targetsession
|
|
// so the "victim" and not the one who is shadowing
|
|
function WinStationShadowStop(hServer: Handle; SessionId: DWORD;
|
|
bWait: BOOL): Boolean; stdcall;
|
|
|
|
function WinStationShutDownSystem(hSERVER: HANDLE;
|
|
ShutdownFlags: DWORD): Boolean; stdcall;
|
|
|
|
function WinStationTerminateProcess(hServer: Handle; dwPID: DWORD;
|
|
dwExitCode: DWORD): Boolean; stdcall;
|
|
|
|
function WinStationUnRegisterConsoleNotification(hServer: HANDLE;
|
|
hwnd: THANDLE): Boolean; stdcall;
|
|
|
|
{$ENDIF JWA_IMPLEMENTATIONSECTION}
|
|
|
|
{$IFNDEF JWA_OMIT_SECTIONS}
|
|
implementation
|
|
|
|
uses
|
|
JwaWinDLLNames;
|
|
{$ENDIF JWA_OMIT_SECTIONS}
|
|
|
|
{$IFNDEF JWA_INCLUDEMODE}
|
|
const
|
|
winstadll = 'winsta.dll';
|
|
utildll = 'utildll.dll';
|
|
{$ENDIF JWA_INCLUDEMODE}
|
|
|
|
{$IFNDEF JWA_INTERFACESECTION}
|
|
|
|
|
|
{$IFNDEF DYNAMIC_LINK}
|
|
procedure CachedGetUserFromSid; external utildll name 'CachedGetUserFromSid';
|
|
function CalculateDiffTime; external utildll name 'CalculateDiffTime';
|
|
function CalculateElapsedTime; external utildll name 'CalculateElapsedTime';
|
|
function CurrentDateTimeString; external utildll name 'CurrentDateTimeString';
|
|
function DateTimeString; external utildll name 'DateTimeString';
|
|
function DateTimeStringVistaRTM; external utildll name 'DateTimeString';
|
|
function ElapsedTimeString; external utildll name 'ElapsedTimeString';
|
|
// Vista version of ElapsedTimeString, exported name is ElapsedTimeString
|
|
|
|
function ElapsedTimeStringVistaRTM; external utildll name 'ElapsedTimeString';
|
|
function GetUnknownString; external utildll name 'GetUnknownString';
|
|
function LogonIdFromWinStationNameA; external winstadll name 'LogonIdFromWinStationNameA';
|
|
function LogonIdFromWinStationNameW; external winstadll name 'LogonIdFromWinStationNameW';
|
|
function QueryCurrentWinStation; external utildll name 'QueryCurrentWinStation';
|
|
function QueryCurrentWinStationVistaRTM; external utildll name 'QueryCurrentWinStation';
|
|
function StrConnectState; external utildll name 'StrConnectState';
|
|
function WinStationBroadcastSystemMessage; external winstadll name 'WinStationBroadcastSystemMessage';
|
|
function WinStationCallBack; external winstadll name 'WinStationCallBack';
|
|
procedure WinStationCloseServer; external winstadll name 'WinStationCloseServer';
|
|
function WinStationConnectW; external winstadll name 'WinStationConnectW';
|
|
function WinStationDisconnect; external winstadll name 'WinStationDisconnect';
|
|
function WinStationEnumerateA; external winstadll name 'WinStationEnumerateA';
|
|
function WinStationEnumerateW; external winstadll name 'WinStationEnumerateW';
|
|
function WinStationFreeGAPMemory; external winstadll name 'WinStationFreeGAPMemory';
|
|
function WinStationGetAllProcesses; external winstadll name 'WinStationGetAllProcesses';
|
|
function WinStationGetLanAdapterNameW; external winstadll name 'WinStationGetLanAdapterNameW';
|
|
function WinStationGetProcessSid; external winstadll name 'WinStationGetProcessSid';
|
|
function WinStationGetTermSrvCountersValue; external winstadll name 'WinStationGetTermSrvCountersValue';
|
|
function WinStationNameFromLogonIdA; external winstadll name 'WinStationNameFromLogonIdA';
|
|
function WinStationNameFromLogonIdW; external winstadll name 'WinStationNameFromLogonIdW';
|
|
function WinStationOpenServerA; external winstadll name 'WinStationOpenServerA';
|
|
function WinStationOpenServerW; external winstadll name 'WinStationOpenServerW';
|
|
function WinStationQueryLogonCredentialsW; external winstadll name 'WinStationQueryLogonCredentialsW';
|
|
function WinStationRegisterConsoleNotification; external winstadll name 'WinStationRegisterConsoleNotification';
|
|
function WinStationRenameA; external winstadll name 'WinStationRenameA';
|
|
function WinStationRenameW; external winstadll name 'WinStationRenameW';
|
|
function WinStationSendMessageA; external winstadll name 'WinStationSendMessageA';
|
|
function WinStationSendMessageW; external winstadll name 'WinStationSendMessageW';
|
|
function WinStationServerPing; external winstadll name 'WinStationServerPing';
|
|
function WinStationSetInformationA; external winstadll name 'WinStationSetInformationA';
|
|
function WinStationSetInformationW; external winstadll name 'WinStationSetInformationW';
|
|
function WinStationShadow; external winstadll name 'WinStationShadow';
|
|
function WinStationShadowStop; external winstadll name 'WinStationShadowStop';
|
|
function WinStationShutDownSystem; external winstadll name 'WinStationShutDownSystem';
|
|
function WinStationQueryInformationW; external winstadll name 'WinStationQueryInformationW';
|
|
function WinStationTerminateProcess; external winstadll name 'WinStationTerminateProcess';
|
|
function WinStationUnRegisterConsoleNotification; external winstadll name 'WinStationUnRegisterConsoleNotification';
|
|
{$ELSE}
|
|
|
|
var
|
|
__CachedGetUserFromSid: Pointer;
|
|
|
|
procedure CachedGetUserFromSid;
|
|
begin
|
|
GetProcedureAddress(__CachedGetUserFromSid, utildll, 'CachedGetUserFromSid');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__CachedGetUserFromSid]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__CalculateDiffTime: Pointer;
|
|
|
|
function CalculateDiffTime;
|
|
begin
|
|
GetProcedureAddress(__CalculateDiffTime, utildll, 'CalculateDiffTime');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__CalculateDiffTime]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__CalculateElapsedTime: Pointer;
|
|
|
|
function CalculateElapsedTime;
|
|
begin
|
|
GetProcedureAddress(__CalculateElapsedTime, utildll, 'CalculateElapsedTime');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__CalculateElapsedTime]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__CurrentDateTimeString: Pointer;
|
|
|
|
function CurrentDateTimeString;
|
|
begin
|
|
GetProcedureAddress(__CurrentDateTimeString, utildll, 'CurrentDateTimeString');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__CurrentDateTimeString]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__DateTimeString: Pointer;
|
|
|
|
function DateTimeString;
|
|
begin
|
|
GetProcedureAddress(__DateTimeString, utildll, 'DateTimeString');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__DateTimeString]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__DateTimeStringVistaRTM: Pointer;
|
|
|
|
function DateTimeStringVistaRTM;
|
|
begin
|
|
GetProcedureAddress(__DateTimeStringVistaRTM, utildll, 'DateTimeString');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__DateTimeStringVistaRTM]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__ElapsedTimeString: Pointer;
|
|
|
|
function ElapsedTimeString;
|
|
begin
|
|
GetProcedureAddress(__ElapsedTimeString, utildll, 'ElapsedTimeString');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__ElapsedTimeString]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__ElapsedTimeStringVistaRTM: Pointer;
|
|
|
|
function ElapsedTimeStringVistaRTM;
|
|
begin
|
|
GetProcedureAddress(__ElapsedTimeStringVistaRTM, utildll, 'ElapsedTimeString');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__ElapsedTimeStringVistaRTM]
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
__GetUnknownString: Pointer;
|
|
|
|
function GetUnknownString;
|
|
begin
|
|
GetProcedureAddress(__GetUnknownString, utildll, 'GetUnknownString');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__GetUnknownString]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__LogonIdFromWinStationNameA: Pointer;
|
|
|
|
function LogonIdFromWinStationNameA;
|
|
begin
|
|
GetProcedureAddress(__LogonIdFromWinStationNameA, winstadll, 'LogonIdFromWinStationNameA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__LogonIdFromWinStationNameA]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__LogonIdFromWinStationNameW: Pointer;
|
|
|
|
function LogonIdFromWinStationNameW;
|
|
begin
|
|
GetProcedureAddress(__LogonIdFromWinStationNameW, winstadll, 'LogonIdFromWinStationNameW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__LogonIdFromWinStationNameW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__QueryCurrentWinStation: Pointer;
|
|
|
|
function QueryCurrentWinStation;
|
|
begin
|
|
GetProcedureAddress(__QueryCurrentWinStation, utildll, 'QueryCurrentWinStation');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__QueryCurrentWinStation]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__QueryCurrentWinStationVistaRTM: Pointer;
|
|
|
|
function QueryCurrentWinStationVistaRTM;
|
|
begin
|
|
GetProcedureAddress(__QueryCurrentWinStationVistaRTM, utildll, 'QueryCurrentWinStation');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__QueryCurrentWinStationVistaRTM]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__StrConnectState: Pointer;
|
|
|
|
function StrConnectState;
|
|
begin
|
|
GetProcedureAddress(__StrConnectState, utildll, 'StrConnectState');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__StrConnectState]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
//__WinStationBroadcastSystemMessage: Pointer;
|
|
__WinStationBroadcastSM: Pointer;
|
|
|
|
function WinStationBroadcastSystemMessage;
|
|
begin
|
|
GetProcedureAddress(__WinStationBroadcastSM, winstadll, 'WinStationBroadcastSystemMessage');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationBroadcastSM]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationCallBack: Pointer;
|
|
|
|
function WinStationCallBack;
|
|
begin
|
|
GetProcedureAddress(__WinStationCallBack, winstadll, 'WinStationCallBack');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationCallBack]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationCloseServer: Pointer;
|
|
|
|
procedure WinStationCloseServer;
|
|
begin
|
|
GetProcedureAddress(__WinStationCloseServer, winstadll, 'WinStationCloseServer');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationCloseServer]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationConnectW: Pointer;
|
|
|
|
function WinStationConnectW;
|
|
begin
|
|
GetProcedureAddress(__WinStationConnectW, winstadll, 'WinStationConnectW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationConnectW]
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
__WinStationDisconnect: Pointer;
|
|
|
|
function WinStationDisconnect;
|
|
begin
|
|
GetProcedureAddress(__WinStationDisconnect, winstadll, 'WinStationDisconnect');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationDisconnect]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationEnumerateA: Pointer;
|
|
|
|
function WinStationEnumerateA;
|
|
begin
|
|
GetProcedureAddress(__WinStationEnumerateA, winstadll, 'WinStationEnumerateA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationEnumerateA]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationEnumerateW: Pointer;
|
|
|
|
function WinStationEnumerateW;
|
|
begin
|
|
GetProcedureAddress(__WinStationEnumerateW, winstadll, 'WinStationEnumerateW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationEnumerateW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationFreeGAPMemory: Pointer;
|
|
|
|
function WinStationFreeGAPMemory;
|
|
begin
|
|
GetProcedureAddress(__WinStationFreeGAPMemory, winstadll, 'WinStationFreeGAPMemory');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationFreeGAPMemory]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationGetAllProcesses: Pointer;
|
|
|
|
function WinStationGetAllProcesses;
|
|
begin
|
|
GetProcedureAddress(__WinStationGetAllProcesses, winstadll, 'WinStationGetAllProcesses');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationGetAllProcesses]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationGetLanAdapterNameW: Pointer;
|
|
|
|
function WinStationGetLanAdapterNameW;
|
|
begin
|
|
GetProcedureAddress(__WinStationGetLanAdapterNameW, winstadll, 'WinStationGetLanAdapterNameW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationGetLanAdapterNameW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationGetProcessSid: Pointer;
|
|
|
|
function WinStationGetProcessSid;
|
|
begin
|
|
GetProcedureAddress(__WinStationGetProcessSid, winstadll, 'WinStationGetProcessSid');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationGetProcessSid]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationGetTermSrvCountersV: Pointer;
|
|
|
|
function WinStationGetTermSrvCountersValue;
|
|
begin
|
|
GetProcedureAddress(__WinStationGetTermSrvCountersV, winstadll, 'WinStationGetTermSrvCountersValue');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationGetTermSrvCountersV]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationNameFromLogonIdA: Pointer;
|
|
|
|
function WinStationNameFromLogonIdA;
|
|
begin
|
|
GetProcedureAddress(__WinStationNameFromLogonIdA, winstadll, 'WinStationNameFromLogonIdA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationNameFromLogonIdA]
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
__WinStationNameFromLogonIdW: Pointer;
|
|
|
|
function WinStationNameFromLogonIdW;
|
|
begin
|
|
GetProcedureAddress(__WinStationNameFromLogonIdW, winstadll, 'WinStationNameFromLogonIdW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationNameFromLogonIdW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationOpenServerA: Pointer;
|
|
|
|
function WinStationOpenServerA;
|
|
begin
|
|
GetProcedureAddress(__WinStationOpenServerA, winstadll, 'WinStationOpenServerA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationOpenServerA]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationOpenServerW: Pointer;
|
|
|
|
function WinStationOpenServerW;
|
|
begin
|
|
GetProcedureAddress(__WinStationOpenServerW, winstadll, 'WinStationOpenServerW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationOpenServerW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationQueryLogonCW: Pointer;
|
|
|
|
function WinStationQueryLogonCredentialsW;
|
|
begin
|
|
GetProcedureAddress(__WinStationQueryLogonCW, winstadll, 'WinStationQueryLogonCredentialsW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationQueryLogonCW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationRenameA: Pointer;
|
|
|
|
function WinStationRenameA;
|
|
begin
|
|
GetProcedureAddress(__WinStationRenameA, winstadll, 'WinStationRenameA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationRenameA]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationRenameW: Pointer;
|
|
|
|
function WinStationRenameW;
|
|
begin
|
|
GetProcedureAddress(__WinStationRenameW, winstadll, 'WinStationRenameW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationRenameW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationQueryInformationW: Pointer;
|
|
|
|
function WinStationQueryInformationW;
|
|
begin
|
|
GetProcedureAddress(__WinStationQueryInformationW, winstadll, 'WinStationQueryInformationW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationQueryInformationW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationRegisterCN: Pointer;
|
|
|
|
function WinStationRegisterConsoleNotification;
|
|
begin
|
|
GetProcedureAddress(__WinStationRegisterCN, winstadll, 'WinStationRegisterConsoleNotification');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationRegisterCN]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationSendMessageA: Pointer;
|
|
|
|
function WinStationSendMessageA;
|
|
begin
|
|
GetProcedureAddress(__WinStationSendMessageA, winstadll, 'WinStationSendMessageA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationSendMessageA]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationSendMessageW: Pointer;
|
|
|
|
function WinStationSendMessageW;
|
|
begin
|
|
GetProcedureAddress(__WinStationSendMessageW, winstadll, 'WinStationSendMessageW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationSendMessageW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationServerPing: Pointer;
|
|
|
|
function WinStationServerPing;
|
|
begin
|
|
GetProcedureAddress(__WinStationServerPing, winstadll, 'WinStationServerPing');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationServerPing]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationSetInformationA: Pointer;
|
|
|
|
function WinStationSetInformationA;
|
|
begin
|
|
GetProcedureAddress(__WinStationSetInformationA, winstadll, 'WinStationSetInformationA');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationSetInformationA]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationSetInformationW: Pointer;
|
|
|
|
function WinStationSetInformationW;
|
|
begin
|
|
GetProcedureAddress(__WinStationSetInformationW, winstadll, 'WinStationSetInformationW');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationSetInformationW]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationShadow: Pointer;
|
|
|
|
function WinStationShadow;
|
|
begin
|
|
GetProcedureAddress(__WinStationShadow, winstadll, 'WinStationShadow');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationShadow]
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
__WinStationShadowStop : Pointer;
|
|
|
|
function WinStationShadowStop;
|
|
begin
|
|
GetProcedureAddress(__WinStationShadowStop, winstadll, 'WinStationShadowStop');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationShadowStop]
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
__WinStationShutDownSystem : Pointer;
|
|
|
|
function WinStationShutDownSystem;
|
|
begin
|
|
GetProcedureAddress(__WinStationShutDownSystem, winstadll, 'WinStationShutDownSystem');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationShutDownSystem]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationTerminateProcess: Pointer;
|
|
|
|
function WinStationTerminateProcess;
|
|
begin
|
|
GetProcedureAddress(__WinStationTerminateProcess, winstadll, 'WinStationTerminateProcess');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationTerminateProcess]
|
|
end;
|
|
end;
|
|
|
|
var
|
|
__WinStationUnRegisterCN: Pointer;
|
|
|
|
function WinStationUnRegisterConsoleNotification;
|
|
begin
|
|
GetProcedureAddress(__WinStationUnRegisterCN, winstadll, 'WinStationUnRegisterConsoleNotification');
|
|
asm
|
|
MOV ESP, EBP
|
|
POP EBP
|
|
JMP [__WinStationUnRegisterCN]
|
|
end;
|
|
end;
|
|
{$ENDIF DYNAMIC_LINK}
|
|
|
|
function IsWindows7Beta: boolean;
|
|
var VersionInfo: TOSVersionInfoEx;
|
|
begin
|
|
// Zero Memory and set structure size
|
|
ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
|
|
VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
|
|
GetVersionEx(@VersionInfo);
|
|
// Are we running Vista RTM?
|
|
Result := (VersionInfo.dwMajorVersion = 6) and
|
|
(VersionInfo.dwMinorVersion = 1) and
|
|
(VersionInfo.wProductType = VER_NT_WORKSTATION) and
|
|
(VersionInfo.dwBuildNumber = 7000);
|
|
end;
|
|
|
|
// This function is not exported
|
|
function IsVistaRTM: boolean;
|
|
var VersionInfo: TOSVersionInfoEx;
|
|
begin
|
|
// Zero Memory and set structure size
|
|
ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
|
|
VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
|
|
GetVersionEx(@VersionInfo);
|
|
|
|
// Are we running Vista RTM?
|
|
Result := (VersionInfo.dwMajorVersion = 6) and
|
|
(VersionInfo.dwMinorVersion = 0) and
|
|
(VersionInfo.wProductType = VER_NT_WORKSTATION) and
|
|
(VersionInfo.wServicePackMajor = 0); //If no Service Pack has been installed, the value is zero
|
|
end;
|
|
|
|
function IsVista: boolean;
|
|
var VersionInfo: TOSVersionInfoEx;
|
|
begin
|
|
// Zero Memory and set structure size
|
|
ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
|
|
VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
|
|
GetVersionEx(@VersionInfo);
|
|
|
|
// Are we running Vista?
|
|
Result := (VersionInfo.dwMajorVersion = 6) and
|
|
(VersionInfo.dwMinorVersion = 0) and
|
|
(VersionInfo.wProductType = VER_NT_WORKSTATION);
|
|
end;
|
|
|
|
// This the way QWinsta checks if Terminal Services is active:
|
|
function AreWeRunningTerminalServices: Boolean;
|
|
var VersionInfo: TOSVersionInfoEx;
|
|
dwlConditionMask: Int64;
|
|
begin
|
|
// Zero Memory and set structure size
|
|
ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
|
|
VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
|
|
|
|
// We are either Terminal Server or Personal Terminal Server
|
|
VersionInfo.wSuiteMask := VER_SUITE_TERMINAL or VER_SUITE_SINGLEUSERTS;
|
|
dwlConditionMask := VerSetConditionMask(0, VER_SUITENAME, VER_OR);
|
|
|
|
// Test it
|
|
Result := VerifyVersionInfo(VersionInfo, VER_SUITENAME, dwlConditionMask);
|
|
end;
|
|
|
|
// This functions converts CPU times as returned by
|
|
// TSystemProcesses structure to a string
|
|
function CpuTime2Str(ACPUTime: LARGE_INTEGER): String;
|
|
var
|
|
SystemTime: TSystemTime;
|
|
TimeSeparator: Char;
|
|
begin
|
|
TimeSeparator := GetLocaleChar(LOCALE_USER_DEFAULT, LOCALE_STIME, ':');
|
|
FileTimeToSystemTime(FILETIME(ACPUTime), SystemTime);
|
|
|
|
Result := Format('%0:.2d%1:s%2:.2d%3:s%4:.2d', [SystemTime.wHour, TimeSeparator,
|
|
SystemTime.wMinute, TimeSeparator, SystemTime.wSecond]);
|
|
end;
|
|
|
|
function DateTimeStringSafe(DateTime: PFILETIME; lpBuffer: PWideChar;
|
|
cchDest: SIZE_T): PWideChar; stdcall;
|
|
begin
|
|
// Zero Memory
|
|
ZeroMemory(lpBuffer, cchDest * SizeOf(WCHAR));
|
|
|
|
// Are we running Vista?
|
|
if IsVistaRTM or IsWindows7Beta then
|
|
begin
|
|
// Vista version
|
|
Result := DateTimeStringVistaRTM(DateTime, lpBuffer, cchDest);
|
|
end
|
|
else begin
|
|
// Other OS's (including server 2008!)
|
|
Result := DateTimeString(DateTime, lpBuffer);
|
|
end;
|
|
end;
|
|
|
|
// DiffTimeString is a helper function that returns a formatted
|
|
// Elapsed time string (the way Idle Time is displayed in TSAdmin)
|
|
// Return value is the string length
|
|
function DiffTimeString(FTLow: FILETIME; FTHigh: FILETIME;
|
|
out pwElapsedTime: PWideChar): Integer;
|
|
var
|
|
DiffSecs: INT64;
|
|
DiffTime: TDiffTime;
|
|
NumChars: DWORD;
|
|
begin
|
|
// Get the Difftime where Time1 is the "oldest" time
|
|
// Return value is the difference in seconds
|
|
DiffSecs := CalculateDiffTime(Int64(FTLow), Int64(FTHigh));
|
|
// Recalc DiffTime to TDiffTime
|
|
ZeroMemory(@DiffTime, SizeOf(DiffTime));
|
|
// Calculate no of whole days
|
|
DiffTime.wDays := DiffSecs DIV SECONDS_PER_DAY;
|
|
// Calculate no of whole hours
|
|
DiffTime.wHours := DiffSecs MOD SECONDS_PER_DAY DIV SECONDS_PER_HOUR;
|
|
// Calculate no of whole minutes
|
|
DiffTime.wMinutes := DiffSecs MOD SECONDS_PER_DAY MOD SECONDS_PER_HOUR
|
|
DIV SECONDS_PER_MINUTE; // Result = No of whole minutes
|
|
// Calculate no of whole seconds
|
|
DiffTime.wSeconds := DiffSecs MOD SECONDS_PER_DAY MOD SECONDS_PER_HOUR
|
|
MOD SECONDS_PER_MINUTE; // Result = No of seconds
|
|
// Note that Milliseconds are not used and therefore not calculated
|
|
|
|
// Reserve Memory
|
|
GetMem(pwElapsedTime, ELAPSED_TIME_STRING_LENGTH * SizeOf(WCHAR));
|
|
// Format Elapsed TimeString in minutes (bShowSeconds = False)
|
|
NumChars := ElapsedTimeStringSafe(@DiffTime, False, pwElapsedTime,
|
|
ELAPSED_TIME_STRING_LENGTH);
|
|
Result := NumChars;
|
|
// Caller has to free memory when done
|
|
end;
|
|
|
|
function ElapsedTimeStringSafe(DiffTime: PDiffTime; bShowSeconds: Boolean;
|
|
lpElapsedTime: PWideChar; cchDest: SIZE_T): Integer;
|
|
var
|
|
hr: HRESULT;
|
|
begin
|
|
// Zero Memory
|
|
ZeroMemory(lpElapsedTime, cchDest * SizeOf(WCHAR));
|
|
|
|
// Are we running Vista?
|
|
if IsVistaRTM or IsWindows7Beta then
|
|
begin
|
|
hr := ElapsedTimeStringVistaRTM(DiffTime, bShowSeconds, lpElapsedTime,
|
|
cchDest);
|
|
if Succeeded(hr) then
|
|
begin
|
|
Result := cchDest;
|
|
end
|
|
else begin
|
|
Result := 0;
|
|
end;
|
|
|
|
end
|
|
else begin
|
|
Result := ElapsedTimeString(DiffTime, bShowSeconds, lpElapsedTime);
|
|
end;
|
|
// Caller has to free memory when done
|
|
end;
|
|
|
|
function FileTime2DateTime(FileTime: TFileTime): TDateTime;
|
|
var
|
|
LocalFileTime: TFileTime;
|
|
SystemTime: TSystemTime;
|
|
const
|
|
EncodeDateTimeMinValue = -109205;
|
|
begin
|
|
{ TerminalServer works with FILETIMES which represent the number of
|
|
100-nanosecond intervals since January 1, 1601, so we set the default to
|
|
that date }
|
|
|
|
Result := EncodeDateTimeMinValue; //EncodeDateTime(1601, 1, 1, 0, 0, 0, 0); = -109205
|
|
|
|
if FileTimeToLocalFileTime(FileTime, LocalFileTime) then
|
|
begin
|
|
if FileTimeToSystemTime(LocalFileTime, SystemTime) then
|
|
begin
|
|
try
|
|
// SystemTimeToDateTime can raise EConvertError!
|
|
Result := SystemTimeToDateTime(SystemTime);
|
|
except
|
|
on E: Exception do
|
|
begin
|
|
// Ignore the exception and thus return default
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{procedure InitTermSrvCounterArray(var ATermSrvCounterArray: TTermSrvCounterArray);
|
|
begin
|
|
ATermSrvCounterArray[1].dwIndex := TOTAL_SESSIONS_CREATED_COUNTER;
|
|
ATermSrvCounterArray[2].dwIndex := TOTAL_SESSIONS_DISCONNECTED_COUNTER;
|
|
ATermSrvCounterArray[3].dwIndex := TOTAL_SESSIONS_RECONNECTED_COUNTER;
|
|
ATermSrvCounterArray[4].dwIndex := TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER;
|
|
ATermSrvCounterArray[5].dwIndex := TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER;
|
|
ATermSrvCounterArray[6].dwIndex := TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER_2;
|
|
ATermSrvCounterArray[7].dwIndex := TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER_2;
|
|
end;}
|
|
|
|
// This is the way WTSApi32.dll checks if Terminal Service is running
|
|
function IsTerminalServiceRunning: boolean;
|
|
var hSCM: HANDLE;
|
|
hService: HANDLE;
|
|
ServiceStatus: SERVICE_STATUS;
|
|
begin
|
|
Result := False;
|
|
// Open handle to Service Control Manager
|
|
hSCM := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, GENERIC_READ);
|
|
if hSCM > 0 then
|
|
begin
|
|
// Open handle to Terminal Server Service
|
|
hService := OpenService(hSCM, 'TermService', GENERIC_READ);
|
|
if hService > 0 then
|
|
begin
|
|
// Check if the service is running
|
|
QueryServiceStatus(hService, ServiceStatus);
|
|
Result := ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
|
// Close the handle
|
|
CloseServiceHandle(hService);
|
|
end;
|
|
// Close the handle
|
|
CloseServiceHandle(hSCM);
|
|
end;
|
|
end;
|
|
|
|
function QueryCurrentWinStationSafe(pWinStationName: LPWSTR;
|
|
pUserName: PWideChar; cchDest: DWORD; var SessionId: DWORD;
|
|
var WdFlag: DWORD): Boolean;
|
|
begin
|
|
// Zero Memory
|
|
ZeroMemory(pWinStationName, (WINSTATIONNAME_LENGTH+1) * SizeOf(WChar));
|
|
ZeroMemory(pUserName, cchDest * SizeOf(WCHAR));
|
|
|
|
// Are we running Vista?
|
|
if IsVistaRTM then
|
|
begin
|
|
Result := QueryCurrentWinStationVistaRTM(pWinStationName, pUserName, cchDest,
|
|
SessionId, WdFlag);
|
|
end
|
|
else begin
|
|
Result := QueryCurrentWinStation(pWinStationName, pUserName, SessionId,
|
|
WdFlag);
|
|
end;
|
|
|
|
end;
|
|
|
|
function WinStationGetRemoteIPAddress(hServer: HANDLE; SessionId: DWORD;
|
|
var RemoteIPAddress: WideString; var Port: WORD): Boolean;
|
|
var WinStationRemoteIPAddress: TWinStationRemoteAddress;
|
|
pReturnLength: DWORD;
|
|
begin
|
|
// Zero Memory
|
|
ZeroMemory(@WinStationRemoteIPAddress, SizeOf(WinStationRemoteIPAddress));
|
|
// Query Remote Address
|
|
Result := WinStationQueryInformationW(hServer, SessionId,
|
|
WinStationRemoteAddress, @WinStationRemoteIPAddress,
|
|
SizeOf(WinStationRemoteIPAddress), pReturnLength);
|
|
if Result then
|
|
begin
|
|
// If the AddressFamily is IPv4
|
|
if WinStationRemoteIPAddress.AddressFamily = AF_INET then
|
|
begin
|
|
// The ntohs function converts a u_short from TCP/IP network byte order
|
|
// to host byte order (which is little-endian on Intel processors).
|
|
Port := ntohs(WinStationRemoteIPAddress.Port);
|
|
with WinStationRemoteIPAddress do
|
|
begin
|
|
// format the IP Address as string
|
|
RemoteIPAddress := Format('%d.%d.%d.%d', [Address[2], Address[3],
|
|
Address[4], Address[5]]);
|
|
// If you want to convert the to a sockaddr structure you could
|
|
// user WSAStringToAddress
|
|
end;
|
|
end
|
|
else begin
|
|
Result := False;
|
|
Port := 0;
|
|
RemoteIPAddress := '';
|
|
// SetLastError to give the user a clue as to why we failed..
|
|
// An address incompatible with the requested protocol was used.
|
|
// (An address incompatible with the requested protocol was used.)
|
|
SetLastError(WSAEAFNOSUPPORT);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function WinStationQueryUserToken(hServer: HANDLE; SessionId: DWORD;
|
|
var hToken: HANDLE): Boolean;
|
|
var WinstaUserToken: _WINSTA_USER_TOKEN;
|
|
dwReturnLength: DWORD;
|
|
LUID: _LUID;
|
|
bWasPrivEnabled: Boolean;
|
|
Res: NTSTATUS;
|
|
begin
|
|
// Enable SeTcbPrivilege (system account has this enabled by default)
|
|
LookupPrivilegeValue(nil, SE_TCB_NAME, LUID);
|
|
Res := RtlAdjustPrivilege(LUID.LowPart, True, False, @bWasPrivEnabled);
|
|
|
|
// Initialize structure
|
|
WinstaUserToken.ProcessId := GetCurrentProcessId; // Current Process Id
|
|
WinstaUserToken.ThreadId := GetCurrentThreadId; // Current Thread Id
|
|
WinstaUserToken.TokenHandle := 0;
|
|
|
|
if Res = STATUS_SUCCESS then
|
|
begin
|
|
// Query for the token, we are only allowed to do this if we are the
|
|
// System account (else ACCESS_DENIED is returned)
|
|
Result := WinStationQueryInformationW(hServer, SessionId, WinStationUserToken,
|
|
@WinstaUserToken, SizeOf(WinstaUserToken), dwReturnLength);
|
|
hToken := WinStaUserToken.TokenHandle;
|
|
|
|
// Restore state of SeTcbPrivilege
|
|
RtlAdjustPrivilege(LUID.LowPart, bWasPrivEnabled, False, @bWasPrivEnabled);
|
|
end
|
|
else begin
|
|
Result := False;
|
|
// Convert NTStatus to WinError and SetLastError
|
|
SetLastError(RtlNtStatusToDosError(Res));
|
|
end;
|
|
|
|
end;
|
|
|
|
{$ENDIF JWA_INTERFACESECTION}
|
|
|
|
{$IFNDEF JWA_OMIT_SECTIONS}
|
|
end.
|
|
{$ENDIF JWA_OMIT_SECTIONS}
|
|
|