Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1456 lines
40 KiB

  1. /*******************************************************************************
  2. * session.c
  3. *
  4. * Published Terminal Server APIs
  5. *
  6. * - session routines
  7. *
  8. * Copyright 1998, Citrix Systems Inc.
  9. * Copyright (C) 1997-1999 Microsoft Corp.
  10. /******************************************************************************/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <ntddkbd.h>
  15. #include <ntddmou.h>
  16. #include <windows.h>
  17. #include <winbase.h>
  18. #include <winerror.h>
  19. #if(WINVER >= 0x0500)
  20. #include <ntstatus.h>
  21. #include <winsta.h>
  22. #else
  23. #include <citrix\cxstatus.h>
  24. #include <citrix\winsta.h>
  25. #endif
  26. #include <utildll.h>
  27. #include <winsock.h> // for AF_INET, etc.
  28. #include <stdio.h>
  29. #include <stdarg.h>
  30. #include <wtsapi32.h>
  31. /*=============================================================================
  32. == External procedures defined
  33. =============================================================================*/
  34. BOOL WINAPI WTSEnumerateSessionsW( HANDLE, DWORD, DWORD, PWTS_SESSION_INFOW *,
  35. DWORD * );
  36. BOOL WINAPI WTSEnumerateSessionsA( HANDLE, DWORD, DWORD, PWTS_SESSION_INFOA *,
  37. DWORD * );
  38. BOOL WINAPI WTSQuerySessionInformationW( HANDLE, DWORD, WTS_INFO_CLASS,
  39. LPWSTR *, DWORD * );
  40. BOOL WINAPI WTSQuerySessionInformationA( HANDLE, DWORD, WTS_INFO_CLASS,
  41. LPSTR *, DWORD * );
  42. BOOL WINAPI WTSSendMessageW( HANDLE, DWORD, LPWSTR, DWORD, LPWSTR, DWORD,
  43. DWORD, DWORD, DWORD *, BOOL );
  44. BOOL WINAPI WTSSendMessageA( HANDLE, DWORD, LPSTR, DWORD, LPSTR, DWORD,
  45. DWORD, DWORD, DWORD *, BOOL );
  46. BOOL WINAPI WTSDisconnectSession( HANDLE, DWORD, BOOL );
  47. BOOL WINAPI WTSLogoffSession( HANDLE, DWORD, BOOL );
  48. /*=============================================================================
  49. == Internal procedures defined
  50. =============================================================================*/
  51. BOOL _CopyData( PVOID, ULONG, LPWSTR *, DWORD * );
  52. BOOL _CopyStringW( LPWSTR, LPWSTR *, DWORD * );
  53. BOOL _CopyStringA( LPSTR, LPWSTR *, DWORD * );
  54. BOOL _CopyStringWtoA( LPWSTR, LPSTR *, DWORD * );
  55. BOOL ValidateCopyAnsiToUnicode(LPSTR, DWORD, LPWSTR);
  56. BOOL ValidateCopyUnicodeToUnicode(LPWSTR, DWORD, LPWSTR);
  57. /*=============================================================================
  58. == Procedures used
  59. =============================================================================*/
  60. VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * );
  61. VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
  62. /*=============================================================================
  63. == Local Data
  64. =============================================================================*/
  65. /*
  66. * Table to map WINSTATIONSTATECLASS to WTS_CONNECTSTATE_CLASS
  67. */
  68. WTS_CONNECTSTATE_CLASS WTSStateMapping[] =
  69. {
  70. WTSActive,
  71. WTSConnected,
  72. WTSConnectQuery,
  73. WTSShadow,
  74. WTSDisconnected,
  75. WTSIdle,
  76. WTSListen,
  77. WTSReset,
  78. WTSDown,
  79. WTSInit,
  80. };
  81. /****************************************************************************
  82. *
  83. * WTSEnumerateSessionsW (UNICODE)
  84. *
  85. * Returns a list of Terminal Server Sessions on the specified server
  86. *
  87. * ENTRY:
  88. * hServer (input)
  89. * Terminal Server handle (or WTS_CURRENT_SERVER)
  90. * Reserved (input)
  91. * Must be zero
  92. * Version (input)
  93. * Version of the enumeration request (must be 1)
  94. * ppSessionInfo (output)
  95. * Points to the address of a variable to receive the enumeration results,
  96. * which are returned as an array of WTS_SESSION_INFO structures. The
  97. * buffer is allocated within this API and is disposed of using
  98. * WTSFreeMemory.
  99. * pCount (output)
  100. * Points to the address of a variable to receive the number of
  101. * WTS_SESSION_INFO structures returned
  102. *
  103. * EXIT:
  104. *
  105. * TRUE -- The enumerate operation succeeded.
  106. *
  107. * FALSE -- The operation failed. Extended error status is available
  108. * using GetLastError.
  109. *
  110. ****************************************************************************/
  111. BOOL
  112. WINAPI
  113. WTSEnumerateSessionsW(
  114. IN HANDLE hServer,
  115. IN DWORD Reserved,
  116. IN DWORD Version,
  117. OUT PWTS_SESSION_INFOW * ppSessionInfo,
  118. OUT DWORD * pCount
  119. )
  120. {
  121. PWTS_SESSION_INFOW pSessionW;
  122. PLOGONIDW pLogonIds;
  123. PLOGONIDW pLogonId;
  124. ULONG SessionCount;
  125. ULONG NameLength;
  126. PBYTE pNameData;
  127. ULONG Length;
  128. ULONG i;
  129. /*
  130. * Validate parameters
  131. */
  132. if ( Reserved != 0 || Version != 1 ) {
  133. SetLastError( ERROR_INVALID_PARAMETER );
  134. goto badparam;
  135. }
  136. if (!ppSessionInfo || !pCount) {
  137. SetLastError(ERROR_INVALID_USER_BUFFER);
  138. goto badparam;
  139. }
  140. /*
  141. * Enumerate Sessions and check for an error
  142. */
  143. if ( !WinStationEnumerateW( hServer,
  144. &pLogonIds,
  145. &SessionCount ) ) {
  146. goto badenum;
  147. }
  148. /*
  149. * Total up the size of the session data
  150. */
  151. NameLength = 0;
  152. for ( i=0; i < SessionCount; i++ ) {
  153. NameLength += ((wcslen(pLogonIds[i].WinStationName) + 1) * sizeof(WCHAR)); // number of bytes
  154. }
  155. /*
  156. * Allocate user buffer
  157. */
  158. pSessionW = LocalAlloc( LPTR, (SessionCount * sizeof(WTS_SESSION_INFOW)) + NameLength );
  159. if ( pSessionW == NULL )
  160. goto badalloc;
  161. /*
  162. * Update user parameters
  163. */
  164. *ppSessionInfo = pSessionW;
  165. *pCount = SessionCount;
  166. /*
  167. * Copy data to new buffer
  168. */
  169. pNameData = (PBYTE)pSessionW + (SessionCount * sizeof(WTS_SESSION_INFOW));
  170. for ( i=0; i < SessionCount; i++ ) {
  171. pLogonId = &pLogonIds[i];
  172. Length = (wcslen(pLogonId->WinStationName) + 1) * sizeof(WCHAR); // number of bytes
  173. memcpy( pNameData, pLogonId->WinStationName, Length );
  174. pSessionW->pWinStationName = (LPWSTR) pNameData;
  175. pSessionW->SessionId = pLogonId->LogonId;
  176. pSessionW->State = WTSStateMapping[ pLogonId->State ];
  177. pSessionW++;
  178. pNameData += Length;
  179. }
  180. /*
  181. * Free original Session list buffer
  182. */
  183. WinStationFreeMemory( pLogonIds );
  184. return( TRUE );
  185. /*=============================================================================
  186. == Error return
  187. =============================================================================*/
  188. badalloc:
  189. WinStationFreeMemory( pLogonIds );
  190. badenum:
  191. badparam:
  192. if (ppSessionInfo) *ppSessionInfo = NULL;
  193. if (pCount) *pCount = 0;
  194. return( FALSE );
  195. }
  196. /****************************************************************************
  197. *
  198. * WTSEnumerateSessionsA (ANSI stub)
  199. *
  200. * Returns a list of Terminal Server Sessions on the specified server
  201. *
  202. * ENTRY:
  203. *
  204. * see WTSEnumerateSessionsW
  205. *
  206. * EXIT:
  207. *
  208. * TRUE -- The enumerate operation succeeded.
  209. *
  210. * FALSE -- The operation failed. Extended error status is available
  211. * using GetLastError.
  212. *
  213. ****************************************************************************/
  214. BOOL
  215. WINAPI
  216. WTSEnumerateSessionsA(
  217. IN HANDLE hServer,
  218. IN DWORD Reserved,
  219. IN DWORD Version,
  220. OUT PWTS_SESSION_INFOA * ppSessionInfo,
  221. OUT DWORD * pCount
  222. )
  223. {
  224. PWTS_SESSION_INFOA pSessionA;
  225. PLOGONIDA pLogonIds;
  226. PLOGONIDA pLogonId;
  227. ULONG SessionCount;
  228. ULONG NameLength;
  229. PBYTE pNameData;
  230. ULONG Length;
  231. ULONG i;
  232. /*
  233. * Validate parameters
  234. */
  235. if ( Reserved != 0 || Version != 1 ) {
  236. SetLastError( ERROR_INVALID_PARAMETER );
  237. goto badparam;
  238. }
  239. if (!ppSessionInfo || !pCount) {
  240. SetLastError(ERROR_INVALID_USER_BUFFER);
  241. goto badparam;
  242. }
  243. /*
  244. * Enumerate Sessions and check for an error
  245. */
  246. if ( !WinStationEnumerateA( hServer,
  247. &pLogonIds,
  248. &SessionCount ) ) {
  249. goto badenum;
  250. }
  251. /*
  252. * Total up the size of the session data
  253. */
  254. NameLength = 0;
  255. for ( i=0; i < SessionCount; i++ ) {
  256. NameLength += (strlen(pLogonIds[i].WinStationName) + 1); // number of bytes
  257. }
  258. /*
  259. * Allocate user buffer
  260. */
  261. pSessionA = LocalAlloc( LPTR, (SessionCount * sizeof(WTS_SESSION_INFOA)) + NameLength );
  262. if ( pSessionA == NULL )
  263. goto badalloc;
  264. /*
  265. * Update user parameters
  266. */
  267. *ppSessionInfo = pSessionA;
  268. *pCount = SessionCount;
  269. /*
  270. * Copy data to new buffer
  271. */
  272. pNameData = (PBYTE)pSessionA + (SessionCount * sizeof(WTS_SESSION_INFOA));
  273. for ( i=0; i < SessionCount; i++ ) {
  274. pLogonId = &pLogonIds[i];
  275. Length = strlen(pLogonId->WinStationName) + 1; // number of bytes
  276. memcpy( pNameData, pLogonId->WinStationName, Length );
  277. pSessionA->pWinStationName = (LPSTR) pNameData;
  278. pSessionA->SessionId = pLogonId->LogonId;
  279. pSessionA->State = WTSStateMapping[ pLogonId->State ];
  280. pSessionA++;
  281. pNameData += Length;
  282. }
  283. /*
  284. * Free original Session list buffer
  285. */
  286. WinStationFreeMemory( pLogonIds );
  287. return( TRUE );
  288. /*=============================================================================
  289. == Error return
  290. =============================================================================*/
  291. badalloc:
  292. WinStationFreeMemory( pLogonIds );
  293. badenum:
  294. badparam:
  295. if (ppSessionInfo) *ppSessionInfo = NULL;
  296. if (pCount) *pCount = 0;
  297. return( FALSE );
  298. }
  299. /****************************************************************************
  300. *
  301. * WTSQuerySessionInformationW (UNICODE)
  302. *
  303. * Query information for the specified session and server
  304. *
  305. * ENTRY:
  306. * hServer (input)
  307. * Terminal Server handle (or WTS_CURRENT_SERVER)
  308. * SessionId (input)
  309. * Server Session Id (or WTS_CURRENT_SESSION)
  310. * WTSInfoClass (input)
  311. * Specifies the type of information to retrieve from the specified
  312. * session
  313. * ppBuffer (output)
  314. * Points to the address of a variable to receive information about
  315. * the specified session. The format and contents of the data
  316. * depend on the specified information class being queried. The
  317. * buffer is allocated within this API and is disposed of using
  318. * WTSFreeMemory.
  319. * pBytesReturned (output)
  320. * An optional parameter that if specified, receives the number of
  321. * bytes returned.
  322. *
  323. * EXIT:
  324. *
  325. * TRUE -- The query operation succeeded.
  326. *
  327. * FALSE -- The operation failed. Extended error status is available
  328. * using GetLastError.
  329. *
  330. ****************************************************************************/
  331. BOOL
  332. WINAPI
  333. WTSQuerySessionInformationW(
  334. IN HANDLE hServer,
  335. IN DWORD SessionId,
  336. IN WTS_INFO_CLASS WTSInfoClass,
  337. OUT LPWSTR * ppBuffer,
  338. OUT DWORD * pBytesReturned
  339. )
  340. {
  341. PWINSTATIONCONFIGW pWSConfig = NULL;
  342. PWINSTATIONINFORMATIONW pWSInfo = NULL;
  343. PWINSTATIONCLIENT pWSClient = NULL;
  344. WTS_CLIENT_DISPLAY ClientDisplay;
  345. WTS_CLIENT_ADDRESS ClientAddress;
  346. ULONG WSModulesLength;
  347. ULONG BytesReturned;
  348. ULONG i;
  349. BYTE Version;
  350. BOOL fSuccess = FALSE;
  351. if (!ppBuffer || !pBytesReturned) {
  352. SetLastError(ERROR_INVALID_USER_BUFFER);
  353. return FALSE;
  354. }
  355. /*
  356. * Query WinStation Data
  357. */
  358. switch ( WTSInfoClass ) {
  359. case WTSInitialProgram :
  360. case WTSApplicationName :
  361. case WTSWorkingDirectory :
  362. case WTSOEMId :
  363. pWSConfig = LocalAlloc( LPTR, sizeof(WINSTATIONCONFIGW) );
  364. if ( pWSConfig == NULL )
  365. goto no_memory;
  366. if ( !WinStationQueryInformationW( hServer,
  367. SessionId,
  368. WinStationConfiguration,
  369. pWSConfig,
  370. sizeof(WINSTATIONCONFIGW),
  371. &BytesReturned ) ) {
  372. goto badquery;
  373. }
  374. break;
  375. }
  376. switch ( WTSInfoClass ) {
  377. case WTSSessionId :
  378. pWSInfo = LocalAlloc( LPTR, sizeof(WINSTATIONINFORMATIONW) );
  379. if ( pWSInfo == NULL )
  380. goto no_memory;
  381. //
  382. // no need to make a rpc call here
  383. //
  384. if (WTS_CURRENT_SESSION == SessionId)
  385. {
  386. pWSInfo->LogonId = NtCurrentPeb()->SessionId;
  387. }
  388. else
  389. {
  390. //
  391. // why would anybody want to know non current sessionid ?
  392. //
  393. pWSInfo->LogonId = SessionId;
  394. }
  395. BytesReturned = sizeof(pWSInfo->LogonId);
  396. break;
  397. case WTSUserName :
  398. case WTSWinStationName :
  399. case WTSDomainName :
  400. case WTSConnectState :
  401. pWSInfo = LocalAlloc( LPTR, sizeof(WINSTATIONINFORMATIONW) );
  402. if ( pWSInfo == NULL )
  403. goto no_memory;
  404. if ( !WinStationQueryInformationW( hServer,
  405. SessionId,
  406. WinStationInformation,
  407. pWSInfo,
  408. sizeof(WINSTATIONINFORMATIONW),
  409. &BytesReturned ) ) {
  410. goto badquery;
  411. }
  412. break;
  413. }
  414. switch ( WTSInfoClass ) {
  415. case WTSClientBuildNumber :
  416. case WTSClientName :
  417. case WTSClientDirectory :
  418. case WTSClientProductId :
  419. case WTSClientHardwareId :
  420. case WTSClientAddress :
  421. case WTSClientDisplay :
  422. case WTSClientProtocolType :
  423. pWSClient = LocalAlloc( LPTR, sizeof(WINSTATIONCLIENT) );
  424. if ( pWSClient == NULL )
  425. goto no_memory;
  426. if ( !WinStationQueryInformationW( hServer,
  427. SessionId,
  428. WinStationClient,
  429. pWSClient,
  430. sizeof(WINSTATIONCLIENT),
  431. &BytesReturned ) ) {
  432. goto badquery;
  433. }
  434. break;
  435. }
  436. /*
  437. * Copy the data to the users buffer
  438. */
  439. switch ( WTSInfoClass ) {
  440. case WTSInitialProgram :
  441. if ( SessionId == 0 )
  442. return( FALSE );
  443. fSuccess = _CopyStringW( pWSConfig->User.InitialProgram,
  444. ppBuffer,
  445. pBytesReturned );
  446. break;
  447. case WTSApplicationName :
  448. if ( SessionId == 0 )
  449. return( FALSE );
  450. fSuccess = _CopyStringW( pWSConfig->User.PublishedName,
  451. ppBuffer,
  452. pBytesReturned );
  453. break;
  454. case WTSWorkingDirectory :
  455. fSuccess = _CopyStringW( pWSConfig->User.WorkDirectory,
  456. ppBuffer,
  457. pBytesReturned );
  458. break;
  459. case WTSOEMId :
  460. fSuccess = _CopyStringA( pWSConfig->OEMId,
  461. ppBuffer,
  462. pBytesReturned );
  463. break;
  464. case WTSSessionId :
  465. fSuccess = _CopyData( &(pWSInfo->LogonId),
  466. sizeof(pWSInfo->LogonId),
  467. ppBuffer,
  468. pBytesReturned );
  469. break;
  470. case WTSConnectState :
  471. fSuccess = _CopyData( &(pWSInfo->ConnectState),
  472. sizeof(pWSInfo->ConnectState),
  473. ppBuffer,
  474. pBytesReturned );
  475. break;
  476. case WTSWinStationName :
  477. fSuccess = _CopyStringW( pWSInfo->WinStationName,
  478. ppBuffer,
  479. pBytesReturned );
  480. break;
  481. case WTSUserName :
  482. fSuccess = _CopyStringW( pWSInfo->UserName,
  483. ppBuffer,
  484. pBytesReturned );
  485. break;
  486. case WTSDomainName :
  487. fSuccess = _CopyStringW( pWSInfo->Domain,
  488. ppBuffer,
  489. pBytesReturned );
  490. break;
  491. case WTSClientBuildNumber :
  492. fSuccess = _CopyData( &(pWSClient->ClientBuildNumber),
  493. sizeof(pWSClient->ClientBuildNumber),
  494. ppBuffer,
  495. pBytesReturned );
  496. break;
  497. case WTSClientName :
  498. fSuccess = _CopyStringW( pWSClient->ClientName,
  499. ppBuffer,
  500. pBytesReturned );
  501. break;
  502. case WTSClientDirectory :
  503. fSuccess = _CopyStringW( pWSClient->ClientDirectory,
  504. ppBuffer,
  505. pBytesReturned );
  506. break;
  507. case WTSClientProductId :
  508. fSuccess = _CopyData( &(pWSClient->ClientProductId),
  509. sizeof(pWSClient->ClientProductId),
  510. ppBuffer,
  511. pBytesReturned );
  512. break;
  513. case WTSClientHardwareId :
  514. fSuccess = _CopyData( &(pWSClient->ClientHardwareId),
  515. sizeof(pWSClient->ClientHardwareId),
  516. ppBuffer,
  517. pBytesReturned );
  518. break;
  519. case WTSClientAddress :
  520. ClientAddress.AddressFamily = pWSClient->ClientAddressFamily;
  521. switch ( ClientAddress.AddressFamily ) {
  522. case AF_UNSPEC :
  523. // force null-termination
  524. if ( pWSClient->ClientAddress[CLIENTADDRESS_LENGTH+1] != L'\0' )
  525. pWSClient->ClientAddress[CLIENTADDRESS_LENGTH+1] = L'\0';
  526. // We do this here instead of in the ANSI version of this
  527. // function because we've only got 20 bytes to work with
  528. // (unicode addresses over 10 chars would be truncated).
  529. // The return is the same for both A and W versions.
  530. WideCharToMultiByte( CP_ACP, 0L, pWSClient->ClientAddress,
  531. -1, ClientAddress.Address, 20, NULL, NULL );
  532. break;
  533. case AF_INET :
  534. // convert string to binary format
  535. swscanf( pWSClient->ClientAddress, L"%u.%u.%u.%u",
  536. &ClientAddress.Address[2],
  537. &ClientAddress.Address[3],
  538. &ClientAddress.Address[4],
  539. &ClientAddress.Address[5] );
  540. break;
  541. case AF_IPX :
  542. {
  543. PWCHAR pBuf = pWSClient->ClientAddress;
  544. _wcsupr( pWSClient->ClientAddress );
  545. // convert string to binary format
  546. for ( i=0 ; i<10 ; i++ ) {
  547. if ( *pBuf != L':' ) {
  548. swscanf( pBuf, L"%2X", &ClientAddress.Address[i] );
  549. pBuf += 2;
  550. } else {
  551. // skip the colon
  552. pBuf++;
  553. i--;
  554. continue;
  555. }
  556. }
  557. }
  558. break;
  559. }
  560. fSuccess = _CopyData( &ClientAddress,
  561. sizeof(ClientAddress),
  562. ppBuffer,
  563. pBytesReturned );
  564. break;
  565. case WTSClientDisplay :
  566. ClientDisplay.HorizontalResolution = pWSClient->HRes;
  567. ClientDisplay.VerticalResolution = pWSClient->VRes;
  568. ClientDisplay.ColorDepth = pWSClient->ColorDepth;
  569. fSuccess = _CopyData( &ClientDisplay,
  570. sizeof(ClientDisplay),
  571. ppBuffer,
  572. pBytesReturned );
  573. break;
  574. case WTSClientProtocolType :
  575. fSuccess = _CopyData( &(pWSClient->ProtocolType),
  576. sizeof(pWSClient->ProtocolType),
  577. ppBuffer,
  578. pBytesReturned );
  579. break;
  580. }
  581. badquery:
  582. if ( pWSConfig )
  583. LocalFree( pWSConfig );
  584. if ( pWSInfo )
  585. LocalFree( pWSInfo );
  586. if ( pWSClient )
  587. LocalFree( pWSClient );
  588. return( fSuccess );
  589. /*=============================================================================
  590. == Error return
  591. =============================================================================*/
  592. no_memory:
  593. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  594. return( FALSE );
  595. }
  596. /****************************************************************************
  597. *
  598. * WTSQuerySessionInformationA (ANSI)
  599. *
  600. * Query information for the specified session and server
  601. *
  602. * ENTRY:
  603. *
  604. * see WTSQuerySessionInformationW
  605. *
  606. * EXIT:
  607. *
  608. * TRUE -- The query operation succeeded.
  609. *
  610. * FALSE -- The operation failed. Extended error status is available
  611. * using GetLastError.
  612. *
  613. ****************************************************************************/
  614. BOOL
  615. WINAPI
  616. WTSQuerySessionInformationA(
  617. IN HANDLE hServer,
  618. IN DWORD SessionId,
  619. IN WTS_INFO_CLASS WTSInfoClass,
  620. OUT LPSTR * ppBuffer,
  621. OUT DWORD * pBytesReturned
  622. )
  623. {
  624. LPWSTR pBufferW;
  625. DWORD BytesReturned;
  626. DWORD DataLength;
  627. if (!ppBuffer || !pBytesReturned) {
  628. SetLastError(ERROR_INVALID_USER_BUFFER);
  629. return FALSE;
  630. }
  631. /*
  632. * Query the data
  633. */
  634. if ( !WTSQuerySessionInformationW( hServer,
  635. SessionId,
  636. WTSInfoClass,
  637. &pBufferW,
  638. &BytesReturned ) ) {
  639. return( FALSE );
  640. }
  641. switch ( WTSInfoClass ) {
  642. case WTSSessionId :
  643. case WTSConnectState :
  644. case WTSClientBuildNumber :
  645. case WTSClientProductId :
  646. case WTSClientHardwareId :
  647. case WTSClientAddress :
  648. case WTSClientDisplay :
  649. case WTSClientProtocolType:
  650. /*
  651. * Non-String Data - just return
  652. */
  653. *ppBuffer = (LPSTR) pBufferW;
  654. if ( pBytesReturned ) {
  655. *pBytesReturned = BytesReturned;
  656. }
  657. break;
  658. case WTSInitialProgram :
  659. case WTSWorkingDirectory :
  660. case WTSOEMId :
  661. case WTSWinStationName :
  662. case WTSUserName :
  663. case WTSDomainName :
  664. case WTSClientName :
  665. case WTSClientDirectory :
  666. case WTSApplicationName :
  667. /*
  668. * String Data - Convert to ANSI
  669. * lets allocate the maximum possible MultiByte length.
  670. */
  671. DataLength = (wcslen(pBufferW) + 1) * sizeof(WCHAR);
  672. *ppBuffer = LocalAlloc( LPTR, DataLength );
  673. if ( *ppBuffer == NULL ) {
  674. LocalFree( pBufferW );
  675. return( FALSE );
  676. }
  677. RtlUnicodeToMultiByteN( *ppBuffer, DataLength, pBytesReturned, pBufferW, DataLength);
  678. LocalFree( pBufferW );
  679. break;
  680. }
  681. return( TRUE );
  682. }
  683. /****************************************************************************
  684. *
  685. * WTSSetSessionInformationW (UNICODE)
  686. *
  687. * NOTE: THIS IS CURRENTLY JUST A STUB SO WE DON'T BREAK EXISTING PROGRAMS.
  688. *
  689. * Modify information for the specified session and server
  690. *
  691. * ENTRY:
  692. * hServer (input)
  693. * Terminal Server handle (or WTS_CURRENT_SERVER)
  694. * SessionId (input)
  695. * Server Session Id (or WTS_CURRENT_SESSION)
  696. * WTSInfoClass (input)
  697. * Specifies the type of information to modify for the specified
  698. * session
  699. * pData (input)
  700. * Pointer to the data used to modify the specified session information.
  701. * DataLength (output)
  702. * The length of the data provided.
  703. *
  704. * EXIT:
  705. *
  706. * TRUE -- The modify operation succeeded.
  707. *
  708. * FALSE -- The operation failed. Extended error status is available
  709. * using GetLastError.
  710. *
  711. ****************************************************************************/
  712. BOOL
  713. WINAPI
  714. WTSSetSessionInformationW(
  715. IN HANDLE hServer,
  716. IN DWORD SessionId,
  717. IN WTS_INFO_CLASS WTSInfoClass,
  718. IN PVOID pData,
  719. IN DWORD DataLength
  720. )
  721. {
  722. return( TRUE );
  723. }
  724. /****************************************************************************
  725. *
  726. * WTSSetSessionInformationA (ANSI)
  727. *
  728. * NOTE: THIS IS CURRENTLY JUST A STUB SO WE DON'T BREAK EXISTING PROGRAMS.
  729. *
  730. * Modify information for the specified session and server
  731. *
  732. * ENTRY:
  733. *
  734. * see WTSSetSessionInformationW
  735. *
  736. * EXIT:
  737. *
  738. * TRUE -- The query operation succeeded.
  739. *
  740. * FALSE -- The operation failed. Extended error status is available
  741. * using GetLastError.
  742. *
  743. ****************************************************************************/
  744. BOOL
  745. WINAPI
  746. WTSSetSessionInformationA(
  747. IN HANDLE hServer,
  748. IN DWORD SessionId,
  749. IN WTS_INFO_CLASS WTSInfoClass,
  750. IN PVOID pData,
  751. IN DWORD DataLength
  752. )
  753. {
  754. return( TRUE );
  755. }
  756. /****************************************************************************
  757. *
  758. * WTSSendMessageW (UNICODE)
  759. *
  760. * Send a message box to the specified session
  761. *
  762. * ENTRY:
  763. * hServer (input)
  764. * Terminal Server handle (or WTS_CURRENT_SERVER)
  765. * SessionId (input)
  766. * Server Session Id (or WTS_CURRENT_SESSION)
  767. * pTitle (input)
  768. * Pointer to title for message box to display.
  769. * TitleLength (input)
  770. * Length of title to display in bytes.
  771. * pMessage (input)
  772. * Pointer to message to display.
  773. * MessageLength (input)
  774. * Length of message in bytes to display at the specified window station.
  775. * Style (input)
  776. * Standard Windows MessageBox() style parameter.
  777. * Timeout (input)
  778. * Response timeout in seconds. If message is not responded to in
  779. * Timeout seconds then a response code of IDTIMEOUT (cwin.h) is
  780. * returned to signify the message timed out.
  781. * pResponse (output)
  782. * Address to return selected response. Valid only when bWait is set.
  783. * bWait (input)
  784. * Wait for the response
  785. *
  786. * EXIT:
  787. *
  788. * TRUE -- The operation succeeded.
  789. *
  790. * FALSE -- The operation failed. Extended error status is available
  791. * using GetLastError.
  792. *
  793. ****************************************************************************/
  794. BOOL
  795. WINAPI
  796. WTSSendMessageW(
  797. IN HANDLE hServer,
  798. IN DWORD SessionId,
  799. IN LPWSTR pTitle,
  800. IN DWORD TitleLength,
  801. IN LPWSTR pMessage,
  802. IN DWORD MessageLength,
  803. IN DWORD Style,
  804. IN DWORD Timeout,
  805. OUT DWORD * pResponse,
  806. IN BOOL bWait
  807. )
  808. {
  809. if (!pTitle ||
  810. !pMessage ||
  811. !pResponse
  812. ) {
  813. SetLastError(ERROR_INVALID_PARAMETER);
  814. return FALSE;
  815. }
  816. return( WinStationSendMessageW( hServer,
  817. SessionId,
  818. pTitle,
  819. TitleLength,
  820. pMessage,
  821. MessageLength,
  822. Style,
  823. Timeout,
  824. pResponse,
  825. (BOOLEAN) !bWait ) );
  826. }
  827. /****************************************************************************
  828. *
  829. * WTSSendMessageA (ANSI)
  830. *
  831. * Send a message box to the specified session
  832. *
  833. * ENTRY:
  834. *
  835. * see WTSSendMessageW
  836. *
  837. * EXIT:
  838. *
  839. * TRUE -- The operation succeeded.
  840. *
  841. * FALSE -- The operation failed. Extended error status is available
  842. * using GetLastError.
  843. *
  844. ****************************************************************************/
  845. BOOL
  846. WINAPI
  847. WTSSendMessageA(
  848. IN HANDLE hServer,
  849. IN DWORD SessionId,
  850. IN LPSTR pTitle,
  851. IN DWORD TitleLength,
  852. IN LPSTR pMessage,
  853. IN DWORD MessageLength,
  854. IN DWORD Style,
  855. IN DWORD Timeout,
  856. OUT DWORD * pResponse,
  857. IN BOOL bWait
  858. )
  859. {
  860. if (!pTitle ||
  861. !pMessage ||
  862. !pResponse
  863. ) {
  864. SetLastError(ERROR_INVALID_PARAMETER);
  865. return FALSE;
  866. }
  867. return( WinStationSendMessageA( hServer,
  868. SessionId,
  869. pTitle,
  870. TitleLength,
  871. pMessage,
  872. MessageLength,
  873. Style,
  874. Timeout,
  875. pResponse,
  876. (BOOLEAN) !bWait ) );
  877. }
  878. /****************************************************************************
  879. *
  880. * WTSDisconnectSession
  881. *
  882. * Disconnect the specified session
  883. *
  884. * ENTRY:
  885. * hServer (input)
  886. * Terminal Server handle (or WTS_CURRENT_SERVER)
  887. * SessionId (input)
  888. * Server Session Id (or WTS_CURRENT_SESSION)
  889. * bWait (input)
  890. * Wait for the operation to complete
  891. *
  892. * EXIT:
  893. *
  894. * TRUE -- The operation succeeded.
  895. *
  896. * FALSE -- The operation failed. Extended error status is available
  897. * using GetLastError.
  898. *
  899. ****************************************************************************/
  900. BOOL
  901. WINAPI
  902. WTSDisconnectSession(
  903. IN HANDLE hServer,
  904. IN DWORD SessionId,
  905. IN BOOL bWait
  906. )
  907. {
  908. return( WinStationDisconnect( hServer, SessionId, (BOOLEAN) bWait ) );
  909. }
  910. /****************************************************************************
  911. *
  912. * WTSLogoffSession
  913. *
  914. * Logoff the specified session
  915. *
  916. * ENTRY:
  917. * hServer (input)
  918. * Terminal Server handle (or WTS_CURRENT_SERVER)
  919. * SessionId (input)
  920. * Server Session Id (or WTS_CURRENT_SESSION)
  921. * bWait (input)
  922. * Wait for the operation to complete
  923. *
  924. * EXIT:
  925. *
  926. * TRUE -- The operation succeeded.
  927. *
  928. * FALSE -- The operation failed. Extended error status is available
  929. * using GetLastError.
  930. *
  931. ****************************************************************************/
  932. BOOL
  933. WINAPI
  934. WTSLogoffSession(
  935. IN HANDLE hServer,
  936. IN DWORD SessionId,
  937. IN BOOL bWait
  938. )
  939. {
  940. return( WinStationReset( hServer, SessionId, (BOOLEAN) bWait ) );
  941. }
  942. /****************************************************************************
  943. *
  944. * _CopyData
  945. *
  946. * Allocate buffer and copy data into it
  947. *
  948. * ENTRY:
  949. * pData (input)
  950. * pointer to data to copy
  951. * DataLength (input)
  952. * length of data to copy
  953. * ppBuffer (output)
  954. * Points to the address of a variable to receive the copied data
  955. * pBytesReturned (output)
  956. * An optional parameter that if specified, receives the number of
  957. * bytes returned.
  958. *
  959. * EXIT:
  960. *
  961. * TRUE -- The copy operation succeeded.
  962. *
  963. * FALSE -- The operation failed. Extended error status is available
  964. * using GetLastError.
  965. *
  966. ****************************************************************************/
  967. BOOL
  968. _CopyData( PVOID pData,
  969. ULONG DataLength,
  970. LPWSTR * ppBuffer,
  971. DWORD * pBytesReturned )
  972. {
  973. *ppBuffer = LocalAlloc( LPTR, DataLength );
  974. if ( *ppBuffer == NULL ) {
  975. return( FALSE );
  976. }
  977. if ( pBytesReturned != NULL ) {
  978. *pBytesReturned = DataLength;
  979. }
  980. memcpy( *ppBuffer, pData, DataLength );
  981. return( TRUE );
  982. }
  983. /****************************************************************************
  984. *
  985. * _CopyStringW
  986. *
  987. * Allocate a buffer for a unicode string and copy unicode string into it
  988. *
  989. * ENTRY:
  990. * pString (input)
  991. * pointer to unicode string to copy
  992. * ppBuffer (output)
  993. * Points to the address of a variable to receive the copied data
  994. * pBytesReturned (output)
  995. * An optional parameter that if specified, receives the number of
  996. * bytes returned.
  997. *
  998. * EXIT:
  999. *
  1000. * TRUE -- The copy operation succeeded.
  1001. *
  1002. * FALSE -- The operation failed. Extended error status is available
  1003. * using GetLastError.
  1004. *
  1005. ****************************************************************************/
  1006. BOOL
  1007. _CopyStringW( LPWSTR pString,
  1008. LPWSTR * ppBuffer,
  1009. DWORD * pBytesReturned )
  1010. {
  1011. ULONG DataLength;
  1012. BOOL rc = TRUE;
  1013. /*
  1014. * If original string is NULL, just make copy NULL. KLB 11-03-97
  1015. */
  1016. if ( pString == NULL ) {
  1017. *ppBuffer = NULL;
  1018. if ( pBytesReturned != NULL ) {
  1019. *pBytesReturned = 0;
  1020. }
  1021. goto done;
  1022. }
  1023. DataLength = (wcslen( pString ) + 1) * sizeof(WCHAR);
  1024. *ppBuffer = LocalAlloc( LPTR, DataLength );
  1025. if ( *ppBuffer == NULL ) {
  1026. rc = FALSE;
  1027. goto done;
  1028. }
  1029. if ( pBytesReturned != NULL ) {
  1030. *pBytesReturned = DataLength;
  1031. }
  1032. memcpy( *ppBuffer, pString, DataLength );
  1033. done:
  1034. return( rc );
  1035. }
  1036. /****************************************************************************
  1037. *
  1038. * _CopyStringA
  1039. *
  1040. * Allocate a buffer for a unicode string and copy ansi string into it
  1041. *
  1042. * ENTRY:
  1043. * pString (input)
  1044. * pointer to ansi string to copy
  1045. * ppBuffer (output)
  1046. * Points to the address of a variable to receive the copied data
  1047. * pBytesReturned (output)
  1048. * An optional parameter that if specified, receives the number of
  1049. * bytes returned.
  1050. *
  1051. * EXIT:
  1052. *
  1053. * TRUE -- The copy operation succeeded.
  1054. *
  1055. * FALSE -- The operation failed. Extended error status is available
  1056. * using GetLastError.
  1057. *
  1058. ****************************************************************************/
  1059. BOOL
  1060. _CopyStringA( LPSTR pString,
  1061. LPWSTR * ppBuffer,
  1062. DWORD * pBytesReturned )
  1063. {
  1064. ULONG DataLength;
  1065. BOOL rc = TRUE;
  1066. /*
  1067. * If original string is NULL, just make copy NULL. KLB 11-03-97
  1068. */
  1069. if ( pString == NULL ) {
  1070. *ppBuffer = NULL;
  1071. if ( pBytesReturned != NULL ) {
  1072. *pBytesReturned = 0;
  1073. }
  1074. goto done;
  1075. }
  1076. DataLength = (strlen( pString ) + 1) * sizeof(WCHAR);
  1077. *ppBuffer = LocalAlloc( LPTR, DataLength );
  1078. if ( *ppBuffer == NULL ) {
  1079. rc = FALSE;
  1080. goto done;
  1081. }
  1082. if ( pBytesReturned != NULL ) {
  1083. *pBytesReturned = DataLength;
  1084. }
  1085. AnsiToUnicode( *ppBuffer, DataLength, pString );
  1086. done:
  1087. return( rc );
  1088. }
  1089. /****************************************************************************
  1090. *
  1091. * ValidateCopyUnicodeToUnicode
  1092. *
  1093. * Determines if the source unicode character string is valid and if so,
  1094. * copies it to the destination.
  1095. *
  1096. * ENTRY:
  1097. * pSourceW (input)
  1098. * pointer to a null terminated string.
  1099. * MaxLength (input)
  1100. * The maximum allowed length (in characters).
  1101. * pDestW (input)
  1102. * The destination where pSourceW is copied.
  1103. * EXIT:
  1104. * Returns TRUE if successful, otherwise FALSE.
  1105. *
  1106. ****************************************************************************/
  1107. BOOL
  1108. ValidateCopyUnicodeToUnicode(LPWSTR pSourceW, DWORD MaxLength, LPWSTR pDestW)
  1109. {
  1110. DWORD Length;
  1111. if ( wcslen(pSourceW) > MaxLength ) {
  1112. return(FALSE);
  1113. }
  1114. wcscpy(pDestW,pSourceW);
  1115. return(TRUE);
  1116. }
  1117. /****************************************************************************
  1118. *
  1119. * ValidateCopyAnsiToUnicode
  1120. *
  1121. * Determines if the source ANSI character string is valid and if so,
  1122. * converts and copies it to the unicode destination.
  1123. *
  1124. * ENTRY:
  1125. * pSourceA (input)
  1126. * pointer to a null terminated ANSI string.
  1127. * MaxLength (input)
  1128. * The maximum allowed length (in characters).
  1129. * pDestW (input)
  1130. * The destination where pSourceA is copied.
  1131. * EXIT:
  1132. * Returns TRUE if successful, otherwise FALSE.
  1133. *
  1134. ****************************************************************************/
  1135. BOOL
  1136. ValidateCopyAnsiToUnicode(LPSTR pSourceA, DWORD MaxLength, LPWSTR pDestW)
  1137. {
  1138. UINT Length;
  1139. DWORD DataLength;
  1140. if ( (Length = strlen(pSourceA)) > MaxLength ) {
  1141. return(FALSE);
  1142. }
  1143. DataLength = (Length+1) * sizeof(WCHAR);
  1144. AnsiToUnicode(pDestW,DataLength,pSourceA);
  1145. return(TRUE);
  1146. }
  1147. /****************************************************************************
  1148. *
  1149. * WTSRegisterSessionNotification
  1150. *
  1151. * Register a window handle for console notification
  1152. * Console notification, are messages sent when console session switch occurs
  1153. *
  1154. * ENTRY:
  1155. * hWnd (input)
  1156. * Window handle to be registered.
  1157. * dwFlags (input)
  1158. * value must be NOTIFY_FOR_THIS_SESSION
  1159. * EXIT:
  1160. * Returns TRUE if successful, otherwise FALSE. Sets LastError
  1161. *
  1162. ****************************************************************************/
  1163. BOOL WINAPI
  1164. WTSRegisterSessionNotification (HWND hWnd, DWORD dwFlags)
  1165. {
  1166. DWORD dwProcId;
  1167. HMODULE User32DllHandle = NULL ;
  1168. //
  1169. // make sure that window handle is valid
  1170. //
  1171. if (!IsWindow(hWnd))
  1172. {
  1173. SetLastError(ERROR_INVALID_PARAMETER);
  1174. goto error ;
  1175. }
  1176. GetWindowThreadProcessId(hWnd, &dwProcId);
  1177. if (dwProcId != GetCurrentProcessId())
  1178. {
  1179. SetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
  1180. goto error ;
  1181. }
  1182. if (dwFlags != NOTIFY_FOR_THIS_SESSION && dwFlags != NOTIFY_FOR_ALL_SESSIONS)
  1183. {
  1184. SetLastError(ERROR_INVALID_PARAMETER);
  1185. goto error ;
  1186. }
  1187. return WinStationRegisterConsoleNotification (WTS_CURRENT_SERVER_HANDLE, hWnd, dwFlags);
  1188. // -------------------------------- Handle Errors and return FALSE -----------------------
  1189. error :
  1190. return FALSE ;
  1191. }
  1192. /****************************************************************************
  1193. *
  1194. * WTSUnRegisterSessionNotification
  1195. *
  1196. * UnRegister a window handle for console notification
  1197. * Console notification, are messages sent when console session switch occurs
  1198. *
  1199. * ENTRY:
  1200. * dwFlags (input)
  1201. * NOTIFY_FOR_THIS_SESSION
  1202. * EXIT:
  1203. * Returns TRUE if successful, otherwise FALSE. Sets LastError
  1204. *
  1205. ****************************************************************************/
  1206. BOOL WINAPI
  1207. WTSUnRegisterSessionNotification (HWND hWnd)
  1208. {
  1209. DWORD dwProcId;
  1210. HMODULE User32DllHandle = NULL ;
  1211. //
  1212. // make sure that window handle is valid
  1213. //
  1214. if (!IsWindow(hWnd))
  1215. {
  1216. SetLastError(ERROR_INVALID_PARAMETER);
  1217. goto error ;
  1218. }
  1219. GetWindowThreadProcessId(hWnd, &dwProcId);
  1220. if (dwProcId != GetCurrentProcessId())
  1221. {
  1222. SetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
  1223. goto error ;
  1224. }
  1225. return WinStationUnRegisterConsoleNotification (WTS_CURRENT_SERVER_HANDLE, hWnd);
  1226. // -------------------------------- Handle Errors and return FALSE -----------------------
  1227. error :
  1228. return FALSE ;
  1229. }