Source code of Windows XP (NT5)
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.

1507 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. if ( pWSConfig )
  582. LocalFree( pWSConfig );
  583. if ( pWSInfo )
  584. LocalFree( pWSInfo );
  585. if ( pWSClient )
  586. LocalFree( pWSClient );
  587. return( fSuccess );
  588. /*=============================================================================
  589. == Error return
  590. =============================================================================*/
  591. badquery:
  592. return( FALSE );
  593. no_memory:
  594. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  595. return( FALSE );
  596. }
  597. /****************************************************************************
  598. *
  599. * WTSQuerySessionInformationA (ANSI)
  600. *
  601. * Query information for the specified session and server
  602. *
  603. * ENTRY:
  604. *
  605. * see WTSQuerySessionInformationW
  606. *
  607. * EXIT:
  608. *
  609. * TRUE -- The query operation succeeded.
  610. *
  611. * FALSE -- The operation failed. Extended error status is available
  612. * using GetLastError.
  613. *
  614. ****************************************************************************/
  615. BOOL
  616. WINAPI
  617. WTSQuerySessionInformationA(
  618. IN HANDLE hServer,
  619. IN DWORD SessionId,
  620. IN WTS_INFO_CLASS WTSInfoClass,
  621. OUT LPSTR * ppBuffer,
  622. OUT DWORD * pBytesReturned
  623. )
  624. {
  625. LPWSTR pBufferW;
  626. DWORD BytesReturned;
  627. DWORD DataLength;
  628. if (!ppBuffer || !pBytesReturned) {
  629. SetLastError(ERROR_INVALID_USER_BUFFER);
  630. return FALSE;
  631. }
  632. /*
  633. * Query the data
  634. */
  635. if ( !WTSQuerySessionInformationW( hServer,
  636. SessionId,
  637. WTSInfoClass,
  638. &pBufferW,
  639. &BytesReturned ) ) {
  640. return( FALSE );
  641. }
  642. switch ( WTSInfoClass ) {
  643. case WTSSessionId :
  644. case WTSConnectState :
  645. case WTSClientBuildNumber :
  646. case WTSClientProductId :
  647. case WTSClientHardwareId :
  648. case WTSClientAddress :
  649. case WTSClientDisplay :
  650. case WTSClientProtocolType:
  651. /*
  652. * Non-String Data - just return
  653. */
  654. *ppBuffer = (LPSTR) pBufferW;
  655. if ( pBytesReturned ) {
  656. *pBytesReturned = BytesReturned;
  657. }
  658. break;
  659. case WTSInitialProgram :
  660. case WTSWorkingDirectory :
  661. case WTSOEMId :
  662. case WTSWinStationName :
  663. case WTSUserName :
  664. case WTSDomainName :
  665. case WTSClientName :
  666. case WTSClientDirectory :
  667. case WTSApplicationName :
  668. /*
  669. * String Data - Convert to ANSI
  670. */
  671. DataLength = wcslen(pBufferW) + 1;
  672. *ppBuffer = LocalAlloc( LPTR, DataLength );
  673. if ( *ppBuffer == NULL ) {
  674. LocalFree( pBufferW );
  675. return( FALSE );
  676. }
  677. UnicodeToAnsi( *ppBuffer, DataLength, pBufferW );
  678. if ( pBytesReturned ) {
  679. *pBytesReturned = DataLength;
  680. }
  681. LocalFree( pBufferW );
  682. break;
  683. }
  684. return( TRUE );
  685. }
  686. /****************************************************************************
  687. *
  688. * WTSSetSessionInformationW (UNICODE)
  689. *
  690. * NOTE: THIS IS CURRENTLY JUST A STUB SO WE DON'T BREAK EXISTING PROGRAMS.
  691. *
  692. * Modify information for the specified session and server
  693. *
  694. * ENTRY:
  695. * hServer (input)
  696. * Terminal Server handle (or WTS_CURRENT_SERVER)
  697. * SessionId (input)
  698. * Server Session Id (or WTS_CURRENT_SESSION)
  699. * WTSInfoClass (input)
  700. * Specifies the type of information to modify for the specified
  701. * session
  702. * pData (input)
  703. * Pointer to the data used to modify the specified session information.
  704. * DataLength (output)
  705. * The length of the data provided.
  706. *
  707. * EXIT:
  708. *
  709. * TRUE -- The modify operation succeeded.
  710. *
  711. * FALSE -- The operation failed. Extended error status is available
  712. * using GetLastError.
  713. *
  714. ****************************************************************************/
  715. BOOL
  716. WINAPI
  717. WTSSetSessionInformationW(
  718. IN HANDLE hServer,
  719. IN DWORD SessionId,
  720. IN WTS_INFO_CLASS WTSInfoClass,
  721. IN PVOID pData,
  722. IN DWORD DataLength
  723. )
  724. {
  725. return( TRUE );
  726. }
  727. /****************************************************************************
  728. *
  729. * WTSSetSessionInformationA (ANSI)
  730. *
  731. * NOTE: THIS IS CURRENTLY JUST A STUB SO WE DON'T BREAK EXISTING PROGRAMS.
  732. *
  733. * Modify information for the specified session and server
  734. *
  735. * ENTRY:
  736. *
  737. * see WTSSetSessionInformationW
  738. *
  739. * EXIT:
  740. *
  741. * TRUE -- The query operation succeeded.
  742. *
  743. * FALSE -- The operation failed. Extended error status is available
  744. * using GetLastError.
  745. *
  746. ****************************************************************************/
  747. BOOL
  748. WINAPI
  749. WTSSetSessionInformationA(
  750. IN HANDLE hServer,
  751. IN DWORD SessionId,
  752. IN WTS_INFO_CLASS WTSInfoClass,
  753. IN PVOID pData,
  754. IN DWORD DataLength
  755. )
  756. {
  757. return( TRUE );
  758. }
  759. /****************************************************************************
  760. *
  761. * WTSSendMessageW (UNICODE)
  762. *
  763. * Send a message box to the specified session
  764. *
  765. * ENTRY:
  766. * hServer (input)
  767. * Terminal Server handle (or WTS_CURRENT_SERVER)
  768. * SessionId (input)
  769. * Server Session Id (or WTS_CURRENT_SESSION)
  770. * pTitle (input)
  771. * Pointer to title for message box to display.
  772. * TitleLength (input)
  773. * Length of title to display in bytes.
  774. * pMessage (input)
  775. * Pointer to message to display.
  776. * MessageLength (input)
  777. * Length of message in bytes to display at the specified window station.
  778. * Style (input)
  779. * Standard Windows MessageBox() style parameter.
  780. * Timeout (input)
  781. * Response timeout in seconds. If message is not responded to in
  782. * Timeout seconds then a response code of IDTIMEOUT (cwin.h) is
  783. * returned to signify the message timed out.
  784. * pResponse (output)
  785. * Address to return selected response. Valid only when bWait is set.
  786. * bWait (input)
  787. * Wait for the response
  788. *
  789. * EXIT:
  790. *
  791. * TRUE -- The operation succeeded.
  792. *
  793. * FALSE -- The operation failed. Extended error status is available
  794. * using GetLastError.
  795. *
  796. ****************************************************************************/
  797. BOOL
  798. WINAPI
  799. WTSSendMessageW(
  800. IN HANDLE hServer,
  801. IN DWORD SessionId,
  802. IN LPWSTR pTitle,
  803. IN DWORD TitleLength,
  804. IN LPWSTR pMessage,
  805. IN DWORD MessageLength,
  806. IN DWORD Style,
  807. IN DWORD Timeout,
  808. OUT DWORD * pResponse,
  809. IN BOOL bWait
  810. )
  811. {
  812. if (!pTitle ||
  813. !pMessage ||
  814. !pResponse
  815. ) {
  816. SetLastError(ERROR_INVALID_PARAMETER);
  817. return FALSE;
  818. }
  819. return( WinStationSendMessageW( hServer,
  820. SessionId,
  821. pTitle,
  822. TitleLength,
  823. pMessage,
  824. MessageLength,
  825. Style,
  826. Timeout,
  827. pResponse,
  828. (BOOLEAN) !bWait ) );
  829. }
  830. /****************************************************************************
  831. *
  832. * WTSSendMessageA (ANSI)
  833. *
  834. * Send a message box to the specified session
  835. *
  836. * ENTRY:
  837. *
  838. * see WTSSendMessageW
  839. *
  840. * EXIT:
  841. *
  842. * TRUE -- The operation succeeded.
  843. *
  844. * FALSE -- The operation failed. Extended error status is available
  845. * using GetLastError.
  846. *
  847. ****************************************************************************/
  848. BOOL
  849. WINAPI
  850. WTSSendMessageA(
  851. IN HANDLE hServer,
  852. IN DWORD SessionId,
  853. IN LPSTR pTitle,
  854. IN DWORD TitleLength,
  855. IN LPSTR pMessage,
  856. IN DWORD MessageLength,
  857. IN DWORD Style,
  858. IN DWORD Timeout,
  859. OUT DWORD * pResponse,
  860. IN BOOL bWait
  861. )
  862. {
  863. if (!pTitle ||
  864. !pMessage ||
  865. !pResponse
  866. ) {
  867. SetLastError(ERROR_INVALID_PARAMETER);
  868. return FALSE;
  869. }
  870. return( WinStationSendMessageA( hServer,
  871. SessionId,
  872. pTitle,
  873. TitleLength,
  874. pMessage,
  875. MessageLength,
  876. Style,
  877. Timeout,
  878. pResponse,
  879. (BOOLEAN) !bWait ) );
  880. }
  881. /****************************************************************************
  882. *
  883. * WTSDisconnectSession
  884. *
  885. * Disconnect the specified session
  886. *
  887. * ENTRY:
  888. * hServer (input)
  889. * Terminal Server handle (or WTS_CURRENT_SERVER)
  890. * SessionId (input)
  891. * Server Session Id (or WTS_CURRENT_SESSION)
  892. * bWait (input)
  893. * Wait for the operation to complete
  894. *
  895. * EXIT:
  896. *
  897. * TRUE -- The operation succeeded.
  898. *
  899. * FALSE -- The operation failed. Extended error status is available
  900. * using GetLastError.
  901. *
  902. ****************************************************************************/
  903. BOOL
  904. WINAPI
  905. WTSDisconnectSession(
  906. IN HANDLE hServer,
  907. IN DWORD SessionId,
  908. IN BOOL bWait
  909. )
  910. {
  911. return( WinStationDisconnect( hServer, SessionId, (BOOLEAN) bWait ) );
  912. }
  913. /****************************************************************************
  914. *
  915. * WTSLogoffSession
  916. *
  917. * Logoff the specified session
  918. *
  919. * ENTRY:
  920. * hServer (input)
  921. * Terminal Server handle (or WTS_CURRENT_SERVER)
  922. * SessionId (input)
  923. * Server Session Id (or WTS_CURRENT_SESSION)
  924. * bWait (input)
  925. * Wait for the operation to complete
  926. *
  927. * EXIT:
  928. *
  929. * TRUE -- The operation succeeded.
  930. *
  931. * FALSE -- The operation failed. Extended error status is available
  932. * using GetLastError.
  933. *
  934. ****************************************************************************/
  935. BOOL
  936. WINAPI
  937. WTSLogoffSession(
  938. IN HANDLE hServer,
  939. IN DWORD SessionId,
  940. IN BOOL bWait
  941. )
  942. {
  943. return( WinStationReset( hServer, SessionId, (BOOLEAN) bWait ) );
  944. }
  945. /****************************************************************************
  946. *
  947. * _CopyData
  948. *
  949. * Allocate buffer and copy data into it
  950. *
  951. * ENTRY:
  952. * pData (input)
  953. * pointer to data to copy
  954. * DataLength (input)
  955. * length of data to copy
  956. * ppBuffer (output)
  957. * Points to the address of a variable to receive the copied data
  958. * pBytesReturned (output)
  959. * An optional parameter that if specified, receives the number of
  960. * bytes returned.
  961. *
  962. * EXIT:
  963. *
  964. * TRUE -- The copy operation succeeded.
  965. *
  966. * FALSE -- The operation failed. Extended error status is available
  967. * using GetLastError.
  968. *
  969. ****************************************************************************/
  970. BOOL
  971. _CopyData( PVOID pData,
  972. ULONG DataLength,
  973. LPWSTR * ppBuffer,
  974. DWORD * pBytesReturned )
  975. {
  976. *ppBuffer = LocalAlloc( LPTR, DataLength );
  977. if ( *ppBuffer == NULL ) {
  978. return( FALSE );
  979. }
  980. if ( pBytesReturned != NULL ) {
  981. *pBytesReturned = DataLength;
  982. }
  983. memcpy( *ppBuffer, pData, DataLength );
  984. return( TRUE );
  985. }
  986. /****************************************************************************
  987. *
  988. * _CopyStringW
  989. *
  990. * Allocate a buffer for a unicode string and copy unicode string into it
  991. *
  992. * ENTRY:
  993. * pString (input)
  994. * pointer to unicode string to copy
  995. * ppBuffer (output)
  996. * Points to the address of a variable to receive the copied data
  997. * pBytesReturned (output)
  998. * An optional parameter that if specified, receives the number of
  999. * bytes returned.
  1000. *
  1001. * EXIT:
  1002. *
  1003. * TRUE -- The copy operation succeeded.
  1004. *
  1005. * FALSE -- The operation failed. Extended error status is available
  1006. * using GetLastError.
  1007. *
  1008. ****************************************************************************/
  1009. BOOL
  1010. _CopyStringW( LPWSTR pString,
  1011. LPWSTR * ppBuffer,
  1012. DWORD * pBytesReturned )
  1013. {
  1014. ULONG DataLength;
  1015. BOOL rc = TRUE;
  1016. /*
  1017. * If original string is NULL, just make copy NULL. KLB 11-03-97
  1018. */
  1019. if ( pString == NULL ) {
  1020. *ppBuffer = NULL;
  1021. if ( pBytesReturned != NULL ) {
  1022. *pBytesReturned = 0;
  1023. }
  1024. goto done;
  1025. }
  1026. DataLength = (wcslen( pString ) + 1) * sizeof(WCHAR);
  1027. *ppBuffer = LocalAlloc( LPTR, DataLength );
  1028. if ( *ppBuffer == NULL ) {
  1029. rc = FALSE;
  1030. goto done;
  1031. }
  1032. if ( pBytesReturned != NULL ) {
  1033. *pBytesReturned = DataLength;
  1034. }
  1035. memcpy( *ppBuffer, pString, DataLength );
  1036. done:
  1037. return( rc );
  1038. }
  1039. /****************************************************************************
  1040. *
  1041. * _CopyStringA
  1042. *
  1043. * Allocate a buffer for a unicode string and copy ansi string into it
  1044. *
  1045. * ENTRY:
  1046. * pString (input)
  1047. * pointer to ansi string to copy
  1048. * ppBuffer (output)
  1049. * Points to the address of a variable to receive the copied data
  1050. * pBytesReturned (output)
  1051. * An optional parameter that if specified, receives the number of
  1052. * bytes returned.
  1053. *
  1054. * EXIT:
  1055. *
  1056. * TRUE -- The copy operation succeeded.
  1057. *
  1058. * FALSE -- The operation failed. Extended error status is available
  1059. * using GetLastError.
  1060. *
  1061. ****************************************************************************/
  1062. BOOL
  1063. _CopyStringA( LPSTR pString,
  1064. LPWSTR * ppBuffer,
  1065. DWORD * pBytesReturned )
  1066. {
  1067. ULONG DataLength;
  1068. BOOL rc = TRUE;
  1069. /*
  1070. * If original string is NULL, just make copy NULL. KLB 11-03-97
  1071. */
  1072. if ( pString == NULL ) {
  1073. *ppBuffer = NULL;
  1074. if ( pBytesReturned != NULL ) {
  1075. *pBytesReturned = 0;
  1076. }
  1077. goto done;
  1078. }
  1079. DataLength = (strlen( pString ) + 1) * sizeof(WCHAR);
  1080. *ppBuffer = LocalAlloc( LPTR, DataLength );
  1081. if ( *ppBuffer == NULL ) {
  1082. rc = FALSE;
  1083. goto done;
  1084. }
  1085. if ( pBytesReturned != NULL ) {
  1086. *pBytesReturned = DataLength;
  1087. }
  1088. AnsiToUnicode( *ppBuffer, DataLength, pString );
  1089. done:
  1090. return( rc );
  1091. }
  1092. /****************************************************************************
  1093. *
  1094. * _CopyStringWtoA
  1095. *
  1096. * Allocate a buffer for an ansi string and copy unicode string into it
  1097. *
  1098. * ENTRY:
  1099. * pString (input)
  1100. * pointer to unicode string to copy
  1101. * ppBuffer (output)
  1102. * Points to the address of a variable to receive the copied data
  1103. * pBytesReturned (output)
  1104. * An optional parameter that if specified, receives the number of
  1105. * bytes returned.
  1106. *
  1107. * EXIT:
  1108. *
  1109. * TRUE -- The copy operation succeeded.
  1110. *
  1111. * FALSE -- The operation failed. Extended error status is available
  1112. * using GetLastError.
  1113. *
  1114. ****************************************************************************/
  1115. BOOL
  1116. _CopyStringWtoA( LPWSTR pString,
  1117. LPSTR * ppBuffer,
  1118. DWORD * pBytesReturned )
  1119. {
  1120. ULONG DataLength;
  1121. DataLength = (wcslen( pString ) + 1) * sizeof(CHAR);
  1122. *ppBuffer = LocalAlloc( LPTR, DataLength );
  1123. if ( *ppBuffer == NULL )
  1124. return( FALSE );
  1125. if ( pBytesReturned != NULL ) {
  1126. *pBytesReturned = DataLength;
  1127. }
  1128. UnicodeToAnsi( *ppBuffer, DataLength, pString );
  1129. return( TRUE );
  1130. }
  1131. /****************************************************************************
  1132. *
  1133. * ValidateCopyUnicodeToUnicode
  1134. *
  1135. * Determines if the source unicode character string is valid and if so,
  1136. * copies it to the destination.
  1137. *
  1138. * ENTRY:
  1139. * pSourceW (input)
  1140. * pointer to a null terminated string.
  1141. * MaxLength (input)
  1142. * The maximum allowed length (in characters).
  1143. * pDestW (input)
  1144. * The destination where pSourceW is copied.
  1145. * EXIT:
  1146. * Returns TRUE if successful, otherwise FALSE.
  1147. *
  1148. ****************************************************************************/
  1149. BOOL
  1150. ValidateCopyUnicodeToUnicode(LPWSTR pSourceW, DWORD MaxLength, LPWSTR pDestW)
  1151. {
  1152. DWORD Length;
  1153. if ( wcslen(pSourceW) > MaxLength ) {
  1154. return(FALSE);
  1155. }
  1156. wcscpy(pDestW,pSourceW);
  1157. return(TRUE);
  1158. }
  1159. /****************************************************************************
  1160. *
  1161. * ValidateCopyAnsiToUnicode
  1162. *
  1163. * Determines if the source ANSI character string is valid and if so,
  1164. * converts and copies it to the unicode destination.
  1165. *
  1166. * ENTRY:
  1167. * pSourceA (input)
  1168. * pointer to a null terminated ANSI string.
  1169. * MaxLength (input)
  1170. * The maximum allowed length (in characters).
  1171. * pDestW (input)
  1172. * The destination where pSourceA is copied.
  1173. * EXIT:
  1174. * Returns TRUE if successful, otherwise FALSE.
  1175. *
  1176. ****************************************************************************/
  1177. BOOL
  1178. ValidateCopyAnsiToUnicode(LPSTR pSourceA, DWORD MaxLength, LPWSTR pDestW)
  1179. {
  1180. UINT Length;
  1181. DWORD DataLength;
  1182. if ( (Length = strlen(pSourceA)) > MaxLength ) {
  1183. return(FALSE);
  1184. }
  1185. DataLength = (Length+1) * sizeof(WCHAR);
  1186. AnsiToUnicode(pDestW,DataLength,pSourceA);
  1187. return(TRUE);
  1188. }
  1189. /****************************************************************************
  1190. *
  1191. * WTSRegisterSessionNotification
  1192. *
  1193. * Register a window handle for console notification
  1194. * Console notification, are messages sent when console session switch occurs
  1195. *
  1196. * ENTRY:
  1197. * hWnd (input)
  1198. * Window handle to be registered.
  1199. * dwFlags (input)
  1200. * value must be NOTIFY_FOR_THIS_SESSION
  1201. * EXIT:
  1202. * Returns TRUE if successful, otherwise FALSE. Sets LastError
  1203. *
  1204. ****************************************************************************/
  1205. BOOL WINAPI
  1206. WTSRegisterSessionNotification (HWND hWnd, DWORD dwFlags)
  1207. {
  1208. DWORD dwProcId;
  1209. HMODULE User32DllHandle = NULL ;
  1210. //
  1211. // make sure that window handle is valid
  1212. //
  1213. if (!IsWindow(hWnd))
  1214. {
  1215. SetLastError(ERROR_INVALID_PARAMETER);
  1216. goto error ;
  1217. }
  1218. GetWindowThreadProcessId(hWnd, &dwProcId);
  1219. if (dwProcId != GetCurrentProcessId())
  1220. {
  1221. SetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
  1222. goto error ;
  1223. }
  1224. if (dwFlags != NOTIFY_FOR_THIS_SESSION && dwFlags != NOTIFY_FOR_ALL_SESSIONS)
  1225. {
  1226. SetLastError(ERROR_INVALID_PARAMETER);
  1227. goto error ;
  1228. }
  1229. return WinStationRegisterConsoleNotification (WTS_CURRENT_SERVER_HANDLE, hWnd, dwFlags);
  1230. // -------------------------------- Handle Errors and return FALSE -----------------------
  1231. error :
  1232. return FALSE ;
  1233. }
  1234. /****************************************************************************
  1235. *
  1236. * WTSUnRegisterSessionNotification
  1237. *
  1238. * UnRegister a window handle for console notification
  1239. * Console notification, are messages sent when console session switch occurs
  1240. *
  1241. * ENTRY:
  1242. * dwFlags (input)
  1243. * NOTIFY_FOR_THIS_SESSION
  1244. * EXIT:
  1245. * Returns TRUE if successful, otherwise FALSE. Sets LastError
  1246. *
  1247. ****************************************************************************/
  1248. BOOL WINAPI
  1249. WTSUnRegisterSessionNotification (HWND hWnd)
  1250. {
  1251. DWORD dwProcId;
  1252. HMODULE User32DllHandle = NULL ;
  1253. //
  1254. // make sure that window handle is valid
  1255. //
  1256. if (!IsWindow(hWnd))
  1257. {
  1258. SetLastError(ERROR_INVALID_PARAMETER);
  1259. goto error ;
  1260. }
  1261. GetWindowThreadProcessId(hWnd, &dwProcId);
  1262. if (dwProcId != GetCurrentProcessId())
  1263. {
  1264. SetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
  1265. goto error ;
  1266. }
  1267. return WinStationUnRegisterConsoleNotification (WTS_CURRENT_SERVER_HANDLE, hWnd);
  1268. // -------------------------------- Handle Errors and return FALSE -----------------------
  1269. error :
  1270. return FALSE ;
  1271. }