2
0

jwawinsta.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409
  1. {******************************************************************}
  2. { This Unit provides Delphi translations of some functions from }
  3. { WinSta.dll and Utildll. }
  4. { Most functions are undocumented and somehow related to }
  5. { Terminal Server }
  6. { }
  7. { Author: Remko Weijnen (r dot weijnen at gmail dot com) }
  8. { Documentation can be found at www.remkoweijnen.nl }
  9. { }
  10. { The contents of this file are subject to }
  11. { the Mozilla Public License Version 1.1 (the "License"); you may }
  12. { not use this file except in compliance with the License. You may }
  13. { obtain a copy of the License at }
  14. { http://www.mozilla.org/MPL/MPL-1.1.html }
  15. { }
  16. { Software distributed under the License is distributed on an }
  17. { "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or }
  18. { implied. See the License for the specific language governing }
  19. { rights and limitations under the License. }
  20. {******************************************************************}
  21. {$IFNDEF JWA_OMIT_SECTIONS}
  22. unit JwaWinSta;
  23. interface
  24. {$I jediapilib.inc}
  25. uses
  26. DateUtils, SysUtils, JwaWinType, // JwaWinType must be declared before JwaWinBase because of duplicate declaration of FILETIME
  27. JwaWinBase, JwaWinError, JwaNTStatus, JwaWinNT, JwaWinsock2,
  28. JwaWinSvc, JwaWtsApi32, JwaNative;
  29. {$ENDIF JWA_OMIT_SECTIONS}
  30. {$IFNDEF JWA_IMPLEMENTATIONSECTION}
  31. //==============================================================================
  32. // Defines
  33. //==============================================================================
  34. const
  35. SERVERNAME_CURRENT = 0;
  36. // constants used for WinStationGetTermSrvCounters
  37. TOTAL_SESSIONS_CREATED_COUNTER = 1;
  38. TOTAL_SESSIONS_DISCONNECTED_COUNTER = 2;
  39. TOTAL_SESSIONS_RECONNECTED_COUNTER = 3;
  40. TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER = 4;
  41. TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER = 5;
  42. TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER_2 = 6; //TermSrvSuccLocalLogons;
  43. TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER_2 = 7;
  44. // Max lenght for ElapsedTimeString (server 2008 version of utildll
  45. // fixes size at 15, so that's assumed to be safe
  46. ELAPSED_TIME_STRING_LENGTH = 15;
  47. // WdFlag = WinStation Driver Flag, it is returned in class 3 (WdConfig)
  48. // of WinStationQueryInformation and has a different value which
  49. // depends on the protocol. WdFlag is also returned by QueryCurrentWinStation
  50. WD_FLAG_CONSOLE_XP = $24; // XP
  51. WD_FLAG_CONSOLE = $34; // 2003/2008
  52. WD_FLAG_RDP = $36; // XP/2003/2008
  53. WD_FLAG_ICA = $6E; // Citrix Presentation Server
  54. // (value from Citrix PS4, other versions could be different!)
  55. // Class constants for WinStationQueryInformationW
  56. // These names were found in winsta.dll because they have
  57. // corresponding unicode 2 ansi conversion functions.
  58. // Unknown: AsyncConfig, NasiConfig, OemTdConfig, PdConfig, PdConfig2
  59. // PdParams UserConfig, WinStationCreate, WinStationPrinter
  60. //
  61. // The structures below are currently defined, constant names were
  62. // mapped on best guess:
  63. WdConfig = 3;
  64. WinStationClient = 1;
  65. WinStationConfig = 6;
  66. WinStationInformation = 8;
  67. WinStationProductId = 27;
  68. WinStationRemoteAddress = 29;
  69. // Constants for WinStationSetInformation
  70. WinStationBeep = 10; // Calls MessageBeep
  71. // This class is used to query the user's primary access token
  72. // Only System account is allowed to retrieve this!
  73. WinStationToken = 14;
  74. // WinStationLocks plays the lock or unlock sound
  75. // functionality not yet confirmed
  76. WinStationLock = 28; // Locks or Unlocks the WinStation
  77. SECONDS_PER_DAY = 86400;
  78. SECONDS_PER_HOUR = 3600;
  79. SECONDS_PER_MINUTE = 60;
  80. type
  81. // This type is used for ElapsedTimeString
  82. TDiffTime = record
  83. wDays: Word;
  84. wHours: Word;
  85. wMinutes: Word;
  86. wSeconds: Word;
  87. wMilliseconds: Word;
  88. end;
  89. PDiffTime = ^TDiffTime;
  90. // This type is used for WinStationQueryLogonCredentialsW
  91. // dwType can be one of the types defined in JwaWinWlx
  92. // WLX_CREDENTIAL_TYPE_V1_0 or WLX_CREDENTIAL_TYPE_V2_0 = 2
  93. _LOGON_CREDENTIALSW = record
  94. dwType: DWORD;
  95. pUsername: PWideChar;
  96. pDomain: PWideChar;
  97. pPassword: PWideChar;
  98. Unknown2 : DWORD;
  99. Unknown3 : DWORD;
  100. Unknown4: DWORD;
  101. end;
  102. PLOGON_CREDENTIALSW = ^_LOGON_CREDENTIALSW;
  103. TLogonCredentialsW = _LOGON_CREDENTIALSW;
  104. PLogonCredentialsW = PLOGON_CREDENTIALSW;
  105. _WINSTA_USER_TOKEN = record
  106. ProcessId : DWORD;
  107. ThreadId : DWORD;
  108. TokenHandle : THandle;
  109. end;
  110. PWINSTA_USER_TOKEN = ^_WINSTA_USER_TOKEN;
  111. TWinstaUserToken = _WINSTA_USER_TOKEN;
  112. PWinstaUserToken = ^TWinstaUserToken;
  113. // this type is used for WinStationGetTemSrvCounters
  114. _TERM_SRV_COUNTER = record
  115. dwIndex: DWORD;
  116. bSuccess: BOOL;
  117. dwValue: DWORD;
  118. Reserved2: DWORD;
  119. Reserved3: DWORD;
  120. Reserved4: DWORD;
  121. end;
  122. PTERM_SRV_COUNTER = ^_TERM_SRV_COUNTER;
  123. TTermSrvCounter = _TERM_SRV_COUNTER;
  124. PTermSrvCounter = ^TTermSrvCounter;
  125. TERM_SRV_COUNTER_ARRAY = array [1..7] of _TERM_SRV_COUNTER;
  126. PTERM_SRV_COUNTER_ARRAY = ^TERM_SRV_COUNTER_ARRAY;
  127. TTermSrvCounterArray = TERM_SRV_COUNTER_ARRAY;
  128. PTermSrvCounterArray = PTERM_SRV_COUNTER_ARRAY;
  129. // The following types are used for WinStationGetAllProcesses
  130. // _WINSTA_PROCESS_INFO
  131. _WINSTA_PROCESS_INFO = record
  132. ExtendedInfo: PSYSTEM_PROCESSES;
  133. dwSidLength: DWORD;
  134. pUserSid: PSID;
  135. end;
  136. PWINSTA_PROCESS_INFO = ^_WINSTA_PROCESS_INFO;
  137. TWinstaProcessInfo = _WINSTA_PROCESS_INFO;
  138. PWinstaProcessInfo = PWINSTA_PROCESS_INFO;
  139. // Array of _WINSTA_PROCESS_INFO
  140. _WINSTA_PROCESS_INFO_ARRAY = array [0..ANYSIZE_ARRAY-1] of _WINSTA_PROCESS_INFO;
  141. PWINSTA_PROCESS_INFO_ARRAY= ^_WINSTA_PROCESS_INFO_ARRAY;
  142. TWinstaProcessInfoArray = _WINSTA_PROCESS_INFO_ARRAY;
  143. PWinstaProcessInfoArray = PWINSTA_PROCESS_INFO_ARRAY;
  144. // The following types are used for WinStationQueryInformationW
  145. // WinStationClient, returns information as provided by the
  146. // Terminal Server client (mstsc).
  147. _WINSTATION_CLIENTW = record
  148. Comment: array[0..59] of WCHAR;
  149. Reserved1: array[0..2] of DWORD;
  150. ClientUsername: array[0..20] of WCHAR;
  151. ClientDomain: array[0..17] of WCHAR;
  152. ClientPassword: array[0..255] of WCHAR; // this was fixec win2000 SP4
  153. Reserved2: array[0..1635] of BYTE;
  154. Reserved3: array[0..6] of DWORD;
  155. Reserved4: array[0..275] of BYTE;
  156. end;
  157. PWINSTATION_CLIENTW = ^_WINSTATION_CLIENTW;
  158. TWinStationClientW = _WINSTATION_CLIENTW;
  159. PWinStationClientW = PWINSTATION_CLIENTW;
  160. // WdConfig class, returns information about the WinStationDriver
  161. _WD_CONFIGW = record
  162. WdName: array[0..32] of WCHAR;
  163. WdDLL: array[0..32] of WCHAR;
  164. WsxDLL: array[0..33] of WCHAR;
  165. WdFlag: DWORD;
  166. InputBufferLength: DWORD;
  167. CfgDLL: array[0..32] of WCHAR;
  168. WdPrefix: array[0..12] of WCHAR;
  169. end;
  170. PWD_CONFIGW = ^_WD_CONFIGW;
  171. TWdConfigW = _WD_CONFIGW;
  172. PWdConfigW = PWD_CONFIGW;
  173. // WinStationConfig class, returns information about the client's
  174. // configuration such as network, time(zone) settings and such
  175. _WINSTATION_CONFIGW = record
  176. Reserved1: DWORD;
  177. ClientName: array[0..20] of WCHAR;
  178. Domain: array[0..17] of WCHAR;
  179. Username: array[0..35] of WCHAR;
  180. CurrentDirectory: array[0..256] of WCHAR;
  181. ApplicationName:array[0..259] of WCHAR;
  182. Reserved2: DWORD;
  183. AddressFamily: DWORD; // AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
  184. ClientAddress: array[0..27] of WCHAR;
  185. Reserved3: array[0..7] of BYTE;
  186. Reserved4: array[0..4] of DWORD;
  187. Reserved5: array[0..69] of BYTE;
  188. ClientDLLName: array[0..330] of WCHAR;
  189. Reserved6: array[0..1] of FILETIME;
  190. AudioDriver: array[0..9] of WCHAR;
  191. TZBias: DWORD;
  192. TZStandardName: array[0..31] of WCHAR;
  193. Reserved7: DWORD; // Standard Bias??
  194. TZDaylightName: array[0..31] of WCHAR;
  195. TZDayLightStart: array[0..15] of BYTE;
  196. TZDayLightBias: DWORD;
  197. Reserved8: DWORD; // Daylight offset?
  198. TSInstanceID: array[0..33] of WCHAR; // sometimes windows license key(s)
  199. Reserved9: DWORD; // related to license key or instanceid?
  200. end;
  201. PWINSTATION_CONFIGW = ^_WINSTATION_CONFIGW;
  202. TWinStationConfigW = _WINSTATION_CONFIGW;
  203. PWinStationConfigW = PWINSTATION_CONFIGW;
  204. // class WinStationInformationClass
  205. // provides information about the current state of the client such as
  206. // idletime, sessionstatus and transferred/received bytes
  207. _WINSTATION_INFORMATIONW = record
  208. State: DWORD;
  209. WinStationName: array[0..10] of WideChar;
  210. Unknown1: array[0..10] of byte;
  211. Unknown3: array[0..10] of WideChar;
  212. Unknown2: array[0..8] of byte;
  213. SessionId: DWORD;
  214. Reserved2: array[0..3] of byte;
  215. ConnectTime: FILETIME;
  216. DisconnectTime: FILETIME;
  217. LastInputTime: FILETIME;
  218. LogonTime: FILETIME;
  219. Unknown4: array[0..11] of byte;
  220. OutgoingFrames: DWORD;
  221. OutgoingBytes: DWORD;
  222. OutgoingCompressBytes: DWORD;
  223. Unknown5: array[0..435] of byte;
  224. IncomingCompressedBytes: DWORD;
  225. Unknown6: array[0..7] of byte;
  226. IncomingFrames: DWORD;
  227. IncomingBytes: DWORD;
  228. Unknown7: array[0..3] of byte;
  229. Reserved3: array[0..528] of byte;
  230. Domain: array[0..17] of WideChar;
  231. Username: array[0..22] of WideChar;
  232. CurrentTime: FILETIME;
  233. end;
  234. PWINSTATION_INFORMATIONW = ^_WINSTATION_INFORMATIONW;
  235. TWinStationInformationExW = _WINSTATION_INFORMATIONW;
  236. PWinStationInformationExW = PWINSTATION_INFORMATIONW;
  237. // WinStationRemoteAddress (class 29)
  238. // Definition is preliminary
  239. // AddressFamily can be AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
  240. // Port is the remote port number (local port number is 3389 by default)
  241. // Address (for type AF_INET it start's at a 2 byte offset)
  242. // You can format IP Address to string like this:
  243. // Format('%d.%d.%d.%d', [WinStationAddress.Address[2],
  244. // WinStationRemoteAddress.[3], WinStationRemoteAddress.Address[4],
  245. // WinStationRemoteAddress..Address[5]]);
  246. //
  247. // Be sure to fill the structure with zeroes before query!
  248. _WINSTATION_REMOTE_ADDRESS = record
  249. AddressFamily: DWORD;
  250. Port: WORD;
  251. Address: array [0..19] of BYTE;
  252. Reserved: array[0..5] of BYTE;
  253. end;
  254. PWINSTATION_REMOTE_ADDRESS = ^_WINSTATION_REMOTE_ADDRESS;
  255. TWinStationRemoteAddress = _WINSTATION_REMOTE_ADDRESS;
  256. PWinStationRemoteAddress = PWINSTATION_REMOTE_ADDRESS;
  257. function AreWeRunningTerminalServices: Boolean;
  258. procedure CachedGetUserFromSid(pSid: PSID; pUserName: LPWSTR;
  259. var cbUserName: DWORD); stdcall;
  260. function CalculateDiffTime(TimeLow: INT64; TimeHigh: INT64): INT64;
  261. stdcall;
  262. // Calculate Elapsed time from a Filetime (UTC time) to DiffTime structure
  263. function CalculateElapsedTime(lpFileTime: PFILETIME; var DiffTime: TDiffTime):
  264. Boolean; stdcall;
  265. function CpuTime2Str(ACPUTime: LARGE_INTEGER): string;
  266. function CurrentDateTimeString(out lpBuffer: PWideChar): Boolean; stdcall;
  267. // This is the version for NT Terminal Server, 2000, XP/2003 and Server 2008
  268. function DateTimeString(DateTime: PFILETIME; lpBuffer: PWideChar): PWideChar;
  269. stdcall;
  270. // This is a wrapped for all OS versions
  271. function DateTimeStringSafe(DateTime: PFILETIME; lpBuffer: PWideChar;
  272. cchDest: SIZE_T): PWideChar; stdcall;
  273. // This is the Vista version which takes an additional parameter with
  274. // maximum buffer size (you have to set it)
  275. function DateTimeStringVista(DateTime: PFILETIME; lpBuffer: PWideChar;
  276. cchDest: SIZE_T): PWideChar; stdcall;
  277. function DiffTimeString(FTLow: FILETIME; FTHigh: FILETIME;
  278. out pwElapsedTime: PWideChar): Integer;
  279. // This is the version for NT Terminal Server, 2000, XP/2003 and Server 2008
  280. function ElapsedTimeString(DiffTime: PDiffTime; bShowSeconds: Boolean;
  281. lpElapsedTime: PWideChar): Integer; stdcall;
  282. // This is a wrapped for all OS versions
  283. function ElapsedTimeStringSafe(DiffTime: PDiffTime; bShowSeconds: Boolean;
  284. lpElapsedTime: PWideChar; cchDest: SIZE_T): Integer;
  285. // This is the Vista version of ElapsedTimeString which takes an additional
  286. // parameter with the count of characters for lpElapsedTime (you have to set it)
  287. function ElapsedTimeStringEx(DiffTime: PDiffTime; bShowSeconds: Boolean;
  288. lpElapsedTime: PWideChar; cchDest: SIZE_T): HRESULT; stdcall;
  289. function FileTime2DateTime(FileTime: TFileTime): TDateTime;
  290. function GetUnknownString: PWideChar; stdcall;
  291. function GetWTSLogonIdleTime(hServer: Handle; SessionId: DWORD;
  292. var sLogonTime: string; var sIdleTime: string): Boolean;
  293. // Helper function that inits the structure for you!
  294. procedure InitTermSrvCounterArray(
  295. var ATermSrvCounterArray: TTermSrvCounterArray);
  296. function IsTerminalServiceRunning: boolean;
  297. // Tested and working on Windows XP but doesn't seem to work on
  298. // Windows Vista/2008. Better use W version to be sure!
  299. function LogonIdFromWinStationNameA(hServer: HANDLE; pWinStationName: LPSTR;
  300. var SessionId: DWORD): BOOL; stdcall;
  301. // Tested and working on XP, 2003 and 2008
  302. function LogonIdFromWinStationNameW(hServer: HANDLE; pWinStationName: LPWSTR;
  303. var SessionId: DWORD): BOOL; stdcall;
  304. // This is the version for NT Terminal Server, 2000, XP/2003 and Server 2008
  305. // Reserve 66 bytes for pWinStationName and 21 for pUserName
  306. function QueryCurrentWinStation(pWinStationName: LPWSTR;
  307. pUserName: LPWSTR; var SessionId: DWORD; var WdFlag: DWORD): Boolean;
  308. stdcall;
  309. // This is the Vista version of QueryCurrentWinStation which takes an
  310. // additional parameter with the count of characters for pUserName
  311. // note that pWinStationname is Fixed Size!
  312. function QueryCurrentWinStationEx(pWinStationName: LPWSTR;
  313. pUserName: PWideChar; cchDest: DWORD; var SessionId: DWORD;
  314. var WdFlag: DWORD): Boolean; stdcall;
  315. function QueryCurrentWinStationSafe(pWinStationName: LPWSTR;
  316. pUserName: PWideChar; cchDest: DWORD; var SessionId: DWORD;
  317. var WdFlag: DWORD): Boolean; stdcall;
  318. function StrConnectState(ConnectState: WTS_CONNECTSTATE_CLASS;
  319. bShortString: BOOL): PWideChar; stdcall;
  320. function WinStationBroadcastSystemMessage(hServer: HANDLE;
  321. SendToAllWinstations: BOOL; SessionId: DWORD; TimeOut: DWORD;
  322. dwFlags: DWORD; lpdwRecipients: DWORD; uiMessage: ULONG; wParam: WPARAM;
  323. lParam: LPARAM; pResponse: LONGINT): LONGINT; stdcall;
  324. function WinStationCallBack(hServer:HANDLE; SessionId: DWORD;
  325. pPhoneNumber: LPWSTR): BOOL; stdcall;
  326. function WinStationConnectW(hServer: Handle; SessionId: DWORD;
  327. TargetSessionId: DWORD; pPassword: LPWSTR;
  328. bWait: BOOL): BOOL; stdcall;
  329. function WinStationDisconnect(hServer: THandle; SessionId: DWORD;
  330. bWait: BOOL): BOOL; stdcall;
  331. function WinStationEnumerateA(hServer: HANDLE;
  332. var ppSessionInfo: PWTS_SESSION_INFOA; var pCount: DWORD): BOOL; stdcall;
  333. function WinStationEnumerateW(hServer: HANDLE;
  334. var ppSessionInfo: PWTS_SESSION_INFOW; var pCount: DWORD): BOOL; stdcall;
  335. // Used to release memory allocated by WinStationGetAllProcesses
  336. function WinStationFreeGAPMemory(ClassIndex: DWORD;
  337. pProcessInfo: PWINSTA_PROCESS_INFO_ARRAY; Count: Integer): BOOL; stdcall;
  338. // Important! pProcessInfo must be nil before calling this function
  339. // by using Out parameter Delphi takes care of this for us
  340. function WinStationGetAllProcesses(hServer: HANDLE; ClassIndex: DWORD;
  341. var Count: Integer; out pProcessInfo: PWINSTA_PROCESS_INFO_ARRAY):
  342. BOOL; stdcall;
  343. function WinStationGetLanAdapterNameW(hServer: HANDLE; LanaId: DWORD;
  344. ProtocolTypeLength: DWORD; ProtocolType: PWideChar;
  345. var ResultLength: DWORD; var LanAdapterName: PWideChar): DWORD; stdcall;
  346. function WinStationGetProcessSid(hServer: Handle; dwPID: DWORD;
  347. ProcessStartTime: FILETIME; pProcessUserSid: PSID; var dwSidSize: DWORD):
  348. BOOL; stdcall;
  349. function WinStationGetRemoteIPAddress(hServer: HANDLE; SessionId: DWORD;
  350. var RemoteIPAddress: string; var Port: WORD): Boolean;
  351. function WinStationGetTermSrvCountersValue(hServer: Handle;
  352. dwArraySize: DWORD; PCountersArray: PTERM_SRV_COUNTER_ARRAY): BOOL;
  353. stdcall;
  354. function WinStationNameFromLogonIdA(hServer: HANDLE; SessionId: ULONG;
  355. pWinStationName: LPSTR): BOOL; stdcall;
  356. function WinStationNameFromLogonIdW(hServer: HANDLE; SessionId: ULONG;
  357. pWinStationName: LPWSTR): BOOL; stdcall;
  358. function WinStationQueryInformationW(hServer: HANDLE; SessionId: DWORD;
  359. WinStationInformationClass: Cardinal; pWinStationInformation: PVOID;
  360. WinStationInformationLength: DWORD; var pReturnLength: DWORD):
  361. Boolean; stdcall;
  362. function WinStationQueryLogonCredentialsW(
  363. var LogonCredentials: _LOGON_CREDENTIALSW): HRESULT; stdcall;
  364. function WinstationQueryUserToken(hServer: HANDLE; SessionId: DWORD;
  365. var hToken: HANDLE): BOOL;
  366. // WinStationRename needs Admin rights and always returns true
  367. // need to check GetLastError
  368. // Duplicate names are not allowed
  369. // Renaming a WinStation gives errors on Remote Connections:
  370. // the windowstation is busy processing connect, disconnect, reset
  371. // or login request
  372. // A version untested
  373. function WinStationRenameA(hServer: HANDLE; pOldWinStationName: LPSTR;
  374. pNewWinStationName: LPSTR): BOOL; stdcall;
  375. // W version was tested
  376. function WinStationRenameW(hServer: HANDLE; pOldWinStationName: LPWSTR;
  377. pNewWinStationName: LPWSTR): BOOL; stdcall;
  378. function WinStationSendMessageA(hServer: HANDLE; SessionId: DWORD;
  379. pTitle: LPSTR; TitleLength: DWORD; pMessage: LPSTR; MessageLength: DWORD;
  380. Style: DWORD; Timeout: DWORD; var pResponse: DWORD;
  381. bWait: BOOL): BOOL; stdcall;
  382. function WinStationSendMessageW(hServer: HANDLE; SessionId: DWORD;
  383. pTitle: LPWSTR; TitleLength: DWORD; pMessage: LPWSTR; MessageLength: DWORD;
  384. Style: DWORD; Timeout: DWORD; var pResponse: DWORD;
  385. bWait: BOOL): BOOL; stdcall;
  386. function WinStationSetInformationA(hServer: HANDLE; SessionID: DWORD;
  387. InformationClass: DWORD; InformationClassDATA: PVOID;
  388. DataSize: DWORD): BOOL; stdcall;
  389. function WinStationSetInformationW(hServer: HANDLE; SessionID: DWORD;
  390. InformationClass: DWORD; InformationClassDATA: PVOID;
  391. DataSize: DWORD): BOOL; stdcall;
  392. function WinStationShadow(hServer: Handle; pServerName: LPWSTR;
  393. SessionId: DWORD; HotKey: DWORD; HKModifier: DWORD): BOOL; stdcall;
  394. // Admin can stop a shadowed session. SessionId is the targetsession
  395. // so the "victim" and not the one who is shadowing
  396. function WinStationShadowStop(hServer: Handle; SessionId: DWORD;
  397. bWait: BOOL): BOOL; stdcall;
  398. function WinStationShutDownSystem(hSERVER: HANDLE;
  399. ShutdownFlags: DWORD): BOOL; stdcall;
  400. function WinStationTerminateProcess(hServer: Handle; dwPID: DWORD;
  401. dwExitCode: DWORD): BOOL; stdcall;
  402. {$ENDIF JWA_IMPLEMENTATIONSECTION}
  403. {$IFNDEF JWA_OMIT_SECTIONS}
  404. implementation
  405. uses
  406. JwaWinDLLNames;
  407. {$ENDIF JWA_OMIT_SECTIONS}
  408. {$IFNDEF JWA_INCLUDEMODE}
  409. const
  410. winstadll = 'winsta.dll';
  411. utildll = 'utildll.dll';
  412. {$ENDIF JWA_INCLUDEMODE}
  413. {$IFNDEF JWA_INTERFACESECTION}
  414. {$IFNDEF DYNAMIC_LINK}
  415. procedure CachedGetUserFromSid; external utildll name 'CachedGetUserFromSid';
  416. function CalculateDiffTime; external utildll name 'CalculateDiffTime';
  417. function CalculateElapsedTime; external utildll name 'CalculateElapsedTime';
  418. function CurrentDateTimeString; external utildll name 'CurrentDateTimeString';
  419. function DateTimeString; external utildll name 'DateTimeString';
  420. function DateTimeStringVista; external utildll name 'DateTimeString';
  421. function ElapsedTimeString; external utildll name 'ElapsedTimeString';
  422. // Vista version of ElapsedTimeString, exported name is ElapsedTimeString
  423. function ElapsedTimeStringEx; external utildll name 'ElapsedTimeString';
  424. function GetUnknownString; external utildll name 'GetUnknownString';
  425. function LogonIdFromWinStationNameA; external winstadll name 'LogonIdFromWinStationNameA';
  426. function LogonIdFromWinStationNameW; external winstadll name 'LogonIdFromWinStationNameW';
  427. function QueryCurrentWinStation; external utildll name 'QueryCurrentWinStation';
  428. function QueryCurrentWinStationEx; external utildll name 'QueryCurrentWinStation';
  429. function StrConnectState; external utildll name 'StrConnectState';
  430. function WinStationBroadcastSystemMessage; external winstadll name 'WinStationBroadcastSystemMessage';
  431. function WinStationCallBack; external winstadll name 'WinStationCallBack';
  432. function WinStationConnectW; external winstadll name 'WinStationConnectW';
  433. function WinStationDisconnect; external winstadll name 'WinStationDisconnect';
  434. function WinStationEnumerateA; external winstadll name 'WinStationEnumerateA';
  435. function WinStationEnumerateW; external winstadll name 'WinStationEnumerateW';
  436. function WinStationFreeGAPMemory; external winstadll name 'WinStationFreeGAPMemory';
  437. function WinStationGetAllProcesses; external winstadll name 'WinStationGetAllProcesses';
  438. function WinStationGetLanAdapterNameW; external winstadll name 'WinStationGetLanAdapterNameW';
  439. function WinStationGetProcessSid; external winstadll name 'WinStationGetProcessSid';
  440. function WinStationGetTermSrvCountersValue; external winstadll name 'WinStationGetTermSrvCountersValue';
  441. function WinStationNameFromLogonIdA; external winstadll name 'WinStationNameFromLogonIdA';
  442. function WinStationNameFromLogonIdW; external winstadll name 'WinStationNameFromLogonIdW';
  443. function WinStationQueryLogonCredentialsW; external winstadll name 'WinStationQueryLogonCredentialsW';
  444. function WinStationRenameA; external winstadll name 'WinStationRenameA';
  445. function WinStationRenameW; external winstadll name 'WinStationRenameW';
  446. function WinStationSendMessageA; external winstadll name 'WinStationSendMessageA';
  447. function WinStationSendMessageW; external winstadll name 'WinStationSendMessageW';
  448. function WinStationSetInformationA; external winstadll name 'WinStationSetInformationA';
  449. function WinStationSetInformationW; external winstadll name 'WinStationSetInformationW';
  450. function WinStationShadow; external winstadll name 'WinStationShadow';
  451. function WinStationShadowStop; external winstadll name 'WinStationShadowStop';
  452. function WinStationShutDownSystem; external winstadll name 'WinStationShutDownSystem';
  453. function WinStationQueryInformationW; external winstadll name 'WinStationQueryInformationW';
  454. function WinStationTerminateProcess; external winstadll name 'WinStationTerminateProcess';
  455. {$ELSE}
  456. var
  457. __CachedGetUserFromSid: Pointer;
  458. procedure CachedGetUserFromSid;
  459. begin
  460. GetProcedureAddress(__CachedGetUserFromSid, utildll, 'CachedGetUserFromSid');
  461. asm
  462. MOV ESP, EBP
  463. POP EBP
  464. JMP [__CachedGetUserFromSid]
  465. end;
  466. end;
  467. var
  468. __CalculateDiffTime: Pointer;
  469. function CalculateDiffTime;
  470. begin
  471. GetProcedureAddress(__CalculateDiffTime, utildll, 'CalculateDiffTime');
  472. asm
  473. MOV ESP, EBP
  474. POP EBP
  475. JMP [__CalculateDiffTime]
  476. end;
  477. end;
  478. var
  479. __CalculateElapsedTime: Pointer;
  480. function CalculateElapsedTime;
  481. begin
  482. GetProcedureAddress(__CalculateElapsedTime, utildll, 'CalculateElapsedTime');
  483. asm
  484. MOV ESP, EBP
  485. POP EBP
  486. JMP [__CalculateElapsedTime]
  487. end;
  488. end;
  489. var
  490. __CurrentDateTimeString: Pointer;
  491. function CurrentDateTimeString;
  492. begin
  493. GetProcedureAddress(__CurrentDateTimeString, utildll, 'CurrentDateTimeString');
  494. asm
  495. MOV ESP, EBP
  496. POP EBP
  497. JMP [__CurrentDateTimeString]
  498. end;
  499. end;
  500. var
  501. __DateTimeString: Pointer;
  502. function DateTimeString;
  503. begin
  504. GetProcedureAddress(__DateTimeString, utildll, 'DateTimeString');
  505. asm
  506. MOV ESP, EBP
  507. POP EBP
  508. JMP [__DateTimeString]
  509. end;
  510. end;
  511. var
  512. __DateTimeStringVista: Pointer;
  513. function DateTimeStringVista;
  514. begin
  515. GetProcedureAddress(__DateTimeStringVista, utildll, 'DateTimeString');
  516. asm
  517. MOV ESP, EBP
  518. POP EBP
  519. JMP [__DateTimeStringVista]
  520. end;
  521. end;
  522. var
  523. __ElapsedTimeString: Pointer;
  524. function ElapsedTimeString;
  525. begin
  526. GetProcedureAddress(__ElapsedTimeString, utildll, 'ElapsedTimeString');
  527. asm
  528. MOV ESP, EBP
  529. POP EBP
  530. JMP [__ElapsedTimeString]
  531. end;
  532. end;
  533. var
  534. __ElapsedTimeStringEx: Pointer;
  535. function ElapsedTimeStringEx;
  536. begin
  537. GetProcedureAddress(__ElapsedTimeStringEx, utildll, 'ElapsedTimeString');
  538. asm
  539. MOV ESP, EBP
  540. POP EBP
  541. JMP [__ElapsedTimeStringEx]
  542. end;
  543. end;
  544. var
  545. __GetUnknownString: Pointer;
  546. function GetUnknownString;
  547. begin
  548. GetProcedureAddress(__GetUnknownString, utildll, 'GetUnknownString');
  549. asm
  550. MOV ESP, EBP
  551. POP EBP
  552. JMP [__GetUnknownString]
  553. end;
  554. end;
  555. var
  556. __LogonIdFromWinStationNameA: Pointer;
  557. function LogonIdFromWinStationNameA;
  558. begin
  559. GetProcedureAddress(__LogonIdFromWinStationNameA, winstadll, 'LogonIdFromWinStationNameA');
  560. asm
  561. MOV ESP, EBP
  562. POP EBP
  563. JMP [__LogonIdFromWinStationNameA]
  564. end;
  565. end;
  566. var
  567. __LogonIdFromWinStationNameW: Pointer;
  568. function LogonIdFromWinStationNameW;
  569. begin
  570. GetProcedureAddress(__LogonIdFromWinStationNameW, winstadll, 'LogonIdFromWinStationNameW');
  571. asm
  572. MOV ESP, EBP
  573. POP EBP
  574. JMP [__LogonIdFromWinStationNameW]
  575. end;
  576. end;
  577. var
  578. __QueryCurrentWinStation: Pointer;
  579. function QueryCurrentWinStation;
  580. begin
  581. GetProcedureAddress(__QueryCurrentWinStation, utildll, 'QueryCurrentWinStation');
  582. asm
  583. MOV ESP, EBP
  584. POP EBP
  585. JMP [__QueryCurrentWinStation]
  586. end;
  587. end;
  588. var
  589. __QueryCurrentWinStationEx: Pointer;
  590. function QueryCurrentWinStationEx;
  591. begin
  592. GetProcedureAddress(__QueryCurrentWinStationEx, utildll, 'QueryCurrentWinStation');
  593. asm
  594. MOV ESP, EBP
  595. POP EBP
  596. JMP [__QueryCurrentWinStationEx]
  597. end;
  598. end;
  599. var
  600. __StrConnectState: Pointer;
  601. function StrConnectState;
  602. begin
  603. GetProcedureAddress(__StrConnectState, utildll, 'StrConnectState');
  604. asm
  605. MOV ESP, EBP
  606. POP EBP
  607. JMP [__StrConnectState]
  608. end;
  609. end;
  610. var
  611. __WinStationBroadcastSystemMessage: Pointer;
  612. function WinStationBroadcastSystemMessage;
  613. begin
  614. GetProcedureAddress(__WinStationBroadcastSystemMessage, winstadll, 'WinStationBroadcastSystemMessage');
  615. asm
  616. MOV ESP, EBP
  617. POP EBP
  618. JMP [__WinStationBroadcastSystemMessage]
  619. end;
  620. end;
  621. var
  622. __WinStationCallBack: Pointer;
  623. function WinStationCallBack;
  624. begin
  625. GetProcedureAddress(__WinStationCallBack, winstadll, 'WinStationCallBack');
  626. asm
  627. MOV ESP, EBP
  628. POP EBP
  629. JMP [__WinStationCallBack]
  630. end;
  631. end;
  632. var
  633. __WinStationConnectW: Pointer;
  634. function WinStationConnectW;
  635. begin
  636. GetProcedureAddress(__WinStationConnectW, winstadll, 'WinStationConnectW');
  637. asm
  638. MOV ESP, EBP
  639. POP EBP
  640. JMP [__WinStationConnectW]
  641. end;
  642. end;
  643. var
  644. __WinStationDisconnect: Pointer;
  645. function WinStationDisconnect;
  646. begin
  647. GetProcedureAddress(__WinStationDisconnect, winstadll, 'WinStationDisconnect');
  648. asm
  649. MOV ESP, EBP
  650. POP EBP
  651. JMP [__WinStationDisconnect]
  652. end;
  653. end;
  654. var
  655. __WinStationEnumerateA: Pointer;
  656. function WinStationEnumerateA;
  657. begin
  658. GetProcedureAddress(__WinStationEnumerateA, winstadll, 'WinStationEnumerateA');
  659. asm
  660. MOV ESP, EBP
  661. POP EBP
  662. JMP [__WinStationEnumerateA]
  663. end;
  664. end;
  665. var
  666. __WinStationEnumerateW: Pointer;
  667. function WinStationEnumerateW;
  668. begin
  669. GetProcedureAddress(__WinStationEnumerateW, winstadll, 'WinStationEnumerateW');
  670. asm
  671. MOV ESP, EBP
  672. POP EBP
  673. JMP [__WinStationEnumerateW]
  674. end;
  675. end;
  676. var
  677. __WinStationFreeGAPMemory: Pointer;
  678. function WinStationFreeGAPMemory;
  679. begin
  680. GetProcedureAddress(__WinStationFreeGAPMemory, winstadll, 'WinStationFreeGAPMemory');
  681. asm
  682. MOV ESP, EBP
  683. POP EBP
  684. JMP [__WinStationFreeGAPMemory]
  685. end;
  686. end;
  687. var
  688. __WinStationGetAllProcesses: Pointer;
  689. function WinStationGetAllProcesses;
  690. begin
  691. GetProcedureAddress(__WinStationGetAllProcesses, winstadll, 'WinStationGetAllProcesses');
  692. asm
  693. MOV ESP, EBP
  694. POP EBP
  695. JMP [__WinStationGetAllProcesses]
  696. end;
  697. end;
  698. var
  699. __WinStationGetLanAdapterNameW: Pointer;
  700. function WinStationGetLanAdapterNameW;
  701. begin
  702. GetProcedureAddress(__WinStationGetLanAdapterNameW, winstadll, 'WinStationGetLanAdapterNameW');
  703. asm
  704. MOV ESP, EBP
  705. POP EBP
  706. JMP [__WinStationGetLanAdapterNameW]
  707. end;
  708. end;
  709. var
  710. __WinStationGetProcessSid: Pointer;
  711. function WinStationGetProcessSid;
  712. begin
  713. GetProcedureAddress(__WinStationGetProcessSid, winstadll, 'WinStationGetProcessSid');
  714. asm
  715. MOV ESP, EBP
  716. POP EBP
  717. JMP [__WinStationGetProcessSid]
  718. end;
  719. end;
  720. var
  721. __WinStationGetTermSrvCountersValue: Pointer;
  722. function WinStationGetTermSrvCountersValue;
  723. begin
  724. GetProcedureAddress(__WinStationGetTermSrvCountersValue, winstadll, 'WinStationGetTermSrvCountersValue');
  725. asm
  726. MOV ESP, EBP
  727. POP EBP
  728. JMP [__WinStationGetTermSrvCountersValue]
  729. end;
  730. end;
  731. var
  732. __WinStationNameFromLogonIdA: Pointer;
  733. function WinStationNameFromLogonIdA;
  734. begin
  735. GetProcedureAddress(__WinStationNameFromLogonIdA, winstadll, 'WinStationNameFromLogonIdA');
  736. asm
  737. MOV ESP, EBP
  738. POP EBP
  739. JMP [__WinStationNameFromLogonIdA]
  740. end;
  741. end;
  742. var
  743. __WinStationNameFromLogonIdW: Pointer;
  744. function WinStationNameFromLogonIdW;
  745. begin
  746. GetProcedureAddress(__WinStationNameFromLogonIdW, winstadll, 'WinStationNameFromLogonIdW');
  747. asm
  748. MOV ESP, EBP
  749. POP EBP
  750. JMP [__WinStationNameFromLogonIdW]
  751. end;
  752. end;
  753. var
  754. __WinStationQueryLogonCredentialsW: Pointer;
  755. function WinStationQueryLogonCredentialsW;
  756. begin
  757. GetProcedureAddress(__WinStationQueryLogonCredentialsW, winstadll, 'WinStationQueryLogonCredentialsW');
  758. asm
  759. MOV ESP, EBP
  760. POP EBP
  761. JMP [__WinStationQueryLogonCredentialsW]
  762. end;
  763. end;
  764. var
  765. __WinStationRenameA: Pointer;
  766. function WinStationRenameA;
  767. begin
  768. GetProcedureAddress(__WinStationRenameA, winstadll, 'WinStationRenameA');
  769. asm
  770. MOV ESP, EBP
  771. POP EBP
  772. JMP [__WinStationRenameA]
  773. end;
  774. end;
  775. var
  776. __WinStationRenameW: Pointer;
  777. function WinStationRenameW;
  778. begin
  779. GetProcedureAddress(__WinStationRenameW, winstadll, 'WinStationRenameW');
  780. asm
  781. MOV ESP, EBP
  782. POP EBP
  783. JMP [__WinStationRenameW]
  784. end;
  785. end;
  786. var
  787. __WinStationQueryInformationW: Pointer;
  788. function WinStationQueryInformationW;
  789. begin
  790. GetProcedureAddress(__WinStationQueryInformationW, winstadll, 'WinStationQueryInformationW');
  791. asm
  792. MOV ESP, EBP
  793. POP EBP
  794. JMP [__WinStationQueryInformationW]
  795. end;
  796. end;
  797. var
  798. __WinStationSendMessageA: Pointer;
  799. function WinStationSendMessageA;
  800. begin
  801. GetProcedureAddress(__WinStationSendMessageA, winstadll, 'WinStationSendMessageA');
  802. asm
  803. MOV ESP, EBP
  804. POP EBP
  805. JMP [__WinStationSendMessageA]
  806. end;
  807. end;
  808. var
  809. __WinStationSendMessageW: Pointer;
  810. function WinStationSendMessageW;
  811. begin
  812. GetProcedureAddress(__WinStationSendMessageW, winstadll, 'WinStationSendMessageW');
  813. asm
  814. MOV ESP, EBP
  815. POP EBP
  816. JMP [__WinStationSendMessageW]
  817. end;
  818. end;
  819. var
  820. __WinStationSetInformationA: Pointer;
  821. function WinStationSetInformationA;
  822. begin
  823. GetProcedureAddress(__WinStationSetInformationA, winstadll, 'WinStationSetInformationA');
  824. asm
  825. MOV ESP, EBP
  826. POP EBP
  827. JMP [__WinStationSetInformationA]
  828. end;
  829. end;
  830. var
  831. __WinStationSetInformationW: Pointer;
  832. function WinStationSetInformationW;
  833. begin
  834. GetProcedureAddress(__WinStationSetInformationW, winstadll, 'WinStationSetInformationW');
  835. asm
  836. MOV ESP, EBP
  837. POP EBP
  838. JMP [__WinStationSetInformationW]
  839. end;
  840. end;
  841. var
  842. __WinStationShadow: Pointer;
  843. function WinStationShadow;
  844. begin
  845. GetProcedureAddress(__WinStationShadow, winstadll, 'WinStationShadow');
  846. asm
  847. MOV ESP, EBP
  848. POP EBP
  849. JMP [__WinStationShadow]
  850. end;
  851. end;
  852. var
  853. __WinStationShadowStop : Pointer;
  854. function WinStationShadowStop;
  855. begin
  856. GetProcedureAddress(__WinStationShadowStop, winstadll, 'WinStationShadowStop');
  857. asm
  858. MOV ESP, EBP
  859. POP EBP
  860. JMP [__WinStationShadowStop]
  861. end;
  862. end;
  863. var
  864. __WinStationShutDownSystem : Pointer;
  865. function WinStationShutDownSystem;
  866. begin
  867. GetProcedureAddress(__WinStationShutDownSystem, winstadll, 'WinStationShutDownSystem');
  868. asm
  869. MOV ESP, EBP
  870. POP EBP
  871. JMP [__WinStationShutDownSystem]
  872. end;
  873. end;
  874. var
  875. __WinStationTerminateProcess: Pointer;
  876. function WinStationTerminateProcess;
  877. begin
  878. GetProcedureAddress(__WinStationTerminateProcess, winstadll, 'WinStationTerminateProcess');
  879. asm
  880. MOV ESP, EBP
  881. POP EBP
  882. JMP [__WinStationTerminateProcess]
  883. end;
  884. end;
  885. {$ENDIF DYNAMIC_LINK}
  886. // This function is not exported
  887. function IsVista: boolean;
  888. var VersionInfo: TOSVersionInfoEx;
  889. begin
  890. // Zero Memory and set structure size
  891. ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
  892. VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
  893. GetVersionEx(@VersionInfo);
  894. // Are we running Vista?
  895. Result := (VersionInfo.dwMajorVersion = 6) and
  896. (VersionInfo.dwMinorVersion = 0) and
  897. (VersionInfo.wProductType = VER_NT_WORKSTATION);
  898. end;
  899. // This the way QWinsta checks if Terminal Services is active:
  900. function AreWeRunningTerminalServices: Boolean;
  901. var VersionInfo: TOSVersionInfoEx;
  902. dwlConditionMask: Int64;
  903. begin
  904. // Zero Memory and set structure size
  905. ZeroMemory(@VersionInfo, SizeOf(VersionInfo));
  906. VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
  907. // We are either Terminal Server or Personal Terminal Server
  908. VersionInfo.wSuiteMask := VER_SUITE_TERMINAL or VER_SUITE_SINGLEUSERTS;
  909. dwlConditionMask := VerSetConditionMask(0, VER_SUITENAME, VER_OR);
  910. // Test it
  911. Result := VerifyVersionInfo(VersionInfo, VER_SUITENAME, dwlConditionMask);
  912. end;
  913. // This functions converts CPU times as returned by
  914. // TSystemProcesses structure to a string
  915. function CpuTime2Str(ACPUTime: LARGE_INTEGER): String;
  916. var SystemTime: TSystemTime;
  917. {$IFDEF COMPILER7_UP}
  918. FS: TFormatSettings;
  919. {$ENDIF COMPILER7_UP}
  920. begin
  921. FileTimeToSystemTime(FILETIME(ACPUTime), SystemTime);
  922. {$IFDEF COMPILER7_UP}
  923. GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, FS);
  924. Result := TimeToStr(SystemTimeToDateTime(SystemTime), FS);
  925. {$ELSE}
  926. Result := TimeToStr(SystemTimeToDateTime(SystemTime));
  927. {$ENDIF COMPILER7_UP}
  928. end;
  929. function DateTimeStringSafe(DateTime: PFILETIME; lpBuffer: PWideChar;
  930. cchDest: SIZE_T): PWideChar; stdcall;
  931. begin
  932. // Zero Memory
  933. ZeroMemory(lpBuffer, cchDest * SizeOf(WCHAR));
  934. // Are we running Vista?
  935. if IsVista then
  936. begin
  937. // Vista version
  938. Result := DateTimeStringVista(DateTime, lpBuffer, cchDest);
  939. end
  940. else begin
  941. // Other OS's (including server 2008!)
  942. Result := DateTimeString(DateTime, lpBuffer);
  943. end;
  944. end;
  945. // DiffTimeString is a helper function that returns a formatted
  946. // Elapsed time string (the way Idle Time is displayed in TSAdmin)
  947. // Return value is the string length
  948. function DiffTimeString(FTLow: FILETIME; FTHigh: FILETIME;
  949. out pwElapsedTime: PWideChar): Integer;
  950. var
  951. DiffSecs: INT64;
  952. DiffTime: TDiffTime;
  953. NumChars: DWORD;
  954. begin
  955. // Get the Difftime where Time1 is the "oldest" time
  956. // Return value is the difference in seconds
  957. DiffSecs := CalculateDiffTime(Int64(FTLow), Int64(FTHigh));
  958. // Recalc DiffTime to TDiffTime
  959. ZeroMemory(@DiffTime, SizeOf(DiffTime));
  960. // Calculate no of whole days
  961. DiffTime.wDays := DiffSecs DIV SECONDS_PER_DAY;
  962. // Calculate no of whole hours
  963. DiffTime.wHours := DiffSecs MOD SECONDS_PER_DAY DIV SECONDS_PER_HOUR;
  964. // Calculate no of whole minutes
  965. DiffTime.wMinutes := DiffSecs MOD SECONDS_PER_DAY MOD SECONDS_PER_HOUR
  966. DIV SECONDS_PER_MINUTE; // Result = No of whole minutes
  967. // Calculate no of whole seconds
  968. DiffTime.wSeconds := DiffSecs MOD SECONDS_PER_DAY MOD SECONDS_PER_HOUR
  969. MOD SECONDS_PER_MINUTE; // Result = No of seconds
  970. // Note that Milliseconds are not used and therefore not calculated
  971. // Reserve Memory
  972. GetMem(pwElapsedTime, ELAPSED_TIME_STRING_LENGTH * SizeOf(WCHAR));
  973. // Format Elapsed TimeString in minutes (bShowSeconds = False)
  974. NumChars := ElapsedTimeStringSafe(@DiffTime, False, pwElapsedTime,
  975. ELAPSED_TIME_STRING_LENGTH);
  976. Result := NumChars;
  977. // Caller has to free memory when done
  978. end;
  979. function ElapsedTimeStringSafe(DiffTime: PDiffTime; bShowSeconds: Boolean;
  980. lpElapsedTime: PWideChar; cchDest: SIZE_T): Integer;
  981. var
  982. hr: HRESULT;
  983. begin
  984. // Zero Memory
  985. ZeroMemory(lpElapsedTime, cchDest * SizeOf(WCHAR));
  986. // Are we running Vista?
  987. if IsVista then
  988. begin
  989. hr := ElapsedTimeStringEx(DiffTime, bShowSeconds, lpElapsedTime,
  990. cchDest);
  991. if Succeeded(hr) then
  992. begin
  993. Result := cchDest;
  994. end
  995. else begin
  996. Result := 0;
  997. end;
  998. end
  999. else begin
  1000. Result := ElapsedTimeString(DiffTime, bShowSeconds, lpElapsedTime);
  1001. end;
  1002. // Caller has to free memory when done
  1003. end;
  1004. function FileTime2DateTime(FileTime: TFileTime): TDateTime;
  1005. var LocalFileTime: TFileTime;
  1006. SystemTime: TSystemTime;
  1007. begin
  1008. FileTimeToLocalFileTime(FileTime, LocalFileTime);
  1009. FileTimeToSystemTime(LocalFileTime, SystemTime);
  1010. Result := SystemTimeToDateTime(SystemTime);
  1011. end;
  1012. function GetWTSLogonIdleTime(hServer: HANDLE; SessionId: DWORD;
  1013. var sLogonTime: string; var sIdleTime: string): Boolean;
  1014. var
  1015. uReturnLength: DWORD;
  1016. Info: _WINSTATION_INFORMATIONW;
  1017. CurrentTime: TDateTime;
  1018. LastInputTime: TDateTime;
  1019. IdleTime: TDateTime;
  1020. LogonTime: TDateTime;
  1021. Days, Hours, Minutes: Word;
  1022. {$IFDEF COMPILER7_UP}
  1023. FS: TFormatSettings;
  1024. {$ENDIF COMPILER7_UP}
  1025. begin
  1026. {$IFDEF COMPILER7_UP}
  1027. GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, FS);
  1028. {$ENDIF COMPILER7_UP}
  1029. uReturnLength := 0;
  1030. try
  1031. Result := WinStationQueryInformationW(hServer, SessionId, 8, @Info, SizeOf(Info), uReturnLength);
  1032. if Result then
  1033. begin
  1034. LogonTime := FileTime2DateTime(Info.LogonTime);
  1035. if YearOf(LogonTime) = 1601 then
  1036. sLogonTime := ''
  1037. else
  1038. {$IFDEF COMPILER7_UP}
  1039. sLogonTime := DateTimeToStr(LogonTime, FS);
  1040. {$ELSE}
  1041. sLogonTime := DateTimeToStr(LogonTime);
  1042. {$ENDIF COMPILER7_UP}
  1043. { from Usenet post by Chuck Chopp
  1044. http://groups.google.com/group/microsoft.public.win32.programmer.kernel/browse_thread/thread/c6dd86e7df6d26e4/3cf53e12a3246e25?lnk=st&q=WinStationQueryInformationa+group:microsoft.public.*&rnum=1&hl=en#3cf53e12a3246e25
  1045. 2) The system console session cannot go into an idle/disconnected state.
  1046. As such, the LastInputTime value will always math CurrentTime for the
  1047. console session.
  1048. 3) The LastInputTime value will be zero if the session has gone
  1049. disconnected. In that case, use the DisconnectTime value in place of
  1050. LastInputTime when calculating the current idle time for a disconnected session.
  1051. 4) All of these time values are GMT time values.
  1052. 5) The disconnect time value will be zero if the sesson has never been
  1053. disconnected.}
  1054. CurrentTime := FileTime2DateTime(Info.CurrentTime);
  1055. LastInputTime := FileTime2DateTime(Info.LastInputTime);
  1056. // Disconnected session = idle since DisconnectTime
  1057. if YearOf(LastInputTime) = 1601 then
  1058. LastInputTime := FileTime2DateTime(Info.DisconnectTime);
  1059. IdleTime := LastInputTime - CurrentTime;
  1060. Days := Trunc(IdleTime);
  1061. Hours := HourOf(IdleTime);
  1062. Minutes := MinuteOf(IdleTime);
  1063. if Days > 0 then
  1064. sIdleTime := Format('%dd %d:%1.2d', [Days, Hours, Minutes])
  1065. else
  1066. if Hours > 0 then
  1067. sIdleTime := Format('%d:%1.2d', [Hours, Minutes])
  1068. else
  1069. if Minutes > 0 then
  1070. sIdleTime := IntToStr(Minutes)
  1071. else
  1072. sIdleTime := '-';
  1073. end;
  1074. except
  1075. Result := False;
  1076. end;
  1077. end;
  1078. procedure InitTermSrvCounterArray(var ATermSrvCounterArray: TTermSrvCounterArray);
  1079. begin
  1080. ATermSrvCounterArray[1].dwIndex := TOTAL_SESSIONS_CREATED_COUNTER;
  1081. ATermSrvCounterArray[2].dwIndex := TOTAL_SESSIONS_DISCONNECTED_COUNTER;
  1082. ATermSrvCounterArray[3].dwIndex := TOTAL_SESSIONS_RECONNECTED_COUNTER;
  1083. ATermSrvCounterArray[4].dwIndex := TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER;
  1084. ATermSrvCounterArray[5].dwIndex := TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER;
  1085. ATermSrvCounterArray[6].dwIndex := TOTAL_SESSIONS_TOTAL_CONNECTED_NOW_COUNTER_2;
  1086. ATermSrvCounterArray[7].dwIndex := TOTAL_SESSIONS_TOTAL_DISCONNECTED_NOW_COUNTER_2;
  1087. end;
  1088. // This is the way WTSApi32.dll checks if Terminal Service is running
  1089. function IsTerminalServiceRunning: boolean;
  1090. var hSCM: HANDLE;
  1091. hService: HANDLE;
  1092. ServiceStatus: SERVICE_STATUS;
  1093. begin
  1094. Result := False;
  1095. // Open handle to Service Control Manager
  1096. hSCM := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, GENERIC_READ);
  1097. if hSCM > 0 then
  1098. begin
  1099. // Open handle to Terminal Server Service
  1100. hService := OpenService(hSCM, 'TermService', GENERIC_READ);
  1101. if hService > 0 then
  1102. begin
  1103. // Check if the service is running
  1104. QueryServiceStatus(hService, ServiceStatus);
  1105. Result := ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  1106. // Close the handle
  1107. CloseServiceHandle(hService);
  1108. end;
  1109. // Close the handle
  1110. CloseServiceHandle(hSCM);
  1111. end;
  1112. end;
  1113. function QueryCurrentWinStationSafe(pWinStationName: LPWSTR;
  1114. pUserName: PWideChar; cchDest: DWORD; var SessionId: DWORD;
  1115. var WdFlag: DWORD): Boolean;
  1116. begin
  1117. // Zero Memory
  1118. ZeroMemory(pWinStationName, 66);
  1119. ZeroMemory(pUserName, cchDest * SizeOf(WCHAR));
  1120. // Are we running Vista?
  1121. if IsVista then
  1122. begin
  1123. Result := QueryCurrentWinStationEx(pWinStationName, pUserName, cchDest,
  1124. SessionId, WdFlag);
  1125. end
  1126. else begin
  1127. Result := QueryCurrentWinStation(pWinStationName, pUserName, SessionId,
  1128. WdFlag);
  1129. end;
  1130. end;
  1131. function WinStationGetRemoteIPAddress(hServer: HANDLE; SessionId: DWORD;
  1132. var RemoteIPAddress: string; var Port: WORD): Boolean;
  1133. var WinStationRemoteIPAddress: TWinStationRemoteAddress;
  1134. pReturnLength: DWORD;
  1135. begin
  1136. // Zero Memory
  1137. ZeroMemory(@WinStationRemoteIPAddress, SizeOf(WinStationRemoteIPAddress));
  1138. // Query Remote Address
  1139. Result := WinStationQueryInformationW(hServer, SessionId,
  1140. WinStationRemoteAddress, @WinStationRemoteIPAddress,
  1141. SizeOf(WinStationRemoteIPAddress), pReturnLength);
  1142. if Result then
  1143. begin
  1144. // If the AddressFamily is IPv4
  1145. if WinStationRemoteIPAddress.AddressFamily = AF_INET then
  1146. begin
  1147. // The ntohs function converts a u_short from TCP/IP network byte order
  1148. // to host byte order (which is little-endian on Intel processors).
  1149. Port := ntohs(WinStationRemoteIPAddress.Port);
  1150. with WinStationRemoteIPAddress do
  1151. begin
  1152. // format the IP Address as string
  1153. RemoteIPAddress := Format('%d.%d.%d.%d', [Address[2], Address[3],
  1154. Address[4], Address[5]]);
  1155. // If you want to convert the to a sockaddr structure you could
  1156. // user WSAStringToAddress
  1157. end;
  1158. end
  1159. else begin
  1160. Result := False;
  1161. Port := 0;
  1162. RemoteIPAddress := '';
  1163. // SetLastError to give the user a clue as to why we failed..
  1164. // An address incompatible with the requested protocol was used.
  1165. // (An address incompatible with the requested protocol was used.)
  1166. SetLastError(WSAEAFNOSUPPORT);
  1167. end;
  1168. end;
  1169. end;
  1170. function WinStationQueryUserToken(hServer: HANDLE; SessionId: DWORD;
  1171. var hToken: HANDLE): BOOL;
  1172. var WinstaUserToken: _WINSTA_USER_TOKEN;
  1173. dwReturnLength: DWORD;
  1174. LUID: _LUID;
  1175. bWasPrivEnabled: Boolean;
  1176. Res: NTSTATUS;
  1177. begin
  1178. // Enable SeTcbPrivilege (system account has this enabled by default)
  1179. LookupPrivilegeValue(nil, SE_TCB_NAME, LUID);
  1180. Res := RtlAdjustPrivilege(LUID.LowPart, True, False, @bWasPrivEnabled);
  1181. // Initialize structure
  1182. WinstaUserToken.ProcessId := GetCurrentProcessId; // Current Process Id
  1183. WinstaUserToken.ThreadId := GetCurrentThreadId; // Current Thread Id
  1184. WinstaUserToken.TokenHandle := 0;
  1185. if Res = STATUS_SUCCESS then
  1186. begin
  1187. // Query for the token, we are only allowed to do this if we are the
  1188. // System account (else ACCESS_DENIED is returned)
  1189. Result := WinStationQueryInformationW(hServer, SessionId, WinStationToken,
  1190. @WinstaUserToken, SizeOf(WinstaUserToken), dwReturnLength);
  1191. hToken := WinStaUserToken.TokenHandle;
  1192. // Restore state of SeTcbPrivilege
  1193. RtlAdjustPrivilege(LUID.LowPart, bWasPrivEnabled, False, @bWasPrivEnabled);
  1194. end
  1195. else begin
  1196. Result := False;
  1197. // Convert NTStatus to WinError and SetLastError
  1198. SetLastError(RtlNtStatusToDosError(Res));
  1199. end;
  1200. end;
  1201. {$ENDIF JWA_INTERFACESECTION}
  1202. {$IFNDEF JWA_OMIT_SECTIONS}
  1203. end.
  1204. {$ENDIF JWA_OMIT_SECTIONS}